@crewx/cli 0.9.0-rc.15 → 0.9.0-rc.150

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 (73) hide show
  1. package/dist/bootstrap/codex-writable-roots.d.ts +20 -1
  2. package/dist/bootstrap/codex-writable-roots.js +1 -88
  3. package/dist/bootstrap/crewx-cli.js +1 -63
  4. package/dist/builtin.d.ts +1 -1
  5. package/dist/builtin.js +5 -127
  6. package/dist/commands/agent.js +4 -224
  7. package/dist/commands/cal.d.ts +15 -0
  8. package/dist/commands/cal.js +2 -0
  9. package/dist/commands/db.d.ts +3 -0
  10. package/dist/commands/db.js +59 -125
  11. package/dist/commands/detached.d.ts +95 -0
  12. package/dist/commands/detached.js +15 -0
  13. package/dist/commands/doctor.d.ts +77 -0
  14. package/dist/commands/doctor.js +4 -196
  15. package/dist/commands/emit-trailer.d.ts +25 -0
  16. package/dist/commands/emit-trailer.js +2 -0
  17. package/dist/commands/execute.d.ts +8 -4
  18. package/dist/commands/execute.js +15 -146
  19. package/dist/commands/hook/command-marker.d.ts +2 -0
  20. package/dist/commands/hook/command-marker.js +1 -0
  21. package/dist/commands/hook/install.d.ts +0 -1
  22. package/dist/commands/hook/install.js +8 -175
  23. package/dist/commands/hook/paths.js +1 -94
  24. package/dist/commands/hook/status.js +1 -86
  25. package/dist/commands/hook/uninstall.js +1 -71
  26. package/dist/commands/hook-dispatch.js +2 -180
  27. package/dist/commands/init.d.ts +34 -0
  28. package/dist/commands/init.js +37 -370
  29. package/dist/commands/kill.d.ts +2 -8
  30. package/dist/commands/kill.js +1 -52
  31. package/dist/commands/log.js +3 -95
  32. package/dist/commands/parse-agent-message.js +1 -52
  33. package/dist/commands/parse-common-flags.d.ts +5 -1
  34. package/dist/commands/parse-common-flags.js +3 -181
  35. package/dist/commands/ps.d.ts +2 -2
  36. package/dist/commands/ps.js +2 -107
  37. package/dist/commands/publish.d.ts +1 -0
  38. package/dist/commands/publish.js +27 -0
  39. package/dist/commands/query.d.ts +7 -2
  40. package/dist/commands/query.js +16 -146
  41. package/dist/commands/registry.js +1 -31
  42. package/dist/commands/resolve-prompt.js +3 -54
  43. package/dist/commands/resolve-recipient.d.ts +14 -0
  44. package/dist/commands/resolve-recipient.js +3 -0
  45. package/dist/commands/restart.d.ts +3 -1
  46. package/dist/commands/restart.js +18 -162
  47. package/dist/commands/result.d.ts +8 -3
  48. package/dist/commands/result.js +1 -70
  49. package/dist/commands/shortcut.d.ts +1 -0
  50. package/dist/commands/shortcut.js +18 -0
  51. package/dist/commands/slack.js +16 -559
  52. package/dist/commands/stop.d.ts +8 -0
  53. package/dist/commands/stop.js +8 -0
  54. package/dist/commands/write-output.js +1 -24
  55. package/dist/index.d.ts +1 -1
  56. package/dist/index.js +1 -5
  57. package/dist/logging.d.ts +1 -1
  58. package/dist/logging.js +10 -86
  59. package/dist/main.d.ts +3 -2
  60. package/dist/main.js +44 -253
  61. package/dist/register-builtin-tools.js +1 -9
  62. package/dist/slack/file-download.js +1 -134
  63. package/dist/slack/markdown.js +1 -33
  64. package/dist/utils/env-defaults.d.ts +2 -5
  65. package/dist/utils/env-defaults.js +1 -10
  66. package/dist/utils/inherited-trace.d.ts +24 -0
  67. package/dist/utils/inherited-trace.js +1 -25
  68. package/dist/utils/product-package-root.d.ts +6 -0
  69. package/dist/utils/product-package-root.js +1 -0
  70. package/dist/utils/sdk-compat.d.ts +24 -0
  71. package/dist/utils/sdk-compat.js +1 -0
  72. package/dist/utils/version.js +1 -28
  73. package/package.json +16 -12
