subconscious-cli 4.0.17 → 4.1.0-windows.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +125 -7
  2. package/bin/agents.js +10 -1
  3. package/bin/auth.js +15 -5
  4. package/bin/cli.js +69 -0
  5. package/bin/native/subc-tui-darwin-amd64 +0 -0
  6. package/bin/native/subc-tui-darwin-arm64 +0 -0
  7. package/bin/native/subc-tui-linux-amd64 +0 -0
  8. package/bin/native/subc-tui-linux-arm64 +0 -0
  9. package/bin/native/subc-tui-windows-amd64.exe +0 -0
  10. package/bin/native/subc-tui-windows-arm64.exe +0 -0
  11. package/bin/profiles.js +60 -16
  12. package/bin/registry.generated.json +14 -4
  13. package/bin/runbook/claude-code/install.sh +4 -4
  14. package/bin/runbook/claude-code/run.sh +3 -3
  15. package/bin/runbook/codex/run.sh +3 -2
  16. package/bin/runbook/copilot/install.sh +6 -5
  17. package/bin/runbook/cursor/install.sh +3 -2
  18. package/bin/runbook/deepseek-harness/run.sh +3 -2
  19. package/bin/runbook/opencode/install.sh +6 -5
  20. package/bin/runbook/opencode/run.sh +3 -2
  21. package/bin/runbook/pi/install.sh +4 -3
  22. package/bin/runbook/pi/run.sh +1 -1
  23. package/bin/runbook/subconscious-code/run.sh +1 -1
  24. package/bin/sessions.js +622 -0
  25. package/bin/tui.js +27 -1
  26. package/bin/update-check.js +90 -17
  27. package/bin/upgrade.js +27 -11
  28. package/bin/usage.js +229 -0
  29. package/bin/windows/agents.js +87 -0
  30. package/bin/windows/claude.js +71 -0
  31. package/bin/windows/common.js +58 -0
  32. package/bin/windows/hook.cjs +71 -0
  33. package/bin/windows/install.js +97 -0
  34. package/bin/windows/launch.js +97 -0
  35. package/bin/windows/pi-compaction.ts +29 -0
  36. package/bin/windows/process.js +157 -0
  37. package/bin/windows/setup.js +168 -0
  38. package/package.json +2 -1
package/README.md CHANGED
@@ -34,8 +34,9 @@ subc <agent> uninstall
34
34
 
35
35
  Running `subc` with no arguments in a terminal opens the native Go TUI. Use
36
36
  the arrow keys and Enter to launch agents or manage the active profile, `p` to
37
- switch profiles, and `q` to quit. The menu includes dedicated **Create profile**,
38
- **Set default model**, **Set subagent model**, and **Update base URL** actions.
37
+ switch profiles, and `q` to quit. The menu includes dedicated **Usage**,
38
+ **Create profile**, **Coding sessions**, **Set default model**, **Set subagent model**,
39
+ **Update base URL**, and **Update platform URL** actions.
39
40
  Model and URL changes are validated and saved to the active profile without
40
41
  leaving the TUI.
41
42
  `subc help` and `subc --help` continue to print script-friendly command help.
@@ -75,6 +76,75 @@ subc pi
75
76
  subc dsh
