@mrpatronz/nexusflow 2.5.0 → 2.5.2
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/dist/commands/diff.d.ts +2 -0
- package/dist/commands/diff.d.ts.map +1 -1
- package/dist/commands/diff.js +13 -1
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/finish.d.ts.map +1 -1
- package/dist/commands/finish.js +7 -0
- package/dist/commands/finish.js.map +1 -1
- package/dist/commands/list.d.ts +3 -1
- package/dist/commands/list.d.ts.map +1 -1
- package/dist/commands/list.js +5 -1
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/schedule.d.ts +3 -1
- package/dist/commands/schedule.d.ts.map +1 -1
- package/dist/commands/schedule.js +15 -2
- package/dist/commands/schedule.js.map +1 -1
- package/dist/commands/status.d.ts +4 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +9 -3
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/ui.d.ts +9 -0
- package/dist/commands/ui.d.ts.map +1 -1
- package/dist/commands/ui.js +42 -1
- package/dist/commands/ui.js.map +1 -1
- package/dist/core/doctor.d.ts.map +1 -1
- package/dist/core/doctor.js +24 -0
- package/dist/core/doctor.js.map +1 -1
- package/dist/core/worktree.test.js +2 -2
- package/dist/desktop-server.d.ts +1 -1
- package/dist/desktop-server.js +1 -1
- package/dist/gui/assets/{AgentsPage-BNHR9qux.js → AgentsPage-CGvhYtRS.js} +1 -1
- package/dist/gui/assets/{DashboardPage-BScH3Cxp.js → DashboardPage-BSVVVXuM.js} +1 -1
- package/dist/gui/assets/{GettingStartedPage-AWlI-176.js → GettingStartedPage-srl_5DA_.js} +1 -1
- package/dist/gui/assets/{ProjectsPage-Bojj7gxI.js → ProjectsPage-BfFX3Rg1.js} +1 -1
- package/dist/gui/assets/{ScaffoldRepoInline-DJMbeHVM.js → ScaffoldRepoInline-DWsd4vxF.js} +1 -1
- package/dist/gui/assets/{SettingsPage-BAdXO8X0.js → SettingsPage-C16CjqlK.js} +1 -1
- package/dist/gui/assets/{SkillsPage-CF6Db1FA.js → SkillsPage-DKLoq_sH.js} +1 -1
- package/dist/gui/assets/StartWorkPage-D56-WIZp.js +1 -0
- package/dist/gui/assets/{StrategiesPage-nGbR9TAc.js → StrategiesPage-CY8xp7Lz.js} +1 -1
- package/dist/gui/assets/{WorkspacesPage-7XRtVJNF.js → WorkspacesPage-CXtIMMUl.js} +1 -1
- package/dist/gui/assets/{alert-dialog-67uzXJi4.js → alert-dialog-CCwlEjU2.js} +1 -1
- package/dist/gui/assets/{index-V1dDX1O_.js → index-pxzwuRLq.js} +3 -3
- package/dist/gui/assets/{vsc-Di05BTNr.js → vsc-DkRhgYbO.js} +1 -1
- package/dist/gui/index.html +1 -1
- package/dist/index.js +130 -546
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +48 -11
- package/dist/server.js.map +1 -1
- package/dist/server.test.js +1 -0
- package/dist/server.test.js.map +1 -1
- package/package.json +3 -3
- package/dist/gui/assets/StartWorkPage-BQid3uIw.js +0 -1
package/dist/index.js
CHANGED
|
@@ -54,136 +54,84 @@ program.hook('preAction', (thisCommand) => {
|
|
|
54
54
|
process.env.NEXUSFLOW_DEBUG = '1';
|
|
55
55
|
}
|
|
56
56
|
});
|
|
57
|
+
function isDebugMode() {
|
|
58
|
+
return process.argv.includes('--debug') || Boolean(process.env.NEXUSFLOW_DEBUG);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Wraps a command action: clean exit on prompt cancellation (Ctrl+C inside an
|
|
62
|
+
* inquirer prompt), clean red error message by default, and exit code 1.
|
|
63
|
+
* When --debug is provided, prints the full error stack.
|
|
64
|
+
*/
|
|
65
|
+
function runAction(fn) {
|
|
66
|
+
return async (...args) => {
|
|
67
|
+
try {
|
|
68
|
+
await fn(...args);
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
if (error instanceof Error && error.message.includes('User force closed')) {
|
|
72
|
+
console.log('\nCancelled.');
|
|
73
|
+
process.exit(0);
|
|
74
|
+
}
|
|
75
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
76
|
+
console.error(chalk.red(`\n✖ ${message}`));
|
|
77
|
+
if (isDebugMode() && error instanceof Error && error.stack) {
|
|
78
|
+
console.error(chalk.dim(error.stack));
|
|
79
|
+
}
|
|
80
|
+
else if (!isDebugMode()) {
|
|
81
|
+
console.error(chalk.dim(' (Run with --debug for details)\n'));
|
|
82
|
+
}
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
}
|
|
57
87
|
program
|
|
58
88
|
.command('create')
|
|
59
89
|
.description('Create a new feature workspace — pick repos, pick AI assistants, generate context')
|
|
60
|
-
.action(
|
|
61
|
-
try {
|
|
62
|
-
await createCommand();
|
|
63
|
-
}
|
|
64
|
-
catch (error) {
|
|
65
|
-
if (error instanceof Error && error.message.includes('User force closed')) {
|
|
66
|
-
console.log('\nCancelled.');
|
|
67
|
-
process.exit(0);
|
|
68
|
-
}
|
|
69
|
-
console.error(error);
|
|
70
|
-
process.exit(1);
|
|
71
|
-
}
|
|
72
|
-
});
|
|
90
|
+
.action(runAction(createCommand));
|
|
73
91
|
program
|
|
74
92
|
.command('list')
|
|
75
93
|
.alias('ls')
|
|
76
94
|
.description('List all existing workspaces')
|
|
77
|
-
.
|
|
78
|
-
|
|
79
|
-
await listCommand();
|
|
80
|
-
}
|
|
81
|
-
catch (error) {
|
|
82
|
-
console.error(error);
|
|
83
|
-
process.exit(1);
|
|
84
|
-
}
|
|
85
|
-
});
|
|
95
|
+
.option('--json', 'Output as JSON')
|
|
96
|
+
.action(runAction(listCommand));
|
|
86
97
|
program
|
|
87
98
|
.command('open')
|
|
88
99
|
.description('Re-open an existing workspace in an editor')
|
|
89
|
-
.action(
|
|
90
|
-
try {
|
|
91
|
-
await openCommand();
|
|
92
|
-
}
|
|
93
|
-
catch (error) {
|
|
94
|
-
if (error instanceof Error && error.message.includes('User force closed')) {
|
|
95
|
-
console.log('\nCancelled.');
|
|
96
|
-
process.exit(0);
|
|
97
|
-
}
|
|
98
|
-
console.error(error);
|
|
99
|
-
process.exit(1);
|
|
100
|
-
}
|
|
101
|
-
});
|
|
100
|
+
.action(runAction(openCommand));
|
|
102
101
|
program
|
|
103
102
|
.command('init')
|
|
104
103
|
.description('Initialize NexusFlow configuration')
|
|
105
|
-
.action(
|
|
106
|
-
try {
|
|
107
|
-
await initCommand();
|
|
108
|
-
}
|
|
109
|
-
catch (error) {
|
|
110
|
-
if (error instanceof Error && error.message.includes('User force closed')) {
|
|
111
|
-
console.log('\nCancelled.');
|
|
112
|
-
process.exit(0);
|
|
113
|
-
}
|
|
114
|
-
console.error(error);
|
|
115
|
-
process.exit(1);
|
|
116
|
-
}
|
|
117
|
-
});
|
|
104
|
+
.action(runAction(initCommand));
|
|
118
105
|
program
|
|
119
106
|
.command('start')
|
|
120
107
|
.description('Start all services in a workspace')
|
|
121
108
|
.argument('[workspace]', 'Path to workspace (auto-detects from CWD)')
|
|
122
|
-
.action(async (workspace) => {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
126
|
-
catch (error) {
|
|
127
|
-
if (error instanceof Error && error.message.includes('User force closed')) {
|
|
128
|
-
console.log('\nCancelled.');
|
|
129
|
-
process.exit(0);
|
|
130
|
-
}
|
|
131
|
-
console.error(error);
|
|
132
|
-
process.exit(1);
|
|
133
|
-
}
|
|
134
|
-
});
|
|
109
|
+
.action(runAction(async (workspace) => {
|
|
110
|
+
await startCommand(workspace);
|
|
111
|
+
}));
|
|
135
112
|
program
|
|
136
113
|
.command('stop')
|
|
137
114
|
.description('Stop all running services in a workspace')
|
|
138
115
|
.argument('[workspace]', 'Path to workspace (auto-detects from CWD)')
|
|
139
|
-
.action(async (workspace) => {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
}
|
|
143
|
-
catch (error) {
|
|
144
|
-
if (error instanceof Error && error.message.includes('User force closed')) {
|
|
145
|
-
console.log('\nCancelled.');
|
|
146
|
-
process.exit(0);
|
|
147
|
-
}
|
|
148
|
-
console.error(error);
|
|
149
|
-
process.exit(1);
|
|
150
|
-
}
|
|
151
|
-
});
|
|
116
|
+
.action(runAction(async (workspace) => {
|
|
117
|
+
await stopCommand(workspace);
|
|
118
|
+
}));
|
|
152
119
|
program
|
|
153
120
|
.command('logs')
|
|
154
121
|
.description('Show logs from running services')
|
|
155
122
|
.argument('[workspace]', 'Path to workspace (auto-detects from CWD)')
|
|
156
123
|
.option('-n, --lines <number>', 'Number of lines per service', '30')
|
|
157
|
-
.action(async (workspace, options) => {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
}
|
|
161
|
-
catch (error) {
|
|
162
|
-
if (error instanceof Error && error.message.includes('User force closed')) {
|
|
163
|
-
console.log('\nCancelled.');
|
|
164
|
-
process.exit(0);
|
|
165
|
-
}
|
|
166
|
-
console.error(error);
|
|
167
|
-
process.exit(1);
|
|
168
|
-
}
|
|
169
|
-
});
|
|
124
|
+
.action(runAction(async (workspace, options) => {
|
|
125
|
+
await logsCommand(workspace, parseInt(options.lines, 10));
|
|
126
|
+
}));
|
|
170
127
|
program
|
|
171
128
|
.command('status')
|
|
172
129
|
.description('Show status of running services')
|
|
173
130
|
.argument('[workspace]', 'Path to workspace (auto-detects from CWD)')
|
|
174
|
-
.
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
catch (error) {
|
|
179
|
-
if (error instanceof Error && error.message.includes('User force closed')) {
|
|
180
|
-
console.log('\nCancelled.');
|
|
181
|
-
process.exit(0);
|
|
182
|
-
}
|
|
183
|
-
console.error(error);
|
|
184
|
-
process.exit(1);
|
|
185
|
-
}
|
|
186
|
-
});
|
|
131
|
+
.option('--json', 'Output in JSON format')
|
|
132
|
+
.action(runAction(async (workspace, options) => {
|
|
133
|
+
await statusCommand(workspace, options);
|
|
134
|
+
}));
|
|
187
135
|
program
|
|
188
136
|
.command('ui')
|
|
189
137
|
.description('Start the NexusFlow dashboard server (the backend the desktop app embeds)')
|
|
@@ -192,59 +140,31 @@ program
|
|
|
192
140
|
.option('--open', 'Also open the dashboard in your default browser')
|
|
193
141
|
.option('--server-only', '(deprecated — server-only is now the default)')
|
|
194
142
|
.option('--strict-port', 'Fail instead of auto-incrementing when the port is in use')
|
|
195
|
-
.action(async (options) => {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}
|
|
199
|
-
catch (error) {
|
|
200
|
-
console.error(error);
|
|
201
|
-
process.exit(1);
|
|
202
|
-
}
|
|
203
|
-
});
|
|
143
|
+
.action(runAction(async (options) => {
|
|
144
|
+
await uiCommand(options);
|
|
145
|
+
}));
|
|
204
146
|
program
|
|
205
147
|
.command('dashboard')
|
|
206
148
|
.alias('dash')
|
|
207
149
|
.description('Open the web dashboard in your default browser')
|
|
208
150
|
.option('-p, --port <number>', 'Port to run the dashboard server on', '3000')
|
|
209
|
-
.action(async (options) => {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
}
|
|
213
|
-
catch (error) {
|
|
214
|
-
console.error(error);
|
|
215
|
-
process.exit(1);
|
|
216
|
-
}
|
|
217
|
-
});
|
|
151
|
+
.action(runAction(async (options) => {
|
|
152
|
+
await uiCommand({ ...options, daemon: true, open: true });
|
|
153
|
+
}));
|
|
218
154
|
program
|
|
219
155
|
.command('tui')
|
|
220
156
|
.description('Open the interactive terminal GUI (TUI) dashboard')
|
|
221
157
|
.argument('[workspace]', 'Path to workspace (auto-detects from CWD)')
|
|
222
|
-
.action(async (workspace) => {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
}
|
|
226
|
-
catch (error) {
|
|
227
|
-
console.error(error);
|
|
228
|
-
process.exit(1);
|
|
229
|
-
}
|
|
230
|
-
});
|
|
158
|
+
.action(runAction(async (workspace) => {
|
|
159
|
+
await tuiCommand({ workspace });
|
|
160
|
+
}));
|
|
231
161
|
program
|
|
232
162
|
.command('sync')
|
|
233
163
|
.description('Sync all repositories in a workspace')
|
|
234
164
|
.argument('[workspace]', 'Path to workspace (auto-detects from CWD)')
|
|
235
|
-
.action(async (workspace) => {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
}
|
|
239
|
-
catch (error) {
|
|
240
|
-
if (error instanceof Error && error.message.includes('User force closed')) {
|
|
241
|
-
console.log('\nCancelled.');
|
|
242
|
-
process.exit(0);
|
|
243
|
-
}
|
|
244
|
-
console.error(error);
|
|
245
|
-
process.exit(1);
|
|
246
|
-
}
|
|
247
|
-
});
|
|
165
|
+
.action(runAction(async (workspace) => {
|
|
166
|
+
await syncCommand(workspace);
|
|
167
|
+
}));
|
|
248
168
|
program
|
|
249
169
|
.command('commit')
|
|
250
170
|
.description('Commit changes across all repositories in a workspace')
|
|
@@ -253,75 +173,36 @@ program
|
|
|
253
173
|
.option('--no-push', 'Stage and commit changes without pushing to remote')
|
|
254
174
|
.option('--dry-run', 'Preview changes without committing')
|
|
255
175
|
.option('-r, --repo <repos...>', 'Only commit the given repositories (by name)')
|
|
256
|
-
.action(async (workspace, options) => {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
}
|
|
260
|
-
catch (error) {
|
|
261
|
-
if (error instanceof Error && error.message.includes('User force closed')) {
|
|
262
|
-
console.log('\nCancelled.');
|
|
263
|
-
process.exit(0);
|
|
264
|
-
}
|
|
265
|
-
console.error(error);
|
|
266
|
-
process.exit(1);
|
|
267
|
-
}
|
|
268
|
-
});
|
|
176
|
+
.action(runAction(async (workspace, options) => {
|
|
177
|
+
await commitCommand(options.message, workspace, options);
|
|
178
|
+
}));
|
|
269
179
|
program
|
|
270
180
|
.command('diff')
|
|
271
181
|
.description('Display a unified summary of changes across all repositories (including unpushed commits)')
|
|
272
182
|
.argument('[workspace]', 'Path to workspace (auto-detects from CWD)')
|
|
273
183
|
.option('-r, --repo <repos...>', 'Only show the given repositories (by name)')
|
|
274
|
-
.
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
catch (error) {
|
|
279
|
-
if (error instanceof Error && error.message.includes('User force closed')) {
|
|
280
|
-
console.log('\nCancelled.');
|
|
281
|
-
process.exit(0);
|
|
282
|
-
}
|
|
283
|
-
console.error(error);
|
|
284
|
-
process.exit(1);
|
|
285
|
-
}
|
|
286
|
-
});
|
|
184
|
+
.option('--json', 'Output in JSON format')
|
|
185
|
+
.action(runAction(async (workspace, options) => {
|
|
186
|
+
await diffCommand(workspace, options);
|
|
187
|
+
}));
|
|
287
188
|
// Pack command removed.
|
|
288
189
|
program
|
|
289
190
|
.command('remove')
|
|
290
191
|
.alias('rm')
|
|
291
192
|
.description('Delete a workspace and cleanly prune/remove its git worktrees')
|
|
292
193
|
.argument('[workspace]', 'Workspace name or path')
|
|
293
|
-
.action(async (workspace) => {
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
}
|
|
297
|
-
catch (error) {
|
|
298
|
-
if (error instanceof Error && error.message.includes('User force closed')) {
|
|
299
|
-
console.log('\nCancelled.');
|
|
300
|
-
process.exit(0);
|
|
301
|
-
}
|
|
302
|
-
console.error(error);
|
|
303
|
-
process.exit(1);
|
|
304
|
-
}
|
|
305
|
-
});
|
|
194
|
+
.action(runAction(async (workspace) => {
|
|
195
|
+
await removeCommand(workspace);
|
|
196
|
+
}));
|
|
306
197
|
program
|
|
307
198
|
.command('add-repo')
|
|
308
199
|
.alias('add')
|
|
309
200
|
.description('Add a repository to an existing workspace and update configurations')
|
|
310
201
|
.argument('[repo-path]', 'Path to the repository to add')
|
|
311
202
|
.argument('[workspace]', 'Workspace name or path')
|
|
312
|
-
.action(async (repoPath, workspace) => {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
}
|
|
316
|
-
catch (error) {
|
|
317
|
-
if (error instanceof Error && error.message.includes('User force closed')) {
|
|
318
|
-
console.log('\nCancelled.');
|
|
319
|
-
process.exit(0);
|
|
320
|
-
}
|
|
321
|
-
console.error(error);
|
|
322
|
-
process.exit(1);
|
|
323
|
-
}
|
|
324
|
-
});
|
|
203
|
+
.action(runAction(async (repoPath, workspace) => {
|
|
204
|
+
await addRepoCommand(repoPath, workspace);
|
|
205
|
+
}));
|
|
325
206
|
program
|
|
326
207
|
.command('isolate')
|
|
327
208
|
.description('Dynamically isolate a repository in an in-place workspace into a dedicated worktree on demand')
|
|
@@ -330,60 +211,32 @@ program
|
|
|
330
211
|
.option('-b, --branch <branch>', 'Target feature branch name')
|
|
331
212
|
.option('--base <base>', 'Base branch to branch off')
|
|
332
213
|
.option('-w, --workspace <workspace>', 'Workspace name or path')
|
|
333
|
-
.action(async (repo, branchArg, options) => {
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
}
|
|
337
|
-
catch (error) {
|
|
338
|
-
if (error instanceof Error && error.message.includes('User force closed')) {
|
|
339
|
-
console.log('\nCancelled.');
|
|
340
|
-
process.exit(0);
|
|
341
|
-
}
|
|
342
|
-
console.error(error);
|
|
343
|
-
process.exit(1);
|
|
344
|
-
}
|
|
345
|
-
});
|
|
214
|
+
.action(runAction(async (repo, branchArg, options) => {
|
|
215
|
+
await isolateCommand(repo, branchArg, options);
|
|
216
|
+
}));
|
|
346
217
|
program
|
|
347
218
|
.command('handoff')
|
|
348
219
|
.description('Generate a compact handoff bundle (nexusflow-handoff.md) for session resumption')
|
|
349
220
|
.argument('[workspace]', 'Path to the workspace')
|
|
350
|
-
.action(async (workspace) => {
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
}
|
|
354
|
-
catch (error) {
|
|
355
|
-
console.error(error);
|
|
356
|
-
process.exit(1);
|
|
357
|
-
}
|
|
358
|
-
});
|
|
221
|
+
.action(runAction(async (workspace) => {
|
|
222
|
+
await handoffCommand(workspace);
|
|
223
|
+
}));
|
|
359
224
|
program
|
|
360
225
|
.command('refresh')
|
|
361
226
|
.description('Refresh workspace context, plan and handoff files (re-analyzes only changed repos)')
|
|
362
227
|
.argument('[workspace]', 'Path to workspace (auto-detects from CWD)')
|
|
363
228
|
.option('-f, --force', 'Ignore the analysis cache and re-analyze every repository')
|
|
364
229
|
.option('-s, --strategy <id>', 'Update the teamwork strategy (use template ID, or "auto" for AI suggestion)')
|
|
365
|
-
.action(async (workspace, options) => {
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
}
|
|
369
|
-
catch (error) {
|
|
370
|
-
console.error(error);
|
|
371
|
-
process.exit(1);
|
|
372
|
-
}
|
|
373
|
-
});
|
|
230
|
+
.action(runAction(async (workspace, options) => {
|
|
231
|
+
await refreshCommand(options, workspace);
|
|
232
|
+
}));
|
|
374
233
|
program
|
|
375
234
|
.command('doctor')
|
|
376
235
|
.description('Run diagnostics to verify workspace health and check for local loop issues')
|
|
377
236
|
.argument('[workspace]', 'Path to workspace (auto-detects from CWD)')
|
|
378
|
-
.action(async (workspace) => {
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
}
|
|
382
|
-
catch (error) {
|
|
383
|
-
console.error(error);
|
|
384
|
-
process.exit(1);
|
|
385
|
-
}
|
|
386
|
-
});
|
|
237
|
+
.action(runAction(async (workspace) => {
|
|
238
|
+
await doctorCommand(workspace);
|
|
239
|
+
}));
|
|
387
240
|
program
|
|
388
241
|
.command('finish')
|
|
389
242
|
.description('Finish a feature — commit & push everything, open PRs, promote learnings, optionally remove the workspace')
|
|
@@ -394,19 +247,9 @@ program
|
|
|
394
247
|
.option('--cleanup', 'Remove the workspace after everything is confirmed pushed (still asks for confirmation)')
|
|
395
248
|
.option('-y, --yes', 'Accept defaults for non-destructive prompts')
|
|
396
249
|
.option('--dry-run', 'Show what finish would do without changing anything')
|
|
397
|
-
.action(async (workspace, options) => {
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
}
|
|
401
|
-
catch (error) {
|
|
402
|
-
if (error instanceof Error && error.message.includes('User force closed')) {
|
|
403
|
-
console.log('\nCancelled.');
|
|
404
|
-
process.exit(0);
|
|
405
|
-
}
|
|
406
|
-
console.error(error);
|
|
407
|
-
process.exit(1);
|
|
408
|
-
}
|
|
409
|
-
});
|
|
250
|
+
.action(runAction(async (workspace, options) => {
|
|
251
|
+
await finishCommand(workspace, options);
|
|
252
|
+
}));
|
|
410
253
|
// Knowledge command group
|
|
411
254
|
const knowledgeCmd = program
|
|
412
255
|
.command('knowledge')
|
|
@@ -420,38 +263,18 @@ knowledgeCmd
|
|
|
420
263
|
.requiredOption('-m, --message <msg>', 'The learning to record, as a rule plus its reason (max 300 chars)')
|
|
421
264
|
.option('--title <title>', 'Short title (used for decision headings)')
|
|
422
265
|
.option('-r, --repo <repo>', "Write to this repo's persistent base knowledge instead")
|
|
423
|
-
.action(async (workspace, options) => {
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
}
|
|
427
|
-
catch (error) {
|
|
428
|
-
if (error instanceof Error && error.message.includes('User force closed')) {
|
|
429
|
-
console.log('\nCancelled.');
|
|
430
|
-
process.exit(0);
|
|
431
|
-
}
|
|
432
|
-
console.error(error);
|
|
433
|
-
process.exit(1);
|
|
434
|
-
}
|
|
435
|
-
});
|
|
266
|
+
.action(runAction(async (workspace, options) => {
|
|
267
|
+
await knowledgeAddCommand(workspace, options);
|
|
268
|
+
}));
|
|
436
269
|
knowledgeCmd
|
|
437
270
|
.command('show')
|
|
438
271
|
.description("Print the workspace knowledge file (or a repo's base knowledge)")
|
|
439
272
|
.argument('[workspace]', 'Path to workspace (auto-detects from CWD)')
|
|
440
273
|
.option('-s, --section <name>', 'Only show one section')
|
|
441
274
|
.option('-r, --repo <repo>', "Show the repo's base knowledge file instead")
|
|
442
|
-
.action(async (workspace, options) => {
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
}
|
|
446
|
-
catch (error) {
|
|
447
|
-
if (error instanceof Error && error.message.includes('User force closed')) {
|
|
448
|
-
console.log('\nCancelled.');
|
|
449
|
-
process.exit(0);
|
|
450
|
-
}
|
|
451
|
-
console.error(error);
|
|
452
|
-
process.exit(1);
|
|
453
|
-
}
|
|
454
|
-
});
|
|
275
|
+
.action(runAction(async (workspace, options) => {
|
|
276
|
+
await knowledgeShowCommand(workspace, options);
|
|
277
|
+
}));
|
|
455
278
|
knowledgeCmd
|
|
456
279
|
.command('promote')
|
|
457
280
|
.description('Copy workspace learnings into per-repo base knowledge so they persist across features')
|
|
@@ -461,39 +284,9 @@ knowledgeCmd
|
|
|
461
284
|
.option('-m, --message <msg>', 'Promote this text directly (non-interactive)')
|
|
462
285
|
.option('--move', 'Remove the entry from the workspace file after promoting (default: copy)')
|
|
463
286
|
.option('--all', 'Promote all decisions, gotchas and assumptions without prompting')
|
|
464
|
-
.action(async (workspace, options) => {
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
}
|
|
468
|
-
catch (error) {
|
|
469
|
-
if (error instanceof Error && error.message.includes('User force closed')) {
|
|
470
|
-
console.log('\nCancelled.');
|
|
471
|
-
process.exit(0);
|
|
472
|
-
}
|
|
473
|
-
console.error(error);
|
|
474
|
-
process.exit(1);
|
|
475
|
-
}
|
|
476
|
-
});
|
|
477
|
-
/**
|
|
478
|
-
* Wraps a command action: clean exit on prompt cancellation (Ctrl+C inside an
|
|
479
|
-
* inquirer prompt), exit code 1 with the error otherwise. New command
|
|
480
|
-
* registrations should use this instead of copy-pasting the try/catch.
|
|
481
|
-
*/
|
|
482
|
-
function runAction(fn) {
|
|
483
|
-
return async (...args) => {
|
|
484
|
-
try {
|
|
485
|
-
await fn(...args);
|
|
486
|
-
}
|
|
487
|
-
catch (error) {
|
|
488
|
-
if (error instanceof Error && error.message.includes('User force closed')) {
|
|
489
|
-
console.log('\nCancelled.');
|
|
490
|
-
process.exit(0);
|
|
491
|
-
}
|
|
492
|
-
console.error(error);
|
|
493
|
-
process.exit(1);
|
|
494
|
-
}
|
|
495
|
-
};
|
|
496
|
-
}
|
|
287
|
+
.action(runAction(async (workspace, options) => {
|
|
288
|
+
await knowledgePromoteCommand(workspace, options);
|
|
289
|
+
}));
|
|
497
290
|
// Project command group
|
|
498
291
|
const projectCmd = program
|
|
499
292
|
.command('project')
|
|
@@ -532,216 +325,76 @@ strategyCmd
|
|
|
532
325
|
.command('list')
|
|
533
326
|
.alias('ls')
|
|
534
327
|
.description('List all available strategy templates (built-in and custom)')
|
|
535
|
-
.action(
|
|
536
|
-
try {
|
|
537
|
-
await strategyListCommand();
|
|
538
|
-
}
|
|
539
|
-
catch (error) {
|
|
540
|
-
if (error instanceof Error && error.message.includes('User force closed')) {
|
|
541
|
-
console.log('\nCancelled.');
|
|
542
|
-
process.exit(0);
|
|
543
|
-
}
|
|
544
|
-
console.error(error);
|
|
545
|
-
process.exit(1);
|
|
546
|
-
}
|
|
547
|
-
});
|
|
328
|
+
.action(runAction(strategyListCommand));
|
|
548
329
|
strategyCmd
|
|
549
330
|
.command('create')
|
|
550
331
|
.description('Create a new custom strategy template')
|
|
551
332
|
.option('-n, --name <name>', 'Strategy name')
|
|
552
333
|
.option('-f, --file <path>', 'Load content from a .md or .txt file')
|
|
553
|
-
.action(
|
|
554
|
-
try {
|
|
555
|
-
await strategyCreateCommand(options);
|
|
556
|
-
}
|
|
557
|
-
catch (error) {
|
|
558
|
-
if (error instanceof Error && error.message.includes('User force closed')) {
|
|
559
|
-
console.log('\nCancelled.');
|
|
560
|
-
process.exit(0);
|
|
561
|
-
}
|
|
562
|
-
console.error(error);
|
|
563
|
-
process.exit(1);
|
|
564
|
-
}
|
|
565
|
-
});
|
|
334
|
+
.action(runAction(strategyCreateCommand));
|
|
566
335
|
strategyCmd
|
|
567
336
|
.command('edit')
|
|
568
337
|
.description('Edit an existing custom strategy template')
|
|
569
338
|
.option('--id <id>', 'Template ID to edit (skips the selection prompt)')
|
|
570
|
-
.action(
|
|
571
|
-
try {
|
|
572
|
-
await strategyEditCommand(options);
|
|
573
|
-
}
|
|
574
|
-
catch (error) {
|
|
575
|
-
if (error instanceof Error && error.message.includes('User force closed')) {
|
|
576
|
-
console.log('\nCancelled.');
|
|
577
|
-
process.exit(0);
|
|
578
|
-
}
|
|
579
|
-
console.error(error);
|
|
580
|
-
process.exit(1);
|
|
581
|
-
}
|
|
582
|
-
});
|
|
339
|
+
.action(runAction(strategyEditCommand));
|
|
583
340
|
strategyCmd
|
|
584
341
|
.command('delete')
|
|
585
342
|
.alias('rm')
|
|
586
343
|
.description('Delete a custom strategy template')
|
|
587
344
|
.option('--id <id>', 'Template ID to delete (skips the selection prompt)')
|
|
588
345
|
.option('-y, --yes', 'Skip confirmation prompt')
|
|
589
|
-
.action(
|
|
590
|
-
try {
|
|
591
|
-
await strategyDeleteCommand(options);
|
|
592
|
-
}
|
|
593
|
-
catch (error) {
|
|
594
|
-
if (error instanceof Error && error.message.includes('User force closed')) {
|
|
595
|
-
console.log('\nCancelled.');
|
|
596
|
-
process.exit(0);
|
|
597
|
-
}
|
|
598
|
-
console.error(error);
|
|
599
|
-
process.exit(1);
|
|
600
|
-
}
|
|
601
|
-
});
|
|
346
|
+
.action(runAction(strategyDeleteCommand));
|
|
602
347
|
strategyCmd
|
|
603
348
|
.command('show')
|
|
604
349
|
.description('Display the full content of a strategy template')
|
|
605
350
|
.option('--id <id>', 'Template ID to show (skips the selection prompt)')
|
|
606
|
-
.action(
|
|
607
|
-
try {
|
|
608
|
-
await strategyShowCommand(options);
|
|
609
|
-
}
|
|
610
|
-
catch (error) {
|
|
611
|
-
if (error instanceof Error && error.message.includes('User force closed')) {
|
|
612
|
-
console.log('\nCancelled.');
|
|
613
|
-
process.exit(0);
|
|
614
|
-
}
|
|
615
|
-
console.error(error);
|
|
616
|
-
process.exit(1);
|
|
617
|
-
}
|
|
618
|
-
});
|
|
351
|
+
.action(runAction(strategyShowCommand));
|
|
619
352
|
program
|
|
620
353
|
.command('desktop')
|
|
621
354
|
.description('Launch the NexusFlow desktop application')
|
|
622
|
-
.action(
|
|
623
|
-
try {
|
|
624
|
-
await desktopCommand();
|
|
625
|
-
}
|
|
626
|
-
catch (error) {
|
|
627
|
-
console.error(error);
|
|
628
|
-
process.exit(1);
|
|
629
|
-
}
|
|
630
|
-
});
|
|
355
|
+
.action(runAction(desktopCommand));
|
|
631
356
|
// Config command group
|
|
632
357
|
const configCmd = program.command('config').description('View and update NexusFlow configuration');
|
|
633
358
|
configCmd
|
|
634
359
|
.command('show')
|
|
635
360
|
.description('Display the current configuration')
|
|
636
|
-
.action(
|
|
637
|
-
try {
|
|
638
|
-
await configShowCommand();
|
|
639
|
-
}
|
|
640
|
-
catch (error) {
|
|
641
|
-
console.error(error);
|
|
642
|
-
process.exit(1);
|
|
643
|
-
}
|
|
644
|
-
});
|
|
361
|
+
.action(runAction(configShowCommand));
|
|
645
362
|
configCmd
|
|
646
363
|
.command('get')
|
|
647
364
|
.description('Get a specific configuration key')
|
|
648
365
|
.argument('<key>', 'Configuration key to read')
|
|
649
|
-
.action(
|
|
650
|
-
try {
|
|
651
|
-
await configGetCommand(key);
|
|
652
|
-
}
|
|
653
|
-
catch (error) {
|
|
654
|
-
console.error(error);
|
|
655
|
-
process.exit(1);
|
|
656
|
-
}
|
|
657
|
-
});
|
|
366
|
+
.action(runAction(configGetCommand));
|
|
658
367
|
configCmd
|
|
659
368
|
.command('set')
|
|
660
369
|
.description('Set a configuration key to a value')
|
|
661
370
|
.argument('<key>', 'Configuration key to set')
|
|
662
371
|
.argument('<value>', 'Value to assign')
|
|
663
|
-
.action(
|
|
664
|
-
try {
|
|
665
|
-
await configSetCommand(key, value);
|
|
666
|
-
}
|
|
667
|
-
catch (error) {
|
|
668
|
-
console.error(error);
|
|
669
|
-
process.exit(1);
|
|
670
|
-
}
|
|
671
|
-
});
|
|
372
|
+
.action(runAction(configSetCommand));
|
|
672
373
|
// Default action when 'nexusflow config' is run without a subcommand
|
|
673
|
-
configCmd.action(
|
|
674
|
-
try {
|
|
675
|
-
await configShowCommand();
|
|
676
|
-
}
|
|
677
|
-
catch (error) {
|
|
678
|
-
console.error(error);
|
|
679
|
-
process.exit(1);
|
|
680
|
-
}
|
|
681
|
-
});
|
|
374
|
+
configCmd.action(runAction(configShowCommand));
|
|
682
375
|
// Adapter command group
|
|
683
376
|
const adapterCmd = program.command('adapter').description('Manage storage adapters — list, switch, configure, or create new ones');
|
|
684
377
|
adapterCmd
|
|
685
378
|
.command('list')
|
|
686
379
|
.description('List all available storage adapters')
|
|
687
|
-
.action(
|
|
688
|
-
try {
|
|
689
|
-
await adapterListCommand();
|
|
690
|
-
}
|
|
691
|
-
catch (error) {
|
|
692
|
-
console.error(error);
|
|
693
|
-
process.exit(1);
|
|
694
|
-
}
|
|
695
|
-
});
|
|
380
|
+
.action(runAction(adapterListCommand));
|
|
696
381
|
adapterCmd
|
|
697
382
|
.command('use')
|
|
698
383
|
.description('Switch to a different storage adapter (prompts for config if needed)')
|
|
699
384
|
.argument('<name>', 'Adapter name to activate')
|
|
700
|
-
.action(
|
|
701
|
-
try {
|
|
702
|
-
await adapterUseCommand(name);
|
|
703
|
-
}
|
|
704
|
-
catch (error) {
|
|
705
|
-
console.error(error);
|
|
706
|
-
process.exit(1);
|
|
707
|
-
}
|
|
708
|
-
});
|
|
385
|
+
.action(runAction(adapterUseCommand));
|
|
709
386
|
adapterCmd
|
|
710
387
|
.command('info')
|
|
711
388
|
.description('Show detailed information about an adapter')
|
|
712
389
|
.argument('<name>', 'Adapter name to inspect')
|
|
713
|
-
.action(
|
|
714
|
-
try {
|
|
715
|
-
await adapterInfoCommand(name);
|
|
716
|
-
}
|
|
717
|
-
catch (error) {
|
|
718
|
-
console.error(error);
|
|
719
|
-
process.exit(1);
|
|
720
|
-
}
|
|
721
|
-
});
|
|
390
|
+
.action(runAction(adapterInfoCommand));
|
|
722
391
|
adapterCmd
|
|
723
392
|
.command('init')
|
|
724
393
|
.description('Scaffold a new adapter plugin project')
|
|
725
394
|
.argument('<name>', 'Name for the new adapter')
|
|
726
|
-
.action(
|
|
727
|
-
try {
|
|
728
|
-
await adapterInitCommand(name);
|
|
729
|
-
}
|
|
730
|
-
catch (error) {
|
|
731
|
-
console.error(error);
|
|
732
|
-
process.exit(1);
|
|
733
|
-
}
|
|
734
|
-
});
|
|
395
|
+
.action(runAction(adapterInitCommand));
|
|
735
396
|
// Default action when 'nexusflow adapter' is run without a subcommand
|
|
736
|
-
adapterCmd.action(
|
|
737
|
-
try {
|
|
738
|
-
await adapterListCommand();
|
|
739
|
-
}
|
|
740
|
-
catch (error) {
|
|
741
|
-
console.error(error);
|
|
742
|
-
process.exit(1);
|
|
743
|
-
}
|
|
744
|
-
});
|
|
397
|
+
adapterCmd.action(runAction(adapterListCommand));
|
|
745
398
|
// Schedule command group
|
|
746
399
|
const scheduleCmd = program
|
|
747
400
|
.command('schedule')
|
|
@@ -752,124 +405,55 @@ scheduleCmd
|
|
|
752
405
|
.argument('[workspace]', 'Path to workspace (auto-detects from CWD)')
|
|
753
406
|
.option('-t, --task <task>', 'Job to run: "sync" or "refresh"', 'sync')
|
|
754
407
|
.requiredOption('-e, --every <interval>', 'How often to run, e.g. 30m, 2h, 1d')
|
|
755
|
-
.action(async (workspace, options) => {
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
}
|
|
759
|
-
catch (error) {
|
|
760
|
-
if (error instanceof Error && error.message.includes('User force closed')) {
|
|
761
|
-
console.log('\nCancelled.');
|
|
762
|
-
process.exit(0);
|
|
763
|
-
}
|
|
764
|
-
console.error(error);
|
|
765
|
-
process.exit(1);
|
|
766
|
-
}
|
|
767
|
-
});
|
|
408
|
+
.action(runAction(async (workspace, options) => {
|
|
409
|
+
await scheduleAddCommand(workspace, options);
|
|
410
|
+
}));
|
|
768
411
|
scheduleCmd
|
|
769
412
|
.command('list')
|
|
770
413
|
.alias('ls')
|
|
771
414
|
.description('List all scheduled jobs')
|
|
772
|
-
.
|
|
773
|
-
|
|
774
|
-
await scheduleListCommand();
|
|
775
|
-
}
|
|
776
|
-
catch (error) {
|
|
777
|
-
console.error(error);
|
|
778
|
-
process.exit(1);
|
|
779
|
-
}
|
|
780
|
-
});
|
|
415
|
+
.option('--json', 'Output in JSON format')
|
|
416
|
+
.action(runAction(scheduleListCommand));
|
|
781
417
|
scheduleCmd
|
|
782
418
|
.command('remove')
|
|
783
419
|
.alias('rm')
|
|
784
420
|
.description('Remove a scheduled job')
|
|
785
421
|
.argument('<id>', 'Job id (see "nexusflow schedule list")')
|
|
786
|
-
.action(
|
|
787
|
-
try {
|
|
788
|
-
await scheduleRemoveCommand(id);
|
|
789
|
-
}
|
|
790
|
-
catch (error) {
|
|
791
|
-
console.error(error);
|
|
792
|
-
process.exit(1);
|
|
793
|
-
}
|
|
794
|
-
});
|
|
422
|
+
.action(runAction(scheduleRemoveCommand));
|
|
795
423
|
scheduleCmd
|
|
796
424
|
.command('enable')
|
|
797
425
|
.description('Enable a scheduled job')
|
|
798
426
|
.argument('<id>', 'Job id (see "nexusflow schedule list")')
|
|
799
|
-
.action(async (id) => {
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
}
|
|
803
|
-
catch (error) {
|
|
804
|
-
console.error(error);
|
|
805
|
-
process.exit(1);
|
|
806
|
-
}
|
|
807
|
-
});
|
|
427
|
+
.action(runAction(async (id) => {
|
|
428
|
+
await scheduleToggleCommand(id, true);
|
|
429
|
+
}));
|
|
808
430
|
scheduleCmd
|
|
809
431
|
.command('disable')
|
|
810
432
|
.description('Disable a scheduled job without removing it')
|
|
811
433
|
.argument('<id>', 'Job id (see "nexusflow schedule list")')
|
|
812
|
-
.action(async (id) => {
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
}
|
|
816
|
-
catch (error) {
|
|
817
|
-
console.error(error);
|
|
818
|
-
process.exit(1);
|
|
819
|
-
}
|
|
820
|
-
});
|
|
434
|
+
.action(runAction(async (id) => {
|
|
435
|
+
await scheduleToggleCommand(id, false);
|
|
436
|
+
}));
|
|
821
437
|
scheduleCmd
|
|
822
438
|
.command('run')
|
|
823
439
|
.description('Run a scheduled job immediately')
|
|
824
440
|
.argument('<id>', 'Job id (see "nexusflow schedule list")')
|
|
825
|
-
.action(
|
|
826
|
-
try {
|
|
827
|
-
await scheduleRunCommand(id);
|
|
828
|
-
}
|
|
829
|
-
catch (error) {
|
|
830
|
-
console.error(error);
|
|
831
|
-
process.exit(1);
|
|
832
|
-
}
|
|
833
|
-
});
|
|
441
|
+
.action(runAction(scheduleRunCommand));
|
|
834
442
|
// Default action when 'nexusflow schedule' is run without a subcommand
|
|
835
|
-
scheduleCmd.action(
|
|
836
|
-
try {
|
|
837
|
-
await scheduleListCommand();
|
|
838
|
-
}
|
|
839
|
-
catch (error) {
|
|
840
|
-
console.error(error);
|
|
841
|
-
process.exit(1);
|
|
842
|
-
}
|
|
843
|
-
});
|
|
443
|
+
scheduleCmd.action(runAction(scheduleListCommand));
|
|
844
444
|
const mcp = program.command('mcp').description('Manage the NexusFlow MCP Server for AI assistants');
|
|
845
445
|
mcp
|
|
846
446
|
.command('run')
|
|
847
447
|
.description('Start the NexusFlow MCP Server (typically called automatically by AI assistants)')
|
|
848
448
|
.argument('[workspace]', 'Path to workspace (auto-detects from CWD)')
|
|
849
|
-
.action(
|
|
850
|
-
try {
|
|
851
|
-
await mcpRunCommand(workspace);
|
|
852
|
-
}
|
|
853
|
-
catch (error) {
|
|
854
|
-
console.error(error);
|
|
855
|
-
process.exit(1);
|
|
856
|
-
}
|
|
857
|
-
});
|
|
449
|
+
.action(runAction(mcpRunCommand));
|
|
858
450
|
mcp
|
|
859
451
|
.command('setup')
|
|
860
452
|
.description('Automatically configure your AI environments (Claude Desktop, Cursor, VS Code) to use the NexusFlow MCP Server')
|
|
861
|
-
.action(
|
|
862
|
-
try {
|
|
863
|
-
await mcpSetupCommand();
|
|
864
|
-
}
|
|
865
|
-
catch (error) {
|
|
866
|
-
console.error(error);
|
|
867
|
-
process.exit(1);
|
|
868
|
-
}
|
|
869
|
-
});
|
|
453
|
+
.action(runAction(mcpSetupCommand));
|
|
870
454
|
program.hook('postAction', async (thisCommand, actionCommand) => {
|
|
871
|
-
// Skip update check for MCP
|
|
872
|
-
if (actionCommand.name() === 'run' && actionCommand.parent?.name() === 'mcp') {
|
|
455
|
+
// Skip update check for non-TTY streams and MCP runs to prevent contaminating stdout stream
|
|
456
|
+
if (!process.stdout.isTTY || (actionCommand.name() === 'run' && actionCommand.parent?.name() === 'mcp')) {
|
|
873
457
|
return;
|
|
874
458
|
}
|
|
875
459
|
try {
|