package/dist/logging.js CHANGED
@@ -1,86 +1,10 @@
1
- "use strict";
2
- /**
3
- * CLI file-based logging for CrewX SDK events.
4
- *
5
- * Subscribe to task:start / task:end events from a Crewx instance
6
- * and write structured log files to .crewx/logs/ in the workspace root.
7
- *
8
- * File name format: {YYYYMMDDTHHmmss}_{traceId}.log
9
- * e.g. 20260412T145044_tsk_AbCdEfGh.log
10
- *
11
- * Format mirrors cli-bak TaskManagementService for backward compatibility.
12
- */
13
- Object.defineProperty(exports, "__esModule", { value: true });
14
- exports.attachFileLogger = attachFileLogger;
15
- const fs_1 = require("fs");
16
- const path_1 = require("path");
17
- const CREWX_VERSION = '0.9.0-alpha.1';
18
- /** Format Date as YYYYMMDDTHHmmss (local time) */
19
- function formatTimestamp(date) {
20
- const pad = (n) => String(n).padStart(2, '0');
21
- return (`${date.getFullYear()}` +
22
- `${pad(date.getMonth() + 1)}` +
23
- `${pad(date.getDate())}` +
24
- `T${pad(date.getHours())}` +
25
- `${pad(date.getMinutes())}` +
26
- `${pad(date.getSeconds())}`);
27
- }
28
- function ensureLogsDir(logsDir) {
29
- if (!(0, fs_1.existsSync)(logsDir)) {
30
- (0, fs_1.mkdirSync)(logsDir, { recursive: true });
31
- }
32
- }
33
- /**
34
- * Attach file-based logging to a Crewx instance.
35
- * Subscribes to task:start and task:end events and writes log files.
36
- *
37
- * @param crewx - The Crewx instance to attach logging to
38
- * @param workspaceRoot - Root directory for .crewx/logs/ (default: process.cwd())
39
- * @returns Cleanup function that removes all event listeners
40
- */
41
- function attachFileLogger(crewx, workspaceRoot) {
42
- const logsDir = (0, path_1.join)(workspaceRoot ?? process.cwd(), '.crewx', 'logs');
43
- // traceId → absolute log file path (in-memory map for the process lifetime)
44
- const logFiles = new Map();
45
- const unsubStart = crewx.on('task:start', (event) => {
46
- try {
47
- ensureLogsDir(logsDir);
48
- const ts = formatTimestamp(event.timestamp);
49
- const logFile = (0, path_1.join)(logsDir, `${ts}_${event.traceId}.log`);
50
- logFiles.set(event.traceId, logFile);
51
- const header = `=== TASK LOG: ${event.traceId} ===\n` +
52
- `CrewX Version: ${CREWX_VERSION}\n` +
53
- `Mode: ${event.mode}\n` +
54
- `Agent: ${event.agentRef}\n` +
55
- `Started: ${event.timestamp.toLocaleString()}\n` +
56
- `Message: ${event.message}\n` +
57
- `\n`;
58
- (0, fs_1.writeFileSync)(logFile, header, { encoding: 'utf8', mode: 0o600 });
59
- }
60
- catch {
61
- // Non-fatal: CLI logging must never crash the main process
62
- }
63
- });
64
- const unsubEnd = crewx.on('task:end', (event) => {
65
- try {
66
- const logFile = logFiles.get(event.traceId);
67
- if (!logFile)
68
- return;
69
- const ts = new Date().toLocaleString();
70
- const status = event.error
71
- ? `failed: ${event.error.message}`
72
- : 'completed successfully';
73
- const completion = `[${ts}] INFO: Task ${status} in ${event.durationMs}ms\n` +
74
- `[${ts}] INFO: Process closed with exit code: ${event.error ? 1 : 0}\n`;
75
- (0, fs_1.appendFileSync)(logFile, completion, 'utf8');
76
- logFiles.delete(event.traceId);
77
- }
78
- catch {
79
- // Non-fatal
80
- }
81
- });
82
- return () => {
83
- unsubStart();
84
- unsubEnd();
85
- };
86
- }
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.attachFileLogger=S;const c=require("fs");const u=require("path");const l=require("@crewx/sdk");const $="0.9.0-alpha.1";function p(e){const s=o=>String(o).padStart(2,"0");return`${e.getFullYear()}${s(e.getMonth()+1)}${s(e.getDate())}T${s(e.getHours())}${s(e.getMinutes())}${s(e.getSeconds())}`}function f(e){if(!(0,c.existsSync)(e)){(0,c.mkdirSync)(e,{recursive:true})}}function S(e,s){const o=(0,u.join)(s??process.cwd(),".crewx","logs");const a=new Map;const g=e.on("task:start",t=>{try{f(o);const n=p(t.timestamp);const r=(0,u.join)(o,`${n}_${t.traceId}.log`);a.set(t.traceId,r);const i=`=== TASK LOG: ${t.traceId} ===
2
+ CrewX Version: ${$}
3
+ Mode: ${t.mode}
4
+ Agent: ${t.agentRef}
5
+ Started: ${(0,l.formatDisplayTimestamp)(t.timestamp)}
6
+ Message: ${t.message}
7
+
8
+ `;(0,c.writeFileSync)(r,i,{encoding:"utf8",mode:384})}catch{}});const d=e.on("task:end",t=>{try{const n=a.get(t.traceId);if(!n)return;const r=(0,l.formatDisplayTimestamp)(new Date);const i=t.error?`failed: ${t.error.message}`:"completed successfully";const m=`[${r}] INFO: Task ${i} in ${t.durationMs}ms
9
+ [${r}] INFO: Process closed with exit code: ${t.error?1:0}
10
+ `;(0,c.appendFileSync)(n,m,"utf8");a.delete(t.traceId)}catch{}});return()=>{g();d()}}
package/dist/main.d.ts CHANGED
@@ -5,7 +5,8 @@
5
5
  *
6
6
  * Boot sequence:
7
7
  * 1. Inject CREWX_CLI / CREWX_WORKSPACE env defaults (must be first)
8
- * 2. Parse command
9
- * 3. Dispatch to handler
8
+ * 2. Load workspace and ~/.crewx .env files (does not override process.env)
9
+ * 3. Parse command
10
+ * 4. Dispatch to handler
10
11
  */
11
12
  export {};
package/dist/main.js CHANGED
@@ -1,242 +1,8 @@
1
1
  #!/usr/bin/env node