76
77
  ```
77
78
 
79
+ ## Native Windows support
80
+
81
+ Windows has its own implementation in `cli/bin/windows/`, selected only when
82
+ Node runs on Windows. macOS/Linux continue to use the existing, unchanged shell
83
+ runbooks. WSL continues to use the Linux implementation.
84
+
85
+ Use Node.js 22 or 24 and Windows PowerShell 5.1+ (included with Windows), from either
86
+ PowerShell or Command Prompt. The Windows CLI integrations do not require Bash,
87
+ `jq`, `curl`, or WSL. The agents themselves must support your Windows version;
88
+ their own dependencies still apply.
89
+
90
+ ```powershell
91
+ npm.cmd install -g subconscious-cli@windows
92
+ subc.cmd login
93
+ subc.cmd claude
94
+ subc codex
95
+ subc opencode
96
+ subc dsh
97
+ subc cursor install
98
+ subc copilot install
99
+ subc pi
100
+ subc config edit notepad
101
+ ```
102
+
103
+ This is an opt-in Windows preview; `@latest` remains the stable release. Update
104
+ the preview with `npm.cmd install -g subconscious-cli@windows`.
105
+
106
+ If PowerShell's execution policy blocks npm-generated `.ps1` entry points, use
107
+ `npm.cmd` and `subc.cmd` or run the same commands in Command Prompt. No policy
108
+ change is required. Pi must already be installed; other terminal agents offer
109
+ their Windows installer when missing in an interactive terminal.
110
+
111
+ Native executables and standard npm `.cmd` shims are supported. The launcher
112
+ invokes the underlying executable or Node entry point directly, preserving
113
+ JSON, quotes, Unicode, and multiline arguments. It checks the user's `.local\bin`,
114
+ npm globals, WinGet links, and the system-profile `.local\bin` location reported
115
+ by some elevated Claude installations. It does not change your global PATH.
116
+ Custom batch wrappers are rejected with guidance to use a native executable or
117
+ standard npm package.
118
+
119
+ Login, saved profiles, model discovery, session browsing/resume, self-update,
120
+ and the native TUI use Windows paths and processes. Profile editing defaults to
121
+ Notepad, honors `VISUAL`/`EDITOR`, and supports `code`/`code-insiders` with `--wait`.
122
+ The existing profile location remains `%USERPROFILE%\.subconscious`.
123
+
124
+ Cursor, Copilot, Codex, and Pi setup use native JSON merges and Node hooks. Other
125
+ providers and hooks are preserved; malformed configuration is left unchanged.
126
+ Hook credentials are stored in `subconscious-windows.json` within the agent's
127
+ user directory; treat that file as a secret. Copilot's model provider still uses
128
+ VS Code's secret store and prompts for its key. Its configuration goes under
129
+ `%APPDATA%\Code\User` (or Code - Insiders/VSCodium). Rerun install after moving
130
+ your Node installation, because hooks record the absolute Node executable path.
131
+
132
+ To install the native x64 `sc.exe` preview:
133
+
134
+ ```powershell
135
+ $env:SC_CODE_VERSION = '0.1.4-windows.0'
136
+ subc.cmd sc install
137
+ subc.cmd sc
138
+ ```
139
+
140
+ The installer requires the selected release's Windows asset and SHA-256
141
+ checksum; it reports a clear error if unavailable and never downloads a Unix
142
+ binary as a fallback. Windows ARM64 binaries are not published in this preview.
143
+
144
+ Run `npm run test:windows` from `cli/` for the separate Windows suite. The
145
+ Windows CI job also builds/tests the Go TUI. Existing Unix tests and runbooks
146
+ remain separate and unchanged.
147
+
78
148
  ## Supported agents
79
149
 
80
150
  The packaged integrations live in `cli/bin/runbook`.
@@ -90,6 +160,35 @@ The packaged integrations live in `cli/bin/runbook`.
90
160
  | `subc pi` | Refresh the Pi provider from the live catalog, then launch |
91
161
  | `subc dsh` | Launch the DeepSeek Harness Web UI with a temporary provider populated from the live catalog |
92
162
 
163
+ ## Sessions and cross-harness handoff
164
+
165
+ Run `subc` and choose **Coding sessions**, or list the same local catalog from
166
+ the shell:
167
+
168
+ ```bash
169
+ subc sessions
170
+ subc sessions resume claude:SESSION_ID
171
+ subc sessions resume claude:SESSION_ID --harness codex
172
+ subc sessions resume codex:SESSION_ID --harness opencode
173
+ ```
174
+
175
+ The catalog discovers recent sessions written locally by Claude Code, Codex,
176
+ OpenCode, Pi, and Subconscious Code. It shows each session's originating
177
+ harness, title, last activity, project directory, and model when the harness
178
+ records one. Selecting the original harness uses its native resume mechanism.
179
+
180
+ Selecting Claude Code, Codex, OpenCode, or Pi as a different destination starts
181
+ a new session in the original project directory with a portable handoff. The
182
+ handoff is limited to the newest 24 user/assistant text messages and 24,000
183
+ characters. Tool payloads, tool results, system prompts, and hidden reasoning
184
+ are not copied. Source transcripts remain owned by their original harness and
185
+ are never rewritten.
186
+
187
+ Cursor and GitHub Copilot sessions are not listed because their IDE-owned
188
+ conversation stores do not expose a stable local resume interface. A session
189
+ whose local transcript is missing remains available for native resume but does
190
+ not offer cross-harness destinations.
191
+
93
192
  If Subconscious Code, Claude Code, Codex, OpenCode, or DeepSeek Harness is missing, an interactive terminal offers
94
193
  to install it before launching. Pi refreshes its Subconscious provider on every
95
194
  `subc pi` launch while preserving all other providers in `models.json`; its
@@ -161,7 +260,7 @@ DeepSeek Harness context and output settings used by the packaged runbook script
161
260
  subc config # list every profile and its file path
162
261
  subc -p staging config create # create a profile with default settings
163
262
  subc -p staging config # print that path and env file
164
- subc -p staging config --model subconscious/glm-5.2
263
+ subc -p staging config --model subconscious/glm-5.3-marathon
165
264
  subc -p staging config --model UNSET
166
265
  subc -p staging config --subagent-model subconscious/deepseek-v4-flash-marathon
167
266
  subc -p staging config --subagent-model UNSET
@@ -197,7 +296,7 @@ Named profiles work like AWS CLI profiles:
197
296
  subc -p staging config \
198
297
  --gateway-url https://staging.example \
199
298
  --api-key sk-staging-... \
200
- --model subconscious/glm-5.2
299
+ --model subconscious/glm-5.3-marathon
201
300
 
202
301
  subc -p staging claude
203
302
  subc -p staging cursor install
@@ -216,7 +315,8 @@ that request fails, it falls back to the public `/v1/models` fleet list, then
216
315
  to the models packaged with the CLI:
217
316
 
218
317
  ```text
