subconscious-cli 0.3.0 → 0.3.1

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.
package/bin/cli.js CHANGED
@@ -22,18 +22,24 @@ import {
22
22
  resolveAgent,
23
23
  runAgent,
24
24
  agentList,
25
- parseSetupRequest,
25
+ agentCommandName,
26
26
  isAgentHelpRequest,
27
+ parseAgentAction,
27
28
  } from './agents.js';
28
29
  import {
29
30
  configCommand,
30
31
  DEFAULT_PROFILE,
31
32
  loadProfile,
32
33
  modelsCommand,
34
+ printConfigHelp,
33
35
  updateUrlCommand,
34
36
  validateProfileName,
35
37
  } from './profiles.js';
36
38
 
39
+ function isHelpArg(arg) {
40
+ return arg === 'help' || arg === '-h' || arg === '--help';
41
+ }
42
+
37
43
  function printHelp() {
38
44
  const agents = agentList()
39
45
  .map(({ name, alias, action }) => ` ${c.cyan}${alias.padEnd(13)}${c.reset}${c.dim}${action} ${name}${c.reset}`)
@@ -43,6 +49,7 @@ function printHelp() {
43
49
 
44
50
  ${c.bold}Usage${c.reset}
45
51
  ${c.cyan}subc${c.reset} <command> [...args]
52
+ ${c.cyan}subc${c.reset} <command> help
46
53
 
47
54
  ${c.bold}Auth${c.reset}
48
55
  ${c.cyan}login${c.reset} Authenticate and save your API key
@@ -51,11 +58,8 @@ function printHelp() {
51
58
  ${c.cyan}logout${c.reset} Remove saved credentials
52
59
  ${c.cyan}whoami${c.reset} Show current authentication status
53
60
 
54
- ${c.bold}Setup and profiles${c.reset}
55
- ${c.cyan}help <agent>${c.reset} Show coding-agent integration help and settings
56
- ${c.cyan}setup${c.reset} Configure all or one coding-agent integration
57
- ${c.cyan}config${c.reset} Show or update the selected runbook profile
58
- ${c.cyan}settings${c.reset} Edit profile and per-agent settings interactively
61
+ ${c.bold}Profiles${c.reset}
62
+ ${c.cyan}config${c.reset} List profiles, or show/edit one with ${c.dim}-p${c.reset}
59
63
  ${c.cyan}models${c.reset} List available Subconscious models
60
64
 
61
65
  ${c.bold}Coding agents${c.reset}
@@ -69,17 +73,90 @@ ${agents}
69
73
 
70
74
  ${c.bold}Examples${c.reset}
71
75
  ${c.dim}$${c.reset} subc login
72
- ${c.dim}$${c.reset} subc update-key sk-...
73
- ${c.dim}$${c.reset} subc update-url https://api.subconscious.dev
74
- ${c.dim}$${c.reset} subc setup
75
- ${c.dim}$${c.reset} subc settings
76
- ${c.dim}$${c.reset} subc models
77
- ${c.dim}$${c.reset} subc help codex
76
+ ${c.dim}$${c.reset} subc config
77
+ ${c.dim}$${c.reset} subc config help
78
+ ${c.dim}$${c.reset} subc -p staging config
79
+ ${c.dim}$${c.reset} subc config edit vim
78
80
  ${c.dim}$${c.reset} subc claude
79
- ${c.dim}$${c.reset} subc --profile staging codex
80
- ${c.dim}$${c.reset} subc codex --model subconscious/glm-5.2
81
+ ${c.dim}$${c.reset} subc claude help
82
+ ${c.dim}$${c.reset} subc cursor install
83
+ ${c.dim}$${c.reset} subc cursor uninstall
84
+ ${c.dim}$${c.reset} subc pi install
85
+ ${c.dim}$${c.reset} subc -p staging codex
86
+
87
+ ${c.dim}Use subc <command> help for command-specific usage.${c.reset}
88
+ `);
89
+ }
90
+
91
+ const COMMAND_HELP = {
92
+ login: `
93
+ Usage:
94
+ subc login
95
+ subc -p NAME login
96
+ subc login help
97
+
98
+ Authenticate and save an API key to the selected profile.
99
+ `,
100
+ logout: `
101
+ Usage:
102
+ subc logout
103
+ subc -p NAME logout
104
+ subc logout help
105
+
106
+ Remove the selected profile's saved API key. Non-secret settings are kept.
107
+ `,
108
+ whoami: `
109
+ Usage:
110
+ subc whoami
111
+ subc -p NAME whoami
112
+ subc whoami help
113
+
114
+ Show the current authentication status for the selected profile.
115
+ `,
116
+ 'update-key': `
117
+ Usage:
118
+ subc update-key <api-key>
119
+ subc -p NAME update-key <api-key>
120
+ subc update-key help
121
+
122
+ Replace the selected profile's shared API key.
123
+ `,
124
+ 'update-url': `
125
+ Usage:
126
+ subc update-url <gateway-url>
127
+ subc update-url help
128
+
129
+ Update the active profile's gateway URL.
130
+ `,
131
+ models: `
132
+ Usage:
133
+ subc models
134
+ subc models help
135
+
136
+ List available Subconscious models.
137
+ `,
138
+ };
139
+
140
+ function printRetiredSetup(args = []) {
141
+ const maybeAgent = resolveAgent(args[0]);
142
+ const command = maybeAgent ? agentCommandName(maybeAgent) : 'cursor';
143
+ console.error(`
144
+ ${c.red}subc setup is no longer used.${c.reset} Use the agent command instead:
145
+
146
+ ${c.cyan}subc ${command} install${c.reset}
147
+ ${c.cyan}subc ${command} uninstall${c.reset}
148
+ ${c.cyan}subc ${command} help${c.reset}
149
+ `);
150
+ }
81
151
 
82
- ${c.dim}Arguments are forwarded to terminal agents or their runbook setup.${c.reset}
152
+ function printRetiredSettings() {
153
+ console.error(`
154
+ ${c.red}subc settings is no longer used.${c.reset} Use:
155
+
156
+ ${c.cyan}subc config${c.reset} List profiles
157
+ ${c.cyan}subc -p NAME config${c.reset} Show a profile
158
+ ${c.cyan}subc -p NAME config edit${c.reset} Open the profile env file
159
+ ${c.cyan}subc config help${c.reset}
83
160
  `);
84
161
  }
85
162
 
@@ -91,10 +168,8 @@ const authCommands = {
91
168
  };
92
169
 
93
170
  function extractProfile(argv) {
94
- let profileName =
95
- process.env.SUBC_PROFILE?.trim() ||
96
- process.env.MBTA_PROFILE?.trim() ||
97
- DEFAULT_PROFILE;
171
+ let profileName = process.env.SUBC_PROFILE?.trim() || DEFAULT_PROFILE;
172
+ let profileExplicit = false;
98
173
  const args = [];
99
174
  for (let i = 0; i < argv.length; i++) {
100
175
  const arg = argv[i];
@@ -106,39 +181,41 @@ function extractProfile(argv) {
106
181
  const value = argv[++i];
107
182
  if (!value) throw new Error(`${arg} requires a profile name`);
108
183
  profileName = value;
184
+ profileExplicit = true;
109
185
  continue;
110
186
  }
111
187
  if (arg.startsWith('--profile=')) {
112
188
  profileName = arg.slice('--profile='.length);
189
+ profileExplicit = true;
113
190
  continue;
114
191
  }
115
192
  args.push(arg);
116
193
  }
117
194
  validateProfileName(profileName);
118
- return { args, profileName };
195
+ return { args, profileName, profileExplicit };
119
196
  }
120
197
 
121
198
  function requireNamedProfile(profile) {
122
199
  if (profile.name !== DEFAULT_PROFILE && !profile.exists) {
123
200
  throw new Error(
124
201
  `Profile '${profile.name}' does not exist. Create it with ` +
125
- `subc --profile ${profile.name} config --api-key KEY`,
202
+ `subc -p ${profile.name} config --api-key KEY`,
126
203
  );
127
204
  }
128
205
  }
129
206
 
130
207
  async function main() {
131
208
  const parsed = extractProfile(process.argv.slice(2));
132
- const { args, profileName } = parsed;
209
+ const { args, profileName, profileExplicit } = parsed;
133
210
  const command = args[0];
134
211
 
135
- if (!command || command === '--help' || command === '-h') {
212
+ if (!command || command === '--help' || command === '-h' || (command === 'help' && !args[1])) {
136
213
  printHelp();
137
214
  return;
138
215
  }
139
216
 
140
217
  if (command === 'help') {
141
- if (!args[1]) {
218
+ if (!args[1] || isHelpArg(args[1])) {
142
219
  printHelp();
143
220
  return;
144
221
  }
@@ -156,94 +233,67 @@ async function main() {
156
233
  return;
157
234
  }
158
235
 
236
+ if (command === 'setup') {
237
+ printRetiredSetup(args.slice(1));
238
+ process.exitCode = 1;
239
+ return;
240
+ }
241
+
242
+ if (command === 'settings') {
243
+ printRetiredSettings();
244
+ process.exitCode = 1;
245
+ return;
246
+ }
247
+
159
248
  const authHandler = authCommands[command];
160
249
  if (authHandler) {
250
+ if (isHelpArg(args[1])) {
251
+ console.log(COMMAND_HELP[command]);
252
+ return;
253
+ }
161
254
  const profile = await loadProfile(profileName);
162
255
  await authHandler(args.slice(1), { profile, profileName });
163
256
  return;
164
257
  }
165
258
 
166
259
  if (command === 'config') {
167
- await configCommand(args.slice(1), profileName);
168
- return;
169
- }
170
-
171
- if (command === 'settings') {
172
- if (['help', '-h', '--help'].includes(args[1])) {
173
- console.log(`
174
- Usage:
175
- subc settings
176
- subc --profile NAME settings
177
- subc --profile NAME config interactive
178
-
179
- Interactively choose or create a profile, then edit shared or per-agent settings.
180
- `);
260
+ if (isHelpArg(args[1])) {
261
+ printConfigHelp();
181
262
  return;
182
263
  }
183
- if (args.length > 1) throw new Error('Usage: subc [--profile NAME] settings');
184
- await configCommand(['interactive'], profileName);
264
+ await configCommand(args.slice(1), profileName, { profileExplicit });
185
265
  return;
186
266
  }
187
267
 
188
268
  if (command === 'models') {
269
+ if (isHelpArg(args[1])) {
270
+ console.log(COMMAND_HELP.models);
271
+ return;
272
+ }
189
273
  modelsCommand();
190
274
  return;
191
275
  }
192
276
 
193
277
  if (command === 'update-url') {
194
- await updateUrlCommand(args.slice(1), { profileName });
195
- return;
196
- }
197
-
198
- if (command === 'setup') {
199
- const setupArgs = args.slice(1);
200
- if (setupArgs[0] === '-h' || setupArgs[0] === '--help') {
201
- console.log(`
202
- Usage:
203
- subc setup [install|status|uninstall]
204
- subc setup AGENT [install|status|uninstall] [agent options]
205
-
206
- Examples:
207
- subc setup Configure every coding-agent integration
208
- subc setup status Show every integration's setup status
209
- subc setup codex Configure only Codex
210
- subc setup codex status Show only Codex's setup status
211
- subc setup codex --subagents Configure Codex's legacy subagent mode
212
- subc setup codex env Print persistent Codex exports for sourcing
213
- `);
278
+ if (isHelpArg(args[1])) {
279
+ console.log(COMMAND_HELP['update-url']);
214
280
  return;
215
281
  }
216
- const request = parseSetupRequest(setupArgs);
217
- const profile = await loadProfile(profileName);
218
- const targetHelp = request.targeted && isAgentHelpRequest(request.args);
219
- const persistentHelper = ['use', 'env', 'unset'].includes(request.action);
220
- const oneOffApiKey = request.targeted && request.args.includes('--api-key');
221
- if (!targetHelp && !persistentHelper && !oneOffApiKey) requireNamedProfile(profile);
222
- const failures = [];
223
- for (const agent of request.agents) {
224
- const code = await runAgent(agent, request.args, { profile, setup: true });
225
- if (code) failures.push(agent.name);
226
- }
227
- if (failures.length) {
228
- throw new Error(`Setup failed for: ${failures.join(', ')}`);
229
- }
230
- if (targetHelp || persistentHelper) return;
231
- const subject = request.targeted ? request.agents[0].name : 'Coding-agent';
232
- const message =
233
- request.action === 'status'
234
- ? `${subject} status check complete.`
235
- : request.action === 'uninstall'
236
- ? `${subject} integration${request.targeted ? '' : 's'} removed.`
237
- : `${subject} setup complete.`;
238
- console.log(`\n ${c.green}${c.bold}✓ ${message}${c.reset}\n`);
282
+ await updateUrlCommand(args.slice(1), { profileName });
239
283
  return;
240
284
  }
241
285
 
242
286
  const agent = resolveAgent(command);
243
287
  if (agent) {
288
+ const agentArgs = args.slice(1);
244
289
  const profile = await loadProfile(profileName);
245
- if (!isAgentHelpRequest(args.slice(1))) requireNamedProfile(profile);
246
- await runAgent(agent, args.slice(1), { profile });
290
+ if (!isAgentHelpRequest(agentArgs)) {
291
+ const action = parseAgentAction(agent, agentArgs);
292
+ if (action.action !== 'status' && action.action !== 'uninstall') {
293
+ requireNamedProfile(profile);
294
+ }
295
+ }
296
+ await runAgent(agent, agentArgs, { profile });
247
297
  return;
248
298
  }
249
299