2
- "use strict";
3
- /**
4
- * CrewX CLI entry point.
5
- * Dispatches commands to the appropriate handler.
6
- *
7
- * Boot sequence:
8
- * 1. Inject CREWX_CLI / CREWX_WORKSPACE env defaults (must be first)
9
- * 2. Parse command
10
- * 3. Dispatch to handler
11
- */
12
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
13
- if (k2 === undefined) k2 = k;
14
- var desc = Object.getOwnPropertyDescriptor(m, k);
15
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
16
- desc = { enumerable: true, get: function() { return m[k]; } };
17
- }
18
- Object.defineProperty(o, k2, desc);
19
- }) : (function(o, m, k, k2) {
20
- if (k2 === undefined) k2 = k;
21
- o[k2] = m[k];
22
- }));
23
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
24
- Object.defineProperty(o, "default", { enumerable: true, value: v });
25
- }) : function(o, v) {
26
- o["default"] = v;
27
- });
28
- var __importStar = (this && this.__importStar) || (function () {
29
- var ownKeys = function(o) {
30
- ownKeys = Object.getOwnPropertyNames || function (o) {
31
- var ar = [];
32
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
33
- return ar;
34
- };
35
- return ownKeys(o);
36
- };
37
- return function (mod) {
38
- if (mod && mod.__esModule) return mod;
39
- var result = {};
40
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
41
- __setModuleDefault(result, mod);
42
- return result;
43
- };
44
- })();
45
- Object.defineProperty(exports, "__esModule", { value: true });
46
- // ─── P0-1: Env Bootstrap ─────────────────────────────────────────────────────
47
- // Must run before any other code that might use process.env.CREWX_CLI.
48
- const env_defaults_1 = require("./utils/env-defaults");
49
- const sdk_1 = require("@crewx/sdk");
50
- process.env.CREWX_CLI ??= (0, env_defaults_1.resolveCrewxCli)();
51
- process.env.CREWX_WORKSPACE ??= (0, env_defaults_1.resolveCrewxWorkspace)();
52
- // ─── Pricing remote override (WI-20260701-002) ───────────────────────────────
53
- // Best-effort, non-blocking: fetch remote model registry so new models get
54
- // accurate pricing without a CLI republish. Falls back to bundled table on
55
- // failure / offline. Browser entry does not call this automatically.
56
- void (0, sdk_1.initPricingRemote)();
57
- // ─── Command Imports ──────────────────────────────────────────────────────────
58
- const query_1 = require("./commands/query");
59
- const execute_1 = require("./commands/execute");
60
- const agent_1 = require("./commands/agent");
61
- const ps_1 = require("./commands/ps");
62
- const kill_1 = require("./commands/kill");
63
- const result_1 = require("./commands/result");
64
- const restart_1 = require("./commands/restart");
65
- const log_1 = require("./commands/log");
66
- const doctor_1 = require("./commands/doctor");
67
- const init_1 = require("./commands/init");
68
- const builtin_1 = require("./builtin");
69
- const slack_1 = require("./commands/slack");
70
- const install_1 = require("./commands/hook/install");
71
- const uninstall_1 = require("./commands/hook/uninstall");
72
- const status_1 = require("./commands/hook/status");
73
- const hook_dispatch_1 = require("./commands/hook-dispatch");
74
- const db_1 = require("./commands/db");
75
- const parse_common_flags_1 = require("./commands/parse-common-flags");
76
- const registry_1 = require("./commands/registry");
77
- const version_1 = require("./utils/version");
78
- /**
79
- * Dev-only SSOT assertion: bin/cli-commands.js must be the exact union of
80
- * KNOWN_COMMANDS ∪ BUILTIN_COMMAND_NAMES ∪ NOT_YET_MIGRATED from registry.ts.
81
- * Throws on drift so the discrepancy is caught immediately during development.
82
- */
83
- async function assertSsotParity() {
84
- const { join } = await Promise.resolve().then(() => __importStar(require('path')));
85
- // eslint-disable-next-line @typescript-eslint/no-require-imports
86
- const { createRequire } = require('module');
87
- // Use createRequire(__filename) + plain path to avoid TypeScript compiling import() → require()
88
- // in the CJS dist. Node.js 22.12+ supports require(esm), so this loads ESM cli-commands.js fine.
89
- const req = createRequire(__filename);
90
- const cliCommandsPath = join(__dirname, '../../../bin/cli-commands.js');
91
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
92
- const { CLI_SUBCOMMANDS } = req(cliCommandsPath);
93
- const union = new Set([...registry_1.KNOWN_COMMANDS, ...registry_1.BUILTIN_COMMAND_NAMES, ...registry_1.NOT_YET_MIGRATED]);
94
- const missing = [...union].filter((c) => !CLI_SUBCOMMANDS.has(c));
95
- const extra = [...CLI_SUBCOMMANDS].filter((c) => !union.has(c));
96
- if (missing.length > 0 || extra.length > 0) {
97
- throw new Error(`[crewx dev] SSOT drift detected!\n` +
98
- (missing.length ? ` registry has, CLI_SUBCOMMANDS missing: ${missing.join(', ')}\n` : '') +
99
- (extra.length ? ` CLI_SUBCOMMANDS has, registry missing: ${extra.join(', ')}` : ''));
100
- }
101
- }
102
- async function main() {
103
- if (process.env['NODE_ENV'] === 'development') {
104
- await assertSsotParity();
105
- }
106
- const args = process.argv.slice(2);
107
- const command = args[0];
108
- if (!command) {
109
- printHelp();
110
- process.exit(0);
111
- }
112
- // Built-in tools: memory, search, doc, wbs, cron, workflow, skill
113
- if (builtin_1.BUILTIN_COMMANDS.has(command)) {
114
- await (0, builtin_1.handleBuiltin)(command, args.slice(1));
115
- return;
116
- }
117
- // Core commands
118
- switch (command) {
119
- // P0-2: q/x aliases
120
- case 'q':
121
- case 'query':
122
- await (0, query_1.handleQuery)(args.slice(1));
123
- return;
124
- case 'x':
125
- case 'execute':
126
- await (0, execute_1.handleExecute)(args.slice(1));
127
- return;
128
- case 'agent':
129
- await (0, agent_1.handleAgent)(args.slice(1));
130
- return;
131
- // P0-4: ps
132
- case 'ps':
133
- await (0, ps_1.handlePs)(args.slice(1));
134
- return;
135
- // P0-5: kill
136
- case 'kill':
137
- await (0, kill_1.handleKill)(args.slice(1));
138
- return;
139
- // P0-6: result
140
- case 'result':
141
- await (0, result_1.handleResult)(args.slice(1));
142
- return;
143
- // CLI Task Lifecycle 2단계: restart a failed task as a new task
144
- case 'restart':
145
- await (0, restart_1.handleRestart)(args.slice(1));
146
- return;
147
- // P1-1: log
148
- case 'log':
149
- await (0, log_1.handleLog)(args.slice(1));
150
- return;
151
- // P1-1: doctor
152
- case 'doctor':
153
- await (0, doctor_1.handleDoctor)(args.slice(1));
154
- return;
155
- // P1-1: init
156
- case 'init': {
157
- const initArgs = args.slice(1);
158
- const force = initArgs.includes('--force') || initArgs.includes('-f');
159
- try {
160
- const r = await (0, init_1.handleInit)({ path: process.cwd(), force });
161
- if (r.skippedReason === 'yaml-exists') {
162
- console.log('✓ crewx.yaml already exists (use --force to overwrite)');
163
- }
164
- else {
165
- console.log(r.yamlCreated ? '✓ crewx.yaml created' : '✓ yaml skipped');
166
- console.log(r.hookInstalled ? '✓ hook installed' : '⚠ hook skipped');
167
- if (r.errors.length > 0)
168
- console.warn('Warnings:', r.errors.join('; '));
169
- }
170
- if (r.workspaceId)
171
- console.log(`✓ workspace registered (id=${r.workspaceId}, slug=${r.slug})`);
172
- console.log('✓ done');
173
- }
174
- catch (e) {
175
- console.error('✗ init failed:', e.message);
176
- process.exit(1);
177
- }
178
- return;
179
- }
180
- // DB management: crewx db push [--force] [--dry-run]
181
- case 'db':
182
- await (0, db_1.handleDb)(args.slice(1));
183
- return;
184
- // SDK-009: slack / slack:files
185
- case 'slack':
186
- case 'slack:files':
187
- await (0, slack_1.handleSlack)(args.slice(1));
188
- return;
189
- // Hook Platform (Phase 0)
190
- case 'hook-dispatch':
191
- await (0, hook_dispatch_1.handleHookDispatch)(args.slice(1));
192
- return;
193
- case 'help':
194
- case '--help':
195
- case '-h':
196
- printHelp();
197
- return;
198
- case '--version':
199
- case '-v': {
200
- // eslint-disable-next-line @typescript-eslint/no-require-imports
201
- const pkg = require('../package.json');
202
- console.log(pkg.version);
203
- return;
204
- }
205
- }
206
- // Not yet migrated commands (SDK-009)
207
- if (registry_1.NOT_YET_MIGRATED.has(command)) {
208
- console.error(`Command '${command}' is not yet migrated in SDK refactor round. ` +
209
- 'See packages/cli-bak for reference.');
210
- process.exit(1);
211
- }
212
- // Hook subcommands: crewx hook install/uninstall/status
213
- if (command === 'hook') {
214
- const subcommand = args[1];
215
- const subArgs = args.slice(2);
216
- switch (subcommand) {
217
- case 'install':
218
- await (0, install_1.handleHookInstall)(subArgs);
219
- return;
220
- case 'uninstall':
221
- await (0, uninstall_1.handleHookUninstall)(subArgs);
222
- return;
223
- case 'status':
224
- await (0, status_1.handleHookStatus)(subArgs);
225
- return;
226
- default:
227
- console.error(`Unknown hook subcommand: ${subcommand ?? '(none)'}`);
228
- console.error('Usage: crewx hook install|uninstall|status');
229
- process.exit(1);
230
- }
231
- }
232
- // Unknown command
233
- console.error(`Unknown command: ${command}`);
234
- console.error('Run `crewx --help` for usage.');
235
- process.exit(1);
236
- }
237
- function printHelp() {
238
- console.log(`
239
- CrewX CLI v${version_1.CLI_VERSION}
2
+ "use strict";var w=exports&&exports.__createBinding||(Object.create?(function(r,e,o,t){if(t===void 0)t=o;var s=Object.getOwnPropertyDescriptor(e,o);if(!s||("get"in s?!e.__esModule:s.writable||s.configurable)){s={enumerable:true,get:function(){return e[o]}}}Object.defineProperty(r,t,s)}):(function(r,e,o,t){if(t===void 0)t=o;r[t]=e[o]}));var k=exports&&exports.__setModuleDefault||(Object.create?(function(r,e){Object.defineProperty(r,"default",{enumerable:true,value:e})}):function(r,e){r["default"]=e});var v=exports&&exports.__importStar||(function(){var r=function(e){r=Object.getOwnPropertyNames||function(o){var t=[];for(var s in o)if(Object.prototype.hasOwnProperty.call(o,s))t[t.length]=s;return t};return r(e)};return function(e){if(e&&e.__esModule)return e;var o={};if(e!=null){for(var t=r(e),s=0;s<t.length;s++)if(t[s]!=="default")w(o,e,t[s])}k(o,e);return o}})();Object.defineProperty(exports,"__esModule",{value:true});const u=require("./utils/sdk-compat");const _=require("@crewx/sdk/account");const y=require("@crewx/sdk");const b=require("./utils/inherited-trace");process.env.CREWX_CLI??=u.sdkCompat.resolveCrewxCli();process.env.CREWX_WORKSPACE??=u.sdkCompat.resolveCrewxWorkspace();(0,_.loadCrewxEnvFiles)();(0,b.consumeInheritedRunnerIdentity)();u.sdkCompat.initPricingRemote();const x=require("./commands/query");const q=require("./commands/execute");const S=require("./commands/agent");const C=require("./commands/ps");const d=require("./commands/stop");const O=require("./commands/result");const P=require("./commands/restart");const I=require("./commands/log");const D=require("./commands/doctor");const h=require("./commands/init");const E=require("./commands/shortcut");const R=require("./commands/publish");const p=require("./builtin");const M=require("./commands/slack");const j=require("./commands/hook/install");const N=require("./commands/hook/uninstall");const A=require("./commands/hook/status");const L=require("./commands/hook-dispatch");const T=require("./commands/db");const U=require("./commands/parse-common-flags");const c=require("./commands/registry");const B=require("./utils/version");const W=require("./utils/product-package-root");const g=require("./commands/emit-trailer");async function $(){const{join:r}=await Promise.resolve().then(()=>v(require("path")));const{createRequire:e}=require("module");const o=e(__filename);const t=r(__dirname,"../../../bin/cli-commands.js");const{CLI_SUBCOMMANDS:s}=o(t);const i=new Set([...c.KNOWN_COMMANDS,...c.BUILTIN_COMMAND_NAMES,...c.NOT_YET_MIGRATED]);const a=[...i].filter(l=>!s.has(l));const n=[...s].filter(l=>!i.has(l));if(a.length>0||n.length>0){throw new Error(`[crewx dev] SSOT drift detected!
3
+ `+(a.length?` registry has, CLI_SUBCOMMANDS missing: ${a.join(", ")}
4
+ `:"")+(n.length?` CLI_SUBCOMMANDS has, registry missing: ${n.join(", ")}`:""))}}async function F(r){if(process.env["NODE_ENV"]==="development"){await $()}const e=process.argv.slice(2);const o=e[0];if(!o){f();process.exit(0)}if(p.BUILTIN_COMMANDS.has(o)){const t=o==="skill"?(0,W.resolveProductRootFromCliEntry)(process.argv[1]):void 0;await(0,p.handleBuiltin)(o,e.slice(1),t);return}switch(o){case"q":case"query":await(0,x.handleQuery)(e.slice(1),o,r);return;case"x":case"execute":await(0,q.handleExecute)(e.slice(1),o,r);return;case"agent":await(0,S.handleAgent)(e.slice(1));return;case"ps":await(0,C.handlePs)(e.slice(1));return;case"stop":await(0,d.handleStop)(e.slice(1),"stop");return;case"kill":await(0,d.handleStop)(e.slice(1),"kill");return;case"result":await(0,O.handleResult)(e.slice(1));return;case"restart":await(0,P.handleRestart)(e.slice(1));return;case"log":await(0,I.handleLog)(e.slice(1));return;case"doctor":await(0,D.handleDoctor)(e.slice(1));return;case"init":{const t=e.slice(1);const s=t.includes("--force")||t.includes("-f");try{const i=(0,h.parseInitProvider)(t);const a=await(0,h.handleInit)({path:process.cwd(),force:s,provider:i});if(a.skippedReason==="yaml-exists"){console.log("\u2713 crewx.yaml already exists (use --force to overwrite)")}else{console.log(a.yamlCreated?"\u2713 crewx.yaml created":"\u2713 yaml skipped");console.log(a.hookInstalled?"\u2713 hook installed":"\u26A0 hook skipped");if(a.errors.length>0)console.warn("Warnings:",a.errors.join("; "))}const n=(0,y.getDefaultAgentProfile)(a.provider);if(n){console.log(`\u2713 default agents: ${a.provider} (${n.planner.model} / ${n.worker.model})`)}if(a.workspaceId)console.log(`\u2713 workspace registered (id=${a.workspaceId}, slug=${a.slug})`);console.log("\u2713 done")}catch(i){console.error("\u2717 init failed:",i.message);process.exit(1)}return}case"db":await(0,T.handleDb)(e.slice(1));return;case"shortcut":await(0,E.handleShortcut)(e.slice(1));return;case"publish":await(0,R.handlePublish)(e.slice(1));return;case"slack":case"slack:files":await(0,M.handleSlack)(e.slice(1));return;case"hook-dispatch":await(0,L.handleHookDispatch)(e.slice(1));return;case"help":case"--help":case"-h":f();return;case"--version":case"-v":{const t=require("../package.json");console.log(t.version);return}}if(c.NOT_YET_MIGRATED.has(o)){console.error(`Command '${o}' is not yet migrated in SDK refactor round. See packages/cli-bak for reference.`);process.exit(1)}if(o==="hook"){const t=e[1];const s=e.slice(2);switch(t){case"install":await(0,j.handleHookInstall)(s);return;case"uninstall":await(0,N.handleHookUninstall)(s);return;case"status":await(0,A.handleHookStatus)(s);return;default:console.error(`Unknown hook subcommand: ${t??"(none)"}`);console.error("Usage: crewx hook install|uninstall|status");process.exit(1)}}console.error(`Unknown command: ${o}`);console.error("Run `crewx --help` for usage.");process.exit(1)}function f(){console.log(`
5
+ CrewX CLI v${B.CLI_VERSION}
240
6
 
241
7
  Usage:
242
8
  crewx Launch web dashboard + open browser (default)
@@ -248,12 +14,14 @@ UI Modes:
248
14
  crewx electron [--overlay] Launch Electron (desktop or overlay window)
249
15
 
250
16
  Query / Execute:
251
- q|query "@agent <message>" Query an agent (quoted single string)
252
- x|execute "@agent <task>" Execute a task with an agent (quoted single string)
17
+ q|query --to <agent> <message> Query an agent
18
+ x|execute --to <agent> <task> Execute a task with an agent
253
19
 
254
- @agent is optional — defaults to @crewx when omitted.
20
+ Positional @agent <message> is shorthand for selecting a recipient.
21
+ Agent calls require a recipient; human terminal and cron calls default to @crewx.
255
22
 
256
23
  Common flags:
24
+ --to <agent> Explicit agent recipient
257
25
  --thread <name> Conversation thread
258
26
  --provider <cli/xxx> Provider override
259
27
  --metadata <json> Extra metadata (JSON object, double-quoted). Propagated to events/hooks/tracing.
@@ -264,10 +32,16 @@ Query / Execute:
264
32
  --output-format <fmt> Output format (json|text|stream-json)
265
33
  --out/-o <path> Save result to file (stdout suppressed)
266
34
  --effort <level> Model effort (high|medium|low)
267
- -f/--prompt-file <path> Read task body from file (bypasses argv length limits)
35
+ -f/--prompt-file <path> Read body only from file; set recipient with --to (bypasses argv length limits)
268
36
  --var key=value Template variable (repeatable). Accessible as {{key}} in agent prompt.
269
37
  -- End of flags; remaining tokens treated as message text
270
- e.g. crewx q "@agent label" -- --flag-in-message
38
+ e.g. crewx q --to agent "label" -- --flag-in-message
39
+
40
+ q/query/x/execute:
41
+ --detach/--async Persist a receipt, launch a detached runner, and print task-id
42
+ (automatic inside an agent process; q/x stay synchronous elsewhere).
43
+ --wait Force synchronous execution, including inside an agent process.
44
+ e.g. crewx x --to agent "label" --detach
271
45
 
272
46
  Agent Management:
273
47
  agent ls [options] List configured agents
@@ -278,20 +52,42 @@ Agent Management:
278
52
 
279
53
  Task Management:
280
54
  ps List running tasks
281
- kill <task-id> Kill a running task
282
- kill --all Kill all running tasks
55
+ stop <task-id> Stop a running task (cooperative, then forced)
56
+ stop --all Stop all running tasks
57
+ kill <task-id> Alias for stop
283
58
  result [task-id] Get task result (or list recent tasks)
59
+ --wait=N Poll (1s interval) up to N seconds for the task to
60
+ finish. Exit 124 on timeout. --wait=0 = single check.
284
61
  restart <task-id> Restart a failed task as a new task
285
62
 
286
63
  Logs & Diagnostics:
287
64
  log [ls|<task-id>] View task logs
288
65
  doctor [--config <path>] Run system diagnosis
289
- init [--force] [--config <p>] Initialize crewx.yaml
66
+ init [--force] [--provider cli/claude|cli/codex] Initialize crewx.yaml
290
67
 
291
68
  Database:
292
69
  db push Sync DB schema to current code (additive only)
293
70
  --force Reset migration history + skip confirmation
294
71
  --dry-run Preview changes without applying
72
+ db migrate-task-logs Backfill legacy tasks.logs into task_log_events
73
+ --dry-run Validate and estimate without writing
74
+ --apply Consistent backup + resumable task-by-task apply
75
+ --verify Check event/source invariants and parity
76
+ db migrate-request-logs Move request logs from crewx.db into logs.db (bodies stored once)
77
+ --batch N Rows per batch (default 250)
78
+ --dry-run Count rows and distinct bodies without writing
79
+
80
+ Desktop Shortcut (Windows only):
81
+ shortcut status [--json] Show current shortcut status
82
+ shortcut install [--force] [--json] Install/repair the Desktop shortcut
83
+ shortcut uninstall [--json] Remove the Desktop shortcut
84
+
85
+ Publish:
86
+ publish [dir] [options] Package a workspace as a distributable template archive
87
+ --dry-run Scan + build manifest only; do not write a .tgz
88
+ --version <ver> Override manifest version (semver)
89
+ --json Print machine-readable JSON to stdout
90
+ --upload Submit + upload using the SDK account session
295
91
 
296
92
  Built-in Tools:
297
93
  memory <args> Memory tool
@@ -306,14 +102,9 @@ Hook Platform:
306
102
  hook install [--yes] Install PreToolUse hook in .claude/settings.json
307
103
  hook uninstall Remove crewx hook from .claude/settings.json
308
104
  hook status Show hook installation status and plugins
309
- hook-dispatch Internal: IPC router called by Claude (stdin→stdout)
105
+ hook-dispatch Internal: IPC router called by Claude (stdin\u2192stdout)
310
106
 
311
107
  Global Options:
312
108
  --help, -h Show this help
313
109
  --version, -v Show version
314
- `.trim());
315
- }
316
- main().catch((err) => {
317
- console.error(err instanceof Error ? err.message : String(err));
318
- process.exit(err instanceof parse_common_flags_1.UnknownOptionError ? 2 : 1);
319
- });
110
+ `.trim())}function H(r){if(r instanceof U.UnknownOptionError)return 2;if(typeof r==="object"&&r!==null&&"exitCode"in r){const e=r.exitCode;if(typeof e==="number")return e}return 1}const m=(0,g.createDelegationEmitState)();F(m).catch(r=>{console.error(r instanceof Error?r.message:String(r));(0,g.emitDelegationResult)({command:process.argv[2],isError:true,state:m});process.exit(H(r))});
@@ -1,9 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.registerBuiltinToolsIfNeeded = void 0;
4
- /**
5
- * Register built-in Node.js tools for api/* provider agents.
6
- * Delegates to @crewx/sdk/tools/node.
7
- */
8
- var node_1 = require("@crewx/sdk/tools/node");
9
- Object.defineProperty(exports, "registerBuiltinToolsIfNeeded", { enumerable: true, get: function () { return node_1.registerBuiltinTools; } });
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.registerBuiltinToolsIfNeeded=void 0;var e=require("@crewx/sdk/tools/node");Object.defineProperty(exports,"registerBuiltinToolsIfNeeded",{enumerable:true,get:function(){return e.registerBuiltinTools}});
@@ -1,134 +1 @@
1
- "use strict";
2
- /**
3
- * Lightweight Slack file downloader for CLI bot mode.
4
- * Ported from cli-bak SlackFileDownloadService, stripped of NestJS deps.
5
- * Uses Node.js built-in https for API calls.
6
- */
7
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
- if (k2 === undefined) k2 = k;
9
- var desc = Object.getOwnPropertyDescriptor(m, k);
10
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
- desc = { enumerable: true, get: function() { return m[k]; } };
12
- }
13
- Object.defineProperty(o, k2, desc);
14
- }) : (function(o, m, k, k2) {
15
- if (k2 === undefined) k2 = k;
16
- o[k2] = m[k];
17
- }));
18
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
- Object.defineProperty(o, "default", { enumerable: true, value: v });
20
- }) : function(o, v) {
21
- o["default"] = v;
22
- });
23
- var __importStar = (this && this.__importStar) || (function () {
24
- var ownKeys = function(o) {
25
- ownKeys = Object.getOwnPropertyNames || function (o) {
26
- var ar = [];
27
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
- return ar;
29
- };
30
- return ownKeys(o);
31
- };
32
- return function (mod) {
33
- if (mod && mod.__esModule) return mod;
34
- var result = {};
35
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
- __setModuleDefault(result, mod);
37
- return result;
38
- };
39
- })();
40
- Object.defineProperty(exports, "__esModule", { value: true });
41
- exports.downloadInboundFiles = downloadInboundFiles;
42
- const fs = __importStar(require("fs"));
43
- const path = __importStar(require("path"));
44
- const https = __importStar(require("https"));
45
- const MAX_FILE_SIZE = 50 * 1024 * 1024;
46
- async function downloadInboundFiles(botToken, files, threadId) {
47
- if (!files || files.length === 0)
48
- return [];
49
- const results = [];
50
- const downloadDir = path.join(process.cwd(), '.crewx', 'slack-files');
51
- const safeThreadDir = threadId.replace(/:/g, '_');
52
- for (const file of files) {
53
- if (!file.url_private)
54
- continue;
55
- const sanitizedName = sanitizeFileName(file.name || 'unnamed_file');
56
- const saveDir = path.join(downloadDir, safeThreadDir);
57
- const savePath = path.join(saveDir, sanitizedName);
58
- try {
59
- if (fs.existsSync(savePath)) {
60
- const stats = fs.statSync(savePath);
61
- results.push({
62
- fileId: '',
63
- fileName: sanitizedName,
64
- filePath: savePath,
65
- fileSize: stats.size,
66
- threadId,
67
- });
68
- continue;
69
- }
70
- await fs.promises.mkdir(saveDir, { recursive: true });
71
- const buffer = await fetchUrl(botToken, file.url_private);
72
- if (buffer.length > MAX_FILE_SIZE) {
73
- console.error(`File too large: ${sanitizedName} (${formatSize(buffer.length)})`);
74
- continue;
75
- }
76
- await fs.promises.writeFile(savePath, new Uint8Array(buffer));
77
- results.push({
78
- fileId: '',
79
- fileName: sanitizedName,
80
- filePath: savePath,
81
- fileSize: buffer.length,
82
- threadId,
83
- });
84
- }
85
- catch (err) {
86
- console.error(`Failed to download file ${sanitizedName}: ${err instanceof Error ? err.message : String(err)}`);
87
- }
88
- }
89
- return results;
90
- }
91
- function fetchUrl(token, url) {
92
- const parsed = new URL(url);
93
- return new Promise((resolve, reject) => {
94
- const options = {
95
- hostname: parsed.hostname,
96
- path: parsed.pathname + parsed.search,
97
- method: 'GET',
98
- headers: { Authorization: `Bearer ${token}` },
99
- };
100
- const req = https.request(options, (res) => {
101
- if (res.statusCode === 301 || res.statusCode === 302) {
102
- const location = res.headers.location;
103
- if (location) {
104
- fetchUrl(token, location).then(resolve).catch(reject);
105
- return;
106
- }
107
- }
108
- if (res.statusCode !== 200) {
109
- reject(new Error(`HTTP ${res.statusCode}`));
110
- return;
111
- }
112
- const chunks = [];
113
- res.on('data', (chunk) => chunks.push(chunk));
114
- res.on('end', () => resolve(Buffer.concat(chunks)));
115
- res.on('error', reject);
116
- });
117
- req.on('error', reject);
118
- req.setTimeout(30000, () => { req.destroy(); reject(new Error('Timeout')); });
119
- req.end();
120
- });
121
- }
122
- function sanitizeFileName(name) {
123
- let safe = name.replace(/[/\\]/g, '_').replace(/\.\./g, '_');
124
- safe = safe.replace(/[\x00-\x1f\x80-\x9f<>:"|?*]/g, '_');
125
- safe = safe.replace(/^\.+|\.+$/g, '').trim();
126
- return safe || 'unnamed_file';
127
- }
128
- function formatSize(bytes) {
129
- if (bytes < 1024)
130
- return `${bytes}B`;
131
- if (bytes < 1024 * 1024)
132
- return `${(bytes / 1024).toFixed(1)}KB`;
133
- return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
134
- }
1
+ "use strict";var g=exports&&exports.__createBinding||(Object.create?(function(t,e,i,n){if(n===void 0)n=i;var r=Object.getOwnPropertyDescriptor(e,i);if(!r||("get"in r?!e.__esModule:r.writable||r.configurable)){r={enumerable:true,get:function(){return e[i]}}}Object.defineProperty(t,n,r)}):(function(t,e,i,n){if(n===void 0)n=i;t[n]=e[i]}));var w=exports&&exports.__setModuleDefault||(Object.create?(function(t,e){Object.defineProperty(t,"default",{enumerable:true,value:e})}):function(t,e){t["default"]=e});var d=exports&&exports.__importStar||(function(){var t=function(e){t=Object.getOwnPropertyNames||function(i){var n=[];for(var r in i)if(Object.prototype.hasOwnProperty.call(i,r))n[n.length]=r;return n};return t(e)};return function(e){if(e&&e.__esModule)return e;var i={};if(e!=null){for(var n=t(e),r=0;r<n.length;r++)if(n[r]!=="default")g(i,e,n[r])}w(i,e);return i}})();Object.defineProperty(exports,"__esModule",{value:true});exports.downloadInboundFiles=b;const f=d(require("fs"));const h=d(require("path"));const m=d(require("https"));const v=50*1024*1024;async function b(t,e,i){if(!e||e.length===0)return[];const n=[];const r=h.join(process.cwd(),".crewx","slack-files");const l=i.replace(/:/g,"_");for(const u of e){if(!u.url_private)continue;const o=O(u.name||"unnamed_file");const s=h.join(r,l);const a=h.join(s,o);try{if(f.existsSync(a)){const p=f.statSync(a);n.push({fileId:"",fileName:o,filePath:a,fileSize:p.size,threadId:i});continue}await f.promises.mkdir(s,{recursive:true});const c=await _(t,u.url_private);if(c.length>v){console.error(`File too large: ${o} (${P(c.length)})`);continue}await f.promises.writeFile(a,new Uint8Array(c));n.push({fileId:"",fileName:o,filePath:a,fileSize:c.length,threadId:i})}catch(c){console.error(`Failed to download file ${o}: ${c instanceof Error?c.message:String(c)}`)}}return n}function _(t,e){const i=new URL(e);return new Promise((n,r)=>{const l={hostname:i.hostname,path:i.pathname+i.search,method:"GET",headers:{Authorization:`Bearer ${t}`}};const u=m.request(l,o=>{if(o.statusCode===301||o.statusCode===302){const a=o.headers.location;if(a){_(t,a).then(n).catch(r);return}}if(o.statusCode!==200){r(new Error(`HTTP ${o.statusCode}`));return}const s=[];o.on("data",a=>s.push(a));o.on("end",()=>n(Buffer.concat(s)));o.on("error",r)});u.on("error",r);u.setTimeout(3e4,()=>{u.destroy();r(new Error("Timeout"))});u.end()})}function O(t){let e=t.replace(/[/\\]/g,"_").replace(/\.\./g,"_");e=e.replace(/[\x00-\x1f\x80-\x9f<>:"|?*]/g,"_");e=e.replace(/^\.+|\.+$/g,"").trim();return e||"unnamed_file"}function P(t){if(t<1024)return`${t}B`;if(t<1024*1024)return`${(t/1024).toFixed(1)}KB`;return`${(t/(1024*1024)).toFixed(1)}MB`}
@@ -1,33 +1 @@
1
- "use strict";
2
- /**
3
- * Lightweight Markdown → Slack mrkdwn converter.
4
- * Ported from cli-bak formatters, stripped of NestJS / md-to-slack deps.
5
- */
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.markdownToMrkdwn = markdownToMrkdwn;
8
- const HEADING_RE = /^(#{1,6})\s+(.+)$/gm;
9
- const BOLD_RE = /\*\*([^*]+)\*\*/g;
10
- const ITALIC_RE = /(?<!\*)\*([^*]+)\*(?!\*)/g;
11
- const CODE_BLOCK_RE = /```(\w*)\n([\s\S]*?)```/g;
12
- const INLINE_CODE_RE = /`([^`]+)`/g;
13
- const LINK_RE = /\[([^\]]+)\]\(([^)]+)\)/g;
14
- const UNORDERED_LIST_RE = /^[\s]*[-*]\s+/gm;
15
- const ORDERED_LIST_RE = /^[\s]*(\d+)\.\s+/gm;
16
- function markdownToMrkdwn(text) {
17
- if (!text)
18
- return '';
19
- let result = text;
20
- result = result.replace(CODE_BLOCK_RE, (_match, _lang, code) => {
21
- return `\`\`\`${code.trim()}\`\`\``;
22
- });
23
- result = result.replace(INLINE_CODE_RE, '`$1`');
24
- result = result.replace(HEADING_RE, (_match, _hashes, content) => {
25
- return `*${content.trim()}*`;
26
- });
27
- result = result.replace(BOLD_RE, '*$1*');
28
- result = result.replace(ITALIC_RE, '_$1_');
29
- result = result.replace(LINK_RE, '<$2|$1>');
30
- result = result.replace(UNORDERED_LIST_RE, '• ');
31
- result = result.replace(ORDERED_LIST_RE, '$1. ');
32
- return result;
33
- }
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.markdownToMrkdwn=g;const s=/^(#{1,6})\s+(.+)$/gm;const _=/\*\*([^*]+)\*\*/g;const E=/(?<!\*)\*([^*]+)\*(?!\*)/g;const a=/```(\w*)\n([\s\S]*?)```/g;const o=/`([^`]+)`/g;const l=/\[([^\]]+)\]\(([^)]+)\)/g;const R=/^[\s]*[-*]\s+/gm;const u=/^[\s]*(\d+)\.\s+/gm;function g(t){if(!t)return"";let e=t;e=e.replace(a,(c,n,r)=>{return`\`\`\`${r.trim()}\`\`\``});e=e.replace(o,"`$1`");e=e.replace(s,(c,n,r)=>{return`*${r.trim()}*`});e=e.replace(_,"*$1*");e=e.replace(E,"_$1_");e=e.replace(l,"<$2|$1>");e=e.replace(R,"\u2022 ");e=e.replace(u,"$1. ");return e}
@@ -1,5 +1,2 @@
1
- /**
2
- * CREWX_* environment variable defaults for CLI bootstrap.
3
- * Re-exported from @crewx/sdk for convenience.
4
- */
5
- export { resolveCrewxCli, resolveCrewxWorkspace } from '@crewx/sdk';
1
+ export declare function resolveCrewxCli(): string;
2
+ export declare function resolveCrewxWorkspace(): string;