219
- subconscious/glm-5.2 (default)
318
+ subconscious/glm-5.3-marathon (default)
319
+ subconscious/glm-5.2
220
320
  subconscious/tim-qwen3.6-27b
221
321
  subconscious/deepseek-v4-flash-marathon
222
322
  ```
@@ -225,10 +325,10 @@ Select a model per run, save it in the current profile, or override it through
225
325
  the environment:
226
326
 
227
327
  ```bash
228
- subc codex --model subconscious/glm-5.2
328
+ subc codex --model subconscious/glm-5.3-marathon
229
329
  subc config --model subconscious/deepseek-v4-flash-marathon
230
330
  subc config --subagent-model subconscious/tim-qwen3.6-27b
231
- export SUBCONSCIOUS_MODEL=subconscious/glm-5.2
331
+ export SUBCONSCIOUS_MODEL=subconscious/glm-5.3-marathon
232
332
  ```
233
333
 
234
334
  Every launch and install fetches the same live catalog without caching. Codex,
@@ -275,6 +375,9 @@ also maintains `~/.subconscious/config.json`.
275
375
  subc login
276
376
  subc update-key sk-new-key-...
277
377
  subc update-url https://api.subconscious.dev
378
+ subc update-platform-url https://platform.subconscious.dev
379
+ subc usage
380
+ subc usage --json
278
381
  subc whoami
279
382
  subc logout
280
383
  ```
@@ -305,6 +408,21 @@ updated automatically as well.
305
408
  `SUBCONSCIOUS_BASE_URL` continues to take precedence when set. A configured
306
409
  `CLAUDE_GATEWAY_URL` remains a Claude-specific override.
307
410
 
411
+ `subc update-platform-url <platform-url>` validates the URL and saves
412
+ `PLATFORM_URL` in the active profile. Login, `whoami`, and `usage` call this
413
+ host. Production defaults to `https://platform.subconscious.dev`:
414
+
415
+ ```bash
416
+ subc update-platform-url https://platform.subconscious.dev
417
+ subc config --platform-url http://localhost:3000
418
+ ```
419
+
420
+ `SUBCONSCIOUS_URL` overrides the saved profile value for local development.
421
+
422
+ `subc usage` fetches billing mode, daily token allowance, credit balance,
423
+ overage, and per-model consumption from `GET /api/v1/usage` on the resolved
424
+ platform host. Pass `--json` for machine-readable output.
425
+
308
426
  `SUBCONSCIOUS_API_KEY` takes precedence over profile and saved config keys,
309
427
  which is useful for CI and temporary sessions. `subc logout` clears the
310
428
  selected profile's shared key while preserving its non-secret runbook settings;
package/bin/agents.js CHANGED
@@ -19,6 +19,7 @@ import path from 'node:path';
19
19
  import readline from 'node:readline';
20
20
  import { fileURLToPath } from 'node:url';
21
21
  import { c } from './colors.js';
22
+ import { runWindowsAgent } from './windows/agents.js';
22
23
  import { getApiKey } from './auth.js';
23
24
  import {
24
25
  isUnsetSetting,
@@ -170,7 +171,7 @@ const AGENT_HELP = {
170
171
  'Launches the native Subconscious coding agent with the selected profile gateway, credential, and model.',
171
172
  options: [
172
173
  ['help', 'Show this help'],
173
- ['install', 'Install the latest precompiled Linux or macOS release'],
174
+ ['install', process.platform === 'win32' ? 'Install a verified Windows release, when published upstream' : 'Install the latest precompiled Linux or macOS release'],
174
175
  ['--model MODEL', 'Override the profile model for this launch'],
175
176
  ['ARGS...', 'Pass arguments directly to Subconscious Code'],
176
177
  ],
@@ -976,6 +977,14 @@ export async function runAgent(agent, argv, options = {}) {
976
977
  return 0;
977
978
  }
978
979
 
980
+ if (process.platform === 'win32') {
981
+ return runWindowsAgent(agent, argv, {
982
+ profile, parseAgentAction, extractModel, requireApiKey,
983
+ resolvedModelsForLaunch, selectLaunchModel, runbookEnv,
984
+ minimumClaudeVersion: MIN_CLAUDE_CODE_VERSION, parseClaudeVersion, claudeVersionNeedsUpgrade,
985
+ });
986
+ }
987
+
979
988
  const parsed = parseAgentAction(agent, argv);
980
989
  if (parsed.action !== 'launch') {
981
990
  if (!agent.runbook?.setupScript) {
package/bin/auth.js CHANGED
@@ -18,6 +18,7 @@
18
18
  import http from 'node:http';
19
19
  import crypto from 'node:crypto';
20
20
  import { exec } from 'node:child_process';
21
+ import { openWindowsBrowser } from './windows/process.js';
21
22
  import fs from 'node:fs/promises';
22
23
  import os from 'node:os';
23
24
  import path from 'node:path';
@@ -34,9 +35,12 @@ const LEGACY_CONFIG_FILE = CONFIG_OVERRIDE
34
35
  // Defaults to the platform host. Developers set SUBCONSCIOUS_URL for local dev.
35
36
  export const DEFAULT_PLATFORM_URL = 'https://platform.subconscious.dev';
36
37
 
37
- export function getPlatformUrl() {
38
- const raw = process.env.SUBCONSCIOUS_URL?.trim() || DEFAULT_PLATFORM_URL;
39
- return raw.replace(/\/$/, '');
38
+ export function getPlatformUrl(profile) {
39
+ const fromEnv = process.env.SUBCONSCIOUS_URL?.trim();
40
+ if (fromEnv) return fromEnv.replace(/\/$/, '');
41
+ const fromProfile = profile?.values?.PLATFORM_URL?.trim();
42
+ if (fromProfile) return fromProfile.replace(/\/$/, '');
43
+ return DEFAULT_PLATFORM_URL;
40
44
  }
41
45
 
42
46
  // Login callback CORS. After the marketing/platform split, /cli/auth lives on
@@ -132,6 +136,12 @@ export function isLoginMissing(status) {
132
136
  // ── Browser opener ──────────────────────────────────────────────────────
133
137
 
134
138
  function openBrowser(url) {
139
+ if (process.platform === 'win32') {
140
+ void openWindowsBrowser(url).then(code => {
141
+ if (code) throw new Error('Browser could not be opened');
142
+ }).catch(() => console.log(`Please open this URL manually:\n\n ${url}\n`));
143
+ return;
144
+ }
135
145
  const cmd =
136
146
  process.platform === 'darwin'
137
147
  ? `open "${url}"`
@@ -323,7 +333,7 @@ export async function loginCommand(_argv = [], options = {}) {
323
333
  );
324
334
  console.log();
325
335
 
326
- const platformUrl = getPlatformUrl();
336
+ const platformUrl = getPlatformUrl(options.profile);
327
337
  const loginStatus = await probeLoginPage(platformUrl);
328
338
  if (isLoginMissing(loginStatus)) {
329
339
  printLoginUpgradeWarning();
@@ -459,7 +469,7 @@ export async function whoamiCommand(_argv = [], options = {}) {
459
469
 
460
470
  // Validate the key against the server; falls back to offline display if unreachable
461
471
  try {
462
- const res = await fetch(`${getPlatformUrl()}/api/cli/whoami`, {
472
+ const res = await fetch(`${getPlatformUrl(options.profile)}/api/cli/whoami`, {
463
473
  headers: { Authorization: `Bearer ${key}` },
464
474
  signal: AbortSignal.timeout(5000),
465
475
  });
package/bin/cli.js CHANGED
@@ -37,12 +37,15 @@ import {
37
37
  resolvedModelSetting,
38
38
  RUNBOOK_DEFAULTS,
39
39
  SUPPORTED_MODELS as PACKAGED_MODELS,
40
+ updatePlatformUrlCommand,
40
41
  updateUrlCommand,
41
42
  validateProfileName,
42
43
  } from './profiles.js';
43
44
  import { resolveModelCatalog } from './models.js';
44
45
  import { showUpdateNotice } from './update-check.js';
45
46
  import { runTui } from './tui.js';
47
+ import { sessionsCommand } from './sessions.js';
48
+ import { printUsageHelp, usageCommand } from './usage.js';
46
49
 
47
50
  function isHelpArg(arg) {
48
51
  return arg === 'help' || arg === '-h' || arg === '--help';
@@ -63,14 +66,19 @@ function printHelp() {
63
66
  ${c.cyan}login${c.reset} Authenticate and save your API key
64
67
  ${c.cyan}update-key${c.reset} Replace the selected profile's API key
65
68
  ${c.cyan}update-url${c.reset} Update the active profile's gateway URL automatically
69
+ ${c.cyan}update-platform-url${c.reset} Update the active profile's platform URL
66
70
  ${c.cyan}logout${c.reset} Remove saved credentials
67
71
  ${c.cyan}whoami${c.reset} Show current authentication status
72
+ ${c.cyan}usage${c.reset} Show billing, quota, and model usage
68
73
  ${c.cyan}upgrade${c.reset} Upgrade this CLI to the latest version
69
74
 
70
75
  ${c.bold}Profiles${c.reset}
71
76
  ${c.cyan}config${c.reset} List profiles, or show/edit one with ${c.dim}-p${c.reset}
72
77
  ${c.cyan}models${c.reset} List available Subconscious models
73
78
 
79
+ ${c.bold}Sessions${c.reset}
80
+ ${c.cyan}sessions${c.reset} Browse and resume local coding sessions across harnesses
81
+
74
82
  ${c.bold}Coding agents${c.reset}
75
83
  ${agents}
76
84
 
@@ -88,6 +96,10 @@ ${agents}
88
96
  ${c.dim}$${c.reset} subc config help
89
97
  ${c.dim}$${c.reset} subc -p staging config
90
98
  ${c.dim}$${c.reset} subc config edit vim
99
+ ${c.dim}$${c.reset} subc sessions
100
+ ${c.dim}$${c.reset} subc sessions resume claude:SESSION_ID --harness codex
101
+ ${c.dim}$${c.reset} subc usage
102
+ ${c.dim}$${c.reset} subc usage --json
91
103
  ${c.dim}$${c.reset} subc claude
92
104
  ${c.dim}$${c.reset} subc claude help
93
105
  ${c.dim}$${c.reset} subc cursor install
@@ -149,6 +161,22 @@ Usage:
149
161
  subc update-url help
150
162
 
151
163
  Update the active profile's gateway URL.
164
+ `,
165
+ 'update-platform-url': `
166
+ Usage:
167
+ subc update-platform-url <platform-url>
168
+ subc update-platform-url help
169
+
170
+ Update the active profile's platform URL for login, whoami, and usage.
171
+ `,
172
+ usage: `
173
+ Usage:
174
+ subc usage
175
+ subc -p NAME usage
176
+ subc usage --json
177
+ subc usage help
178
+
179
+ Show billing mode, daily token allowance, credit balance, and per-model usage.
152
180
  `,
153
181
  models: `
154
182
  Usage:
@@ -157,6 +185,17 @@ Usage:
157
185
 
158
186
  List available Subconscious models. The default is the profile MODEL,
159
187
  or the first live catalog model if MODEL is UNSET.
188
+ `,
189
+ sessions: `
190
+ Usage:
191
+ subc sessions
192
+ subc sessions resume <session-key>
193
+ subc sessions resume <session-key> --harness <claude|codex|opencode|pi>
194
+ subc sessions help
195
+
196
+ List locally stored sessions from supported coding harnesses. Resuming with the
197
+ original harness uses its native session. Choosing another harness starts a new
198
+ session with a bounded, text-only handoff from the source conversation.
160
199
  `,
161
200
  };
162
201
 
@@ -333,6 +372,17 @@ async function main() {
333
372
  return;
334
373
  }
335
374
 
375
+ if (command === 'sessions') {
376
+ if (isHelpArg(args[1])) {
377
+ console.log(COMMAND_HELP.sessions);
378
+ return;
379
+ }
380
+ const profile = await loadProfile(profileName);
381
+ requireNamedProfile(profile);
382
+ await sessionsCommand(args.slice(1), { profile });
383
+ return;
384
+ }
385
+
336
386
  if (command === 'upgrade') {
337
387
  if (isHelpArg(args[1])) {
338
388
  console.log(COMMAND_HELP.upgrade);
@@ -351,6 +401,25 @@ async function main() {
351
401
  return;
352
402
  }
353
403
 
404
+ if (command === 'update-platform-url') {
405
+ if (isHelpArg(args[1])) {
406
+ console.log(COMMAND_HELP['update-platform-url']);
407
+ return;
408
+ }
409
+ await updatePlatformUrlCommand(args.slice(1), { profileName });
410
+ return;
411
+ }
412
+
413
+ if (command === 'usage') {
414
+ if (isHelpArg(args[1])) {
415
+ printUsageHelp();
416
+ return;
417
+ }
418
+ const profile = await loadProfile(profileName);
419
+ await usageCommand(args.slice(1), { profile, profileName });
420
+ return;
421
+ }
422
+
354
423
  const agent = resolveAgent(command);
355
424
  if (agent) {
356
425
  const agentArgs = args.slice(1);
Binary file
Binary file
Binary file
Binary file
package/bin/profiles.js CHANGED
@@ -7,6 +7,7 @@
7
7
  */
8
8
 
9
9
  import { spawn, execFileSync } from 'node:child_process';
10
+ import { windowsEditor, runWindows } from './windows/process.js';
10
11
  import fs from 'node:fs/promises';
11
12
  import os from 'node:os';
12
13
  import path from 'node:path';
@@ -76,6 +77,12 @@ const SETTINGS = {
76
77
  type: 'url',
77
78
  required: true,
78
79
  },
80
+ PLATFORM_URL: {
81
+ key: 'PLATFORM_URL',
82
+ label: 'Platform URL',
83
+ description: 'Subconscious platform origin for login, whoami, and usage.',
84
+ type: 'url',
85
+ },
79
86
  API_KEY: {
80
87
  key: 'API_KEY',
81
88
  label: 'Shared API key',
@@ -652,7 +659,7 @@ export function validateSettingValue(setting, value) {
652
659
  return null;
653
660
  }
654
661
 
655
- const ALLOWED_EDITORS = new Set(['vim', 'nano']);
662
+ const ALLOWED_EDITORS = new Set(process.platform === 'win32' ? ['notepad', 'code', 'code-insiders', 'vim', 'nano'] : ['vim', 'nano']);
656
663
 
657
664
  function commandExists(bin) {
658
665
  try {
@@ -689,6 +696,12 @@ async function editProfile(profileName, requestedEditor) {
689
696
  }
690
697
 
691
698
  const profile = await ensureProfile(profileName);
699
+ if (process.platform === 'win32') {
700
+ const { command, args } = windowsEditor(requestedEditor);
701
+ const code = await runWindows(command, [...args, profile.path]);
702
+ if (code) process.exitCode = code;
703
+ return;
704
+ }
692
705
  const { cmd, args } = resolveEditor(requestedEditor);
693
706
  await new Promise((resolve, reject) => {
694
707
  const child = spawn(cmd, [...args, profile.path], { stdio: 'inherit' });
@@ -708,16 +721,16 @@ Usage:
708
721
  subc config
709
722
  subc config help
710
723
  subc -p NAME config
711
- subc config edit [vim|nano]
712
- subc -p NAME config edit [vim|nano]
724
+ subc config edit [${process.platform === 'win32' ? 'notepad|code|code-insiders|vim|nano' : 'vim|nano'}]
725
+ subc -p NAME config edit [${process.platform === 'win32' ? 'notepad|code|code-insiders|vim|nano' : 'vim|nano'}]
713
726
  subc config [show|path|list|create|delete]
714
- [--gateway-url URL] [--api-key KEY]
727
+ [--gateway-url URL] [--platform-url URL] [--api-key KEY]
715
728
  [--model MODEL|UNSET]
716
729
  [--subagent-model MODEL|UNSET]
717
730
 
718
731
  subc config List every profile and its file path
719
732
  subc -p NAME config Print that profile's path and env file
720
- subc config edit Open the selected profile in $VISUAL, $EDITOR, vim, or nano
733
+ subc config edit Open the selected profile in ${process.platform === 'win32' ? 'VISUAL, EDITOR, or Notepad' : '$VISUAL, $EDITOR, vim, or nano'}
721
734
  subc config edit vim Open the selected profile in vim
722
735
  subc config edit nano Open the selected profile in nano
723
736
  subc config path Print the selected profile path
@@ -757,6 +770,7 @@ export async function configCommand(argv, profileName = DEFAULT_PROFILE, options
757
770
  action = arg === 'interactive' ? 'edit' : arg;
758
771
  } else if (
759
772
  arg === '--gateway-url' ||
773
+ arg === '--platform-url' ||
760
774
  arg === '--api-key' ||
761
775
  arg === '--model' ||
762
776
  arg === '--subagent-model'
@@ -765,6 +779,7 @@ export async function configCommand(argv, profileName = DEFAULT_PROFILE, options
765
779
  if (!value) throw new Error(`${arg} requires a value`);
766
780
  const key = {
767
781
  '--gateway-url': 'GATEWAY_URL',
782
+ '--platform-url': 'PLATFORM_URL',
768
783
  '--api-key': 'API_KEY',
769
784
  '--model': 'MODEL',
770
785
  '--subagent-model': 'CLAUDE_CODE_SUBAGENT_MODEL',
@@ -784,7 +799,7 @@ export async function configCommand(argv, profileName = DEFAULT_PROFILE, options
784
799
  if (action === 'edit') {
785
800
  if (Object.keys(updates).length) {
786
801
  throw new Error(
787
- 'config edit cannot be combined with --gateway-url, --api-key, --model, or --subagent-model',
802
+ 'config edit cannot be combined with --gateway-url, --platform-url, --api-key, --model, or --subagent-model',
788
803
  );
789
804
  }
790
805
  await editProfile(profileName, editor);
@@ -855,28 +870,36 @@ export function modelsCommand(models = SUPPORTED_MODELS, options = {}) {
855
870
  console.log();
856
871
  }
857
872
 
858
- export async function updateUrlCommand(argv = [], options = {}) {
859
- if (argv.length !== 1 || !argv[0]?.trim()) {
860
- throw new Error('Usage: subc update-url <gateway-url>');
873
+ export function validateOriginUrl(rawUrl, label = 'URL') {
874
+ const normalized = String(rawUrl ?? '').trim().replace(/\/+$/, '');
875
+ if (!normalized) {
876
+ throw new Error(`${label} cannot be blank`);
861
877
  }
862
-
863
- const gatewayUrl = argv[0].trim().replace(/\/+$/, '');
864
878
  let parsed;
865
879
  try {
866
- parsed = new URL(gatewayUrl);
880
+ parsed = new URL(normalized);
867
881
  } catch {
868
- throw new Error('Gateway URL must be a valid http:// or https:// URL');
882
+ throw new Error(`${label} must be a valid http:// or https:// URL`);
869
883
  }
870
884
  if (!['http:', 'https:'].includes(parsed.protocol) || !parsed.hostname) {
871
- throw new Error('Gateway URL must be a valid http:// or https:// URL');
885
+ throw new Error(`${label} must be a valid http:// or https:// URL`);
872
886
  }
873
887
  if (parsed.username || parsed.password) {
874
- throw new Error('Gateway URL cannot contain embedded credentials');
888
+ throw new Error(`${label} cannot contain embedded credentials`);
875
889
  }
876
890
  if (parsed.search || parsed.hash) {
877
- throw new Error('Gateway URL cannot contain a query string or fragment');
891
+ throw new Error(`${label} cannot contain a query string or fragment`);
892
+ }
893
+ return normalized;
894
+ }
895
+
896
+ export async function updateUrlCommand(argv = [], options = {}) {
897
+ if (argv.length !== 1 || !argv[0]?.trim()) {
898
+ throw new Error('Usage: subc update-url <gateway-url>');
878
899
  }
879
900
 
901
+ const gatewayUrl = validateOriginUrl(argv[0], 'Gateway URL');
902
+
880
903
  const profileName = options.profileName || DEFAULT_PROFILE;
881
904
  const profile = await updateProfile(profileName, { GATEWAY_URL: gatewayUrl });
882
905
 
@@ -897,3 +920,24 @@ export async function updateUrlCommand(argv = [], options = {}) {
897
920
  }
898
921
  console.log();
899
922
  }
923
+
924
+ export async function updatePlatformUrlCommand(argv = [], options = {}) {
925
+ if (argv.length !== 1 || !argv[0]?.trim()) {
926
+ throw new Error('Usage: subc update-platform-url <platform-url>');
927
+ }
928
+
929
+ const platformUrl = validateOriginUrl(argv[0], 'Platform URL');
930
+
931
+ const profileName = options.profileName || DEFAULT_PROFILE;
932
+ const profile = await updateProfile(profileName, { PLATFORM_URL: platformUrl });
933
+
934
+ console.log(`\n ${c.green}${c.bold}✓ Platform URL updated.${c.reset}`);
935
+ console.log(` ${c.dim}Updated profile automatically: ${profile.path}${c.reset}`);
936
+ console.log(` ${c.dim}URL: ${platformUrl}${c.reset}`);
937
+ if (process.env.SUBCONSCIOUS_URL?.trim()) {
938
+ console.log(
939
+ `\n ${c.yellow}SUBCONSCIOUS_URL is set and will override this saved URL.${c.reset}`,
940
+ );
941
+ }
942
+ console.log();
943
+ }
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "_generated": "Source of truth: agents/registry.json. Do not edit by hand.",
3
3
  "defaults": {
4
- "model": "subconscious/glm-5.2",
4
+ "model": "subconscious/glm-5.3-marathon",
5
5
  "models": [
6
+ "subconscious/glm-5.3-marathon",
6
7
  "subconscious/glm-5.2",
7
8
  "subconscious/tim-qwen3.6-27b",
8
9
  "subconscious/deepseek-v4-flash-marathon"
@@ -34,7 +35,8 @@
34
35
  "bin": "sc",
35
36
  "install": {
36
37
  "darwin": "subc sc install",
37
- "linux": "subc sc install"
38
+ "linux": "subc sc install",
39
+ "win32": "subc sc install"
38
40
  },
39
41
  "runbook": {
40
42
  "mode": "launch",
@@ -100,8 +102,8 @@
100
102
  "ANTHROPIC_AUTH_TOKEN": "{apiKey}",
101
103
  "ANTHROPIC_MODEL": "{model}",
102
104
  "ANTHROPIC_SMALL_FAST_MODEL": "{model}",
103
- "ANTHROPIC_DEFAULT_OPUS_MODEL": "subconscious/glm-5.2",
104
- "ANTHROPIC_DEFAULT_OPUS_MODEL_NAME": "subconscious/glm-5.2",
105
+ "ANTHROPIC_DEFAULT_OPUS_MODEL": "subconscious/glm-5.3-marathon",
106
+ "ANTHROPIC_DEFAULT_OPUS_MODEL_NAME": "subconscious/glm-5.3-marathon",
105
107
  "ANTHROPIC_DEFAULT_OPUS_MODEL_DESCRIPTION": "Subconscious default model",
106
108
  "ANTHROPIC_DEFAULT_SONNET_MODEL": "subconscious/tim-qwen3.6-27b",
107
109
  "ANTHROPIC_DEFAULT_SONNET_MODEL_NAME": "subconscious/tim-qwen3.6-27b",
@@ -219,6 +221,14 @@
219
221
  }
220
222
  },
221
223
  "models": {
224
+ "subconscious/glm-5.3-marathon": {
225
+ "name": "subconscious/glm-5.3-marathon",
226
+ "tools": true,
227
+ "limit": {
228
+ "context": 5000000,
229
+ "output": 65536
230
+ }
231
+ },
222
232
  "subconscious/glm-5.2": {
223
233
  "name": "subconscious/glm-5.2",
224
234
  "tools": true,
@@ -20,9 +20,9 @@
20
20
  #
21
21
  # export ANTHROPIC_BASE_URL=https://your-gateway.example
22
22
  # export ANTHROPIC_AUTH_TOKEN=sk-gw-...
23
- # export ANTHROPIC_MODEL=subconscious/glm-5.2
24
- # export ANTHROPIC_SMALL_FAST_MODEL=subconscious/glm-5.2
25
- # export CLAUDE_CODE_SUBAGENT_MODEL=subconscious/glm-5.2
23
+ # export ANTHROPIC_MODEL=subconscious/glm-5.3-marathon
24
+ # export ANTHROPIC_SMALL_FAST_MODEL=subconscious/glm-5.3-marathon
25
+ # export CLAUDE_CODE_SUBAGENT_MODEL=subconscious/glm-5.3-marathon
26
26
  # export CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS=4
27
27
  # export CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH=1
28
28
  # export CLAUDE_CODE_AUTO_COMPACT_WINDOW=1000000
@@ -57,7 +57,7 @@ if [[ -f "$SHARED_ENV" ]]; then set -a; source "$SHARED_ENV"; set +a; fi
57
57
 
58
58
  CLAUDE_DIR="${HOME}/.claude"
59
59
  ENV_FILE="${CLAUDE_DIR}/subconscious-gateway.env"
60
- DEFAULT_MODEL="subconscious/glm-5.2"
60
+ DEFAULT_MODEL="subconscious/glm-5.3-marathon"
61
61
  DEFAULT_COMPACT_WINDOW="1000000"
62
62
  DEFAULT_MAX_CONTEXT_TOKENS="3000000"
63
63
  DEFAULT_MAX_CONCURRENT_SUBAGENTS="4"