@crewx/cli 0.9.0-rc.18 → 0.9.0-rc.180

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 (80) 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/bootstrap/rate-limit-snapshot.d.ts +15 -0
  5. package/dist/bootstrap/rate-limit-snapshot.js +1 -0
  6. package/dist/builtin.d.ts +1 -1
  7. package/dist/builtin.js +5 -127
  8. package/dist/commands/agent.d.ts +1 -0
  9. package/dist/commands/agent.js +3 -246
  10. package/dist/commands/ai-account.d.ts +4 -0
  11. package/dist/commands/ai-account.js +27 -0
  12. package/dist/commands/cal.d.ts +15 -0
  13. package/dist/commands/cal.js +2 -0
  14. package/dist/commands/command-help.d.ts +26 -0
  15. package/dist/commands/command-help.js +52 -0
  16. package/dist/commands/db.d.ts +3 -0
  17. package/dist/commands/db.js +59 -125
  18. package/dist/commands/detached.d.ts +102 -0
  19. package/dist/commands/detached.js +15 -0
  20. package/dist/commands/doctor.d.ts +77 -0
  21. package/dist/commands/doctor.js +4 -196
  22. package/dist/commands/emit-trailer.d.ts +25 -0
  23. package/dist/commands/emit-trailer.js +2 -0
  24. package/dist/commands/execute.d.ts +8 -4
  25. package/dist/commands/execute.js +15 -146
  26. package/dist/commands/hook/command-marker.d.ts +2 -0
  27. package/dist/commands/hook/command-marker.js +1 -0
  28. package/dist/commands/hook/install.d.ts +0 -1
  29. package/dist/commands/hook/install.js +8 -175
  30. package/dist/commands/hook/paths.js +1 -94
  31. package/dist/commands/hook/status.js +1 -86
  32. package/dist/commands/hook/uninstall.js +1 -71
  33. package/dist/commands/hook-dispatch.js +2 -180
  34. package/dist/commands/init.d.ts +34 -0
  35. package/dist/commands/init.js +38 -371
  36. package/dist/commands/kill.d.ts +2 -8
  37. package/dist/commands/kill.js +1 -52
  38. package/dist/commands/log.js +3 -95
  39. package/dist/commands/parse-agent-message.js +1 -52
  40. package/dist/commands/parse-common-flags.d.ts +5 -1
  41. package/dist/commands/parse-common-flags.js +3 -181
  42. package/dist/commands/ps.d.ts +2 -2
  43. package/dist/commands/ps.js +2 -107
  44. package/dist/commands/publish.d.ts +1 -0
  45. package/dist/commands/publish.js +27 -0
  46. package/dist/commands/query.d.ts +7 -2
  47. package/dist/commands/query.js +16 -146
  48. package/dist/commands/registry.js +1 -31
  49. package/dist/commands/resolve-prompt.js +3 -54
  50. package/dist/commands/resolve-recipient.d.ts +14 -0
  51. package/dist/commands/resolve-recipient.js +3 -0
  52. package/dist/commands/restart.d.ts +3 -1
  53. package/dist/commands/restart.js +18 -162
  54. package/dist/commands/result.d.ts +8 -3
  55. package/dist/commands/result.js +1 -70
  56. package/dist/commands/shortcut.d.ts +1 -0
  57. package/dist/commands/shortcut.js +18 -0
  58. package/dist/commands/slack.js +16 -559
  59. package/dist/commands/stop.d.ts +8 -0
  60. package/dist/commands/stop.js +8 -0
  61. package/dist/commands/write-output.js +1 -24
  62. package/dist/index.d.ts +1 -1
  63. package/dist/index.js +1 -5
  64. package/dist/logging.d.ts +1 -1
  65. package/dist/logging.js +10 -86
  66. package/dist/main.d.ts +3 -2
  67. package/dist/main.js +49 -253
  68. package/dist/register-builtin-tools.js +1 -9
  69. package/dist/slack/file-download.js +1 -134
  70. package/dist/slack/markdown.js +1 -33
  71. package/dist/utils/env-defaults.d.ts +2 -5
  72. package/dist/utils/env-defaults.js +1 -10
  73. package/dist/utils/inherited-trace.d.ts +24 -0
  74. package/dist/utils/inherited-trace.js +1 -25
  75. package/dist/utils/product-package-root.d.ts +6 -0
  76. package/dist/utils/product-package-root.js +1 -0
  77. package/dist/utils/sdk-compat.d.ts +24 -0
  78. package/dist/utils/sdk-compat.js +1 -0
  79. package/dist/utils/version.js +1 -28
  80. package/package.json +16 -12
@@ -6,16 +6,48 @@
6
6
  * crewx init Create crewx.yaml in current directory
7
7
  * crewx init --force Overwrite existing configuration
8
8
  */
9
+ import { type ProviderAvailabilityDeps } from '@crewx/sdk';
10
+ export type InitProvider = 'cli/claude' | 'cli/codex';
11
+ type InitAgent = {
12
+ id: 'planner' | 'developer' | 'reviewer';
13
+ name: string;
14
+ role: string;
15
+ team: string;
16
+ provider: InitProvider;
17
+ working_directory: string;
18
+ description: string;
19
+ options: {
20
+ query: {
21
+ mode: string;
22
+ effort: string;
23
+ };
24
+ execute: {
25
+ mode: string;
26
+ effort: string;
27
+ };
28
+ };
29
+ inline: {
30
+ model: string;
31
+ prompt: string;
32
+ };
33
+ };
34
+ /** Build the three default agents using the selected CLI provider profile. */
35
+ export declare function buildDefaultAgents(provider: InitProvider): InitAgent[];
9
36
  export interface InitResult {
10
37
  yamlCreated: boolean;
11
38
  hookInstalled: boolean;
12
39
  errors: string[];
40
+ provider: InitProvider;
13
41
  skippedReason?: 'yaml-exists';
14
42
  workspaceId?: string;
15
43
  slug?: string;
16
44
  statusLineConfigured?: boolean;
17
45
  statusLineSkipped?: boolean;
18
46
  }
47
+ /** Parse the provider option accepted by `crewx init`. */
48
+ export declare function parseInitProvider(args: readonly string[]): InitProvider | undefined;
49
+ /** Resolve an explicit provider or detect Claude, then Codex, using PATH only. */
50
+ export declare function resolveInitProvider(provider?: InitProvider, deps?: ProviderAvailabilityDeps): InitProvider;
19
51
  /**
20
52
  * Programmatic init — creates crewx.yaml, support dirs, and optionally installs hooks.
21
53
  * Throws on unrecoverable errors (PATH_NOT_FOUND, YAML_CREATE_FAILED).
@@ -27,4 +59,6 @@ export declare function handleInit(opts: {
27
59
  path: string;
28
60
  skipHook?: boolean;
29
61
  force?: boolean;
62
+ provider?: InitProvider;
30
63
  }): Promise<InitResult>;
64
+ export {};
@@ -1,62 +1,4 @@
1
- "use strict";
2
- /**
3
- * crewx init handler.
4
- * Initializes a CrewX project by creating crewx.yaml and supporting dirs.
5
- *
6
- * Usage:
7
- * crewx init Create crewx.yaml in current directory
8
- * crewx init --force Overwrite existing configuration
9
- */
10
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
11
- if (k2 === undefined) k2 = k;
12
- var desc = Object.getOwnPropertyDescriptor(m, k);
13
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
14
- desc = { enumerable: true, get: function() { return m[k]; } };
15
- }
16
- Object.defineProperty(o, k2, desc);
17
- }) : (function(o, m, k, k2) {
18
- if (k2 === undefined) k2 = k;
19
- o[k2] = m[k];
20
- }));
21
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
22
- Object.defineProperty(o, "default", { enumerable: true, value: v });
23
- }) : function(o, v) {
24
- o["default"] = v;
25
- });
26
- var __importStar = (this && this.__importStar) || (function () {
27
- var ownKeys = function(o) {
28
- ownKeys = Object.getOwnPropertyNames || function (o) {
29
- var ar = [];
30
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
31
- return ar;
32
- };
33
- return ownKeys(o);
34
- };
35
- return function (mod) {
36
- if (mod && mod.__esModule) return mod;
37
- var result = {};
38
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
39
- __setModuleDefault(result, mod);
40
- return result;
41
- };
42
- })();
43
- var __importDefault = (this && this.__importDefault) || function (mod) {
44
- return (mod && mod.__esModule) ? mod : { "default": mod };
45
- };
46
- Object.defineProperty(exports, "__esModule", { value: true });
47
- exports.handleInit = handleInit;
48
- const fs_1 = require("fs");
49
- const path_1 = require("path");
50
- const path = __importStar(require("path"));
51
- const git = __importStar(require("isomorphic-git"));
52
- const nodeFs = __importStar(require("fs"));
53
- const os_1 = __importDefault(require("os"));
54
- const repository_1 = require("@crewx/sdk/repository");
55
- const install_1 = require("./hook/install");
56
- const STATUSLINE_SCRIPT_NAME = 'claude-usage-statusline.js';
57
- const STATUSLINE_SCRIPT_MARKER = 'CrewX claude-usage-statusline';
58
- // Reads Claude Code rate_limits from stdin payload and dumps to ~/.crewx/claude-usage.json
59
- const STATUSLINE_SCRIPT_CONTENT = `// ${STATUSLINE_SCRIPT_MARKER}
1
+ "use strict";var $=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 j=exports&&exports.__setModuleDefault||(Object.create?(function(t,e){Object.defineProperty(t,"default",{enumerable:true,value:e})}):function(t,e){t["default"]=e});var w=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")$(i,e,n[r])}j(i,e);return i}})();var F=exports&&exports.__importDefault||function(t){return t&&t.__esModule?t:{"default":t}};Object.defineProperty(exports,"__esModule",{value:true});exports.buildDefaultAgents=P;exports.parseInitProvider=z;exports.resolveInitProvider=b;exports.handleInit=V;const s=require("fs");const d=require("path");const u=w(require("path"));const _=w(require("isomorphic-git"));const I=w(require("fs"));const E=F(require("os"));const M=require("@crewx/sdk/repository");const f=require("@crewx/sdk");const N=require("./hook/install");const q="claude-usage-statusline.js";const W="CrewX claude-usage-statusline";const Y=`// ${W}
60
2
  // Dumps Claude Code rate_limits (stdin payload) to ~/.crewx/claude-usage.json
61
3
  const fs = require('fs');
62
4
  const os = require('os');
@@ -78,12 +20,14 @@ process.stdin.on('end', () => {
78
20
  }
79
21
  } catch (_) {}
80
22
  });
81
- `;
82
- const INIT_AUTHOR = { name: 'CrewX', email: 'crewx@local' };
83
- const CREWX_MARKER = '# CrewX runtime';
84
- const CREWX_GITIGNORE = `# CrewX runtime
23
+ `;const G={name:"CrewX",email:"crewx@local"};const K="# CrewX runtime";const L=`# CrewX runtime
85
24
  .crewx/
86
25
 
26
+ # Secrets (workspace .env \u2014 see docs/manual)
27
+ .env
28
+ .env.*
29
+ !.env.example
30
+
87
31
  # Memory runtime state (regenerable from entries/)
88
32
  memory/*/.dirty-summary
89
33
  memory/*/graph.json
@@ -96,66 +40,15 @@ skills/*/logs/
96
40
  skills/*/.crewx/
97
41
 
98
42
  # OS
99
- .DS_Store`.trim();
100
- const DEFAULT_AGENTS = [
101
- {
102
- id: 'planner',
103
- name: 'Planner',
104
- role: 'Product/Architecture Planner',
105
- team: 'core',
106
- provider: 'acp/claude',
107
- working_directory: './',
108
- description: 'Owns requirements analysis, design, and work breakdown',
109
- options: {
110
- query: { effort: 'high' },
111
- execute: { effort: 'high', mode: 'bypassPermissions' },
112
- },
113
- inline: {
114
- model: 'claude-opus-4-7',
115
- prompt: `You are a planner. Break down user goals into concrete,\ntestable steps. Challenge assumptions. Never write code directly.`,
116
- },
117
- },
118
- {
119
- id: 'developer',
120
- name: 'Developer',
121
- role: 'Implementation Engineer',
122
- team: 'core',
123
- provider: 'acp/claude',
124
- working_directory: './',
125
- description: 'Implements code changes and tests',
126
- options: {
127
- query: { effort: 'high' },
128
- execute: { effort: 'high', mode: 'bypassPermissions' },
129
- },
130
- inline: {
131
- model: 'claude-sonnet-4-6',
132
- prompt: `Implement what the planner specifies. Prefer editing\nexisting files. Run tests before reporting done.`,
133
- },
134
- },
135
- {
136
- id: 'reviewer',
137
- name: 'Reviewer',
138
- role: 'Code Reviewer',
139
- team: 'core',
140
- provider: 'acp/claude',
141
- working_directory: './',
142
- description: 'Reviews code quality, security, and readability',
143
- options: {
144
- query: { effort: 'high' },
145
- execute: { effort: 'high', mode: 'bypassPermissions' },
146
- },
147
- inline: {
148
- model: 'claude-sonnet-4-6',
149
- prompt: `Review diffs for correctness, security, readability.\nCite file:line. Be blunt, not polite.`,
150
- },
151
- },
152
- ];
153
- const GOAL_TEMPLATE = `---
43
+ .DS_Store`.trim();function P(t){const e=(0,f.getDefaultAgentProfile)(t);if(!e){throw new Error(`DEFAULT_AGENT_PROFILE_NOT_FOUND: ${t}`)}return[{id:"planner",name:"Planner",role:"Product/Architecture Planner",team:"core",provider:t,working_directory:"./",description:"Owns requirements analysis, design, and work breakdown",options:{query:e.planner.query,execute:e.planner.execute},inline:{model:e.planner.model,prompt:`You are a planner. Break down user goals into concrete,
44
+ testable steps. Challenge assumptions. Never write code directly.`}},{id:"developer",name:"Developer",role:"Implementation Engineer",team:"core",provider:t,working_directory:"./",description:"Implements code changes and tests",options:{query:e.worker.query,execute:e.worker.execute},inline:{model:e.worker.model,prompt:`Implement what the planner specifies. Prefer editing
45
+ existing files. Run tests before reporting done.`}},{id:"reviewer",name:"Reviewer",role:"Code Reviewer",team:"core",provider:t,working_directory:"./",description:"Reviews code quality, security, and readability",options:{query:e.worker.query,execute:e.worker.execute},inline:{model:e.worker.model,prompt:`Review diffs for correctness, security, readability.
46
+ Cite file:line. Be blunt, not polite.`}}]}const B=`---
154
47
  type: goal
155
- description: CrewX Goal — OKR
48
+ description: CrewX Goal \u2014 OKR
156
49
  notation:
157
- weight: "(w:N) — KR weight, default 1 if omitted"
158
- auto: "N% auto — L1 progress auto-calculated as weighted average of children"
50
+ weight: "(w:N) \u2014 KR weight, default 1 if omitted"
51
+ auto: "N% auto \u2014 L1 progress auto-calculated as weighted average of children"
159
52
  ---
160
53
 
161
54
  # Goal Title
@@ -176,8 +69,7 @@ Describe the goal...
176
69
  ## Notes
177
70
 
178
71
  ## Reflection
179
- `;
180
- const DAILY_TEMPLATE = `# YYYY-MM-DD (Day)
72
+ `;const X=`# YYYY-MM-DD (Day)
181
73
 
182
74
  ## Top 3
183
75
  1.
@@ -191,8 +83,7 @@ const DAILY_TEMPLATE = `# YYYY-MM-DD (Day)
191
83
  ## Notes
192
84
 
193
85
  ## Reflection
194
- `;
195
- const WI_TEMPLATE = `---
86
+ `;const U=`---
196
87
  wi_id: WI-{YYYYMMDD}-{SEQ}
197
88
  title: ""
198
89
  date: ""
@@ -232,7 +123,7 @@ consumers:
232
123
  # store: useThreadDetailStore
233
124
  # component: MessageBubble
234
125
 
235
- # Estimated scope (atomicity: ≤ $0.30, 1-3 files)
126
+ # Estimated scope (atomicity: \u2264 $0.30, 1-3 files)
236
127
  estimated_files: 0
237
128
  estimated_cost: "$0.00"
238
129
  ---
@@ -266,7 +157,7 @@ estimated_cost: "$0.00"
266
157
  > Summary of the relevant design doc section.
267
158
 
268
159
  \`\`\`bash
269
- npx doc section {design_doc} "{spec_id}"
160
+ crewx doc section {design_doc} "{spec_id}"
270
161
  \`\`\`
271
162
 
272
163
  | Item | Value |
@@ -302,7 +193,7 @@ npx doc section {design_doc} "{spec_id}"
302
193
  | Level | Condition |
303
194
  |-------|-----------|
304
195
  | \`low\` | Single file, no API change, existing tests sufficient |
305
- | \`medium\` | 2-3 files, API change with ≤ 1 consumer |
196
+ | \`medium\` | 2-3 files, API change with \u2264 1 consumer |
306
197
  | \`high\` | API change + 2+ consumers, or store refactoring |
307
198
  | \`critical\` | DB schema change, or core SDK interface change |
308
199
 
@@ -346,261 +237,37 @@ N tests passed
346
237
  ### Commit
347
238
  - hash: <commit hash>
348
239
  - branch: <worktree branch>
349
- (empty = completion report invalid — worktree tasks only)
240
+ (empty = completion report invalid \u2014 worktree tasks only)
350
241
 
351
242
  ### Remaining items
352
243
  None / (list if any)
353
244
  \`\`\`
354
- `;
355
- function indentBlock(text, spaces) {
356
- const prefix = ' '.repeat(spaces);
357
- return text
358
- .split('\n')
359
- .map((line) => `${prefix}${line}`)
360
- .join('\n');
361
- }
362
- function generateDefaultYaml(agents) {
363
- const agentBlocks = agents
364
- .map((a) => ` - id: "${a.id}"
365
- name: "${a.name}"
366
- role: "${a.role}"
367
- team: "${a.team}"
368
- provider: "${a.provider}"
369
- working_directory: "${a.working_directory}"
370
- description: "${a.description}"
245
+ `;function H(t,e){const i=" ".repeat(e);return t.split("\n").map(n=>`${i}${n}`).join("\n")}function J(t){const e=t.map(i=>` - id: "${i.id}"
246
+ name: "${i.name}"
247
+ role: "${i.role}"
248
+ team: "${i.team}"
249
+ provider: "${i.provider}"
250
+ working_directory: "${i.working_directory}"
251
+ description: "${i.description}"
371
252
  options:
372
253
  query:
373
- effort: "high"
254
+ mode: "${i.options.query.mode}"
255
+ effort: "${i.options.query.effort}"
374
256
  execute:
375
- effort: "high"
376
- mode: "bypassPermissions"
257
+ mode: "${i.options.execute.mode}"
258
+ effort: "${i.options.execute.effort}"
377
259
  inline:
378
- model: "${a.inline.model}"
260
+ model: "${i.inline.model}"
379
261
  prompt: |
380
- ${indentBlock(a.inline.prompt, 8)}`)
381
- .join('\n\n');
382
- return `# CrewX Agents Configuration
262
+ ${H(i.inline.prompt,8)}`).join("\n\n");return`# CrewX Agents Configuration
383
263
  # Generated by 'crewx init'
384
264
 
385
265
  agents:
386
- ${agentBlocks}
266
+ ${e}
387
267
 
388
268
  # Usage examples:
389
- # crewx query "@planner analyze this codebase"
390
- # crewx execute "@developer implement the feature described above"
269
+ # crewx q --to planner "analyze this codebase"
270
+ # crewx x --to developer "implement the feature described above"
391
271
  # crewx agent ls
392
- `;
393
- }
394
- /**
395
- * Programmatic init — creates crewx.yaml, support dirs, and optionally installs hooks.
396
- * Throws on unrecoverable errors (PATH_NOT_FOUND, YAML_CREATE_FAILED).
397
- * Partial failures (hook install, mkdir, workspace registration) are collected in InitResult.errors.
398
- * Workspace registration is always attempted (even when yaml already exists) so that CLI and
399
- * server paths both produce a row in ~/.crewx/crewx.db.
400
- */
401
- async function handleInit(opts) {
402
- const { path: target, skipHook = false, force = false } = opts;
403
- const errors = [];
404
- let yamlCreated = false;
405
- let hookInstalled = false;
406
- let skippedReason;
407
- if (!(0, fs_1.existsSync)(target)) {
408
- throw new Error(`PATH_NOT_FOUND: ${target}`);
409
- }
410
- const yamlPath = (0, path_1.join)(target, 'crewx.yaml');
411
- const ymlPath = (0, path_1.join)(target, 'crewx.yml');
412
- if ((0, fs_1.existsSync)(yamlPath) || (0, fs_1.existsSync)(ymlPath)) {
413
- if (!force) {
414
- // yaml already exists: skip creation but still register workspace below
415
- skippedReason = 'yaml-exists';
416
- }
417
- }
418
- if (!skippedReason) {
419
- try {
420
- const content = generateDefaultYaml(DEFAULT_AGENTS);
421
- (0, fs_1.writeFileSync)(yamlPath, content, 'utf-8');
422
- yamlCreated = true;
423
- }
424
- catch (e) {
425
- throw new Error(`YAML_CREATE_FAILED: ${e.message}`);
426
- }
427
- if (!skipHook) {
428
- try {
429
- await (0, install_1.handleHookInstall)({ projectRoot: target, yes: true });
430
- hookInstalled = true;
431
- }
432
- catch (e) {
433
- errors.push(`HOOK_INSTALL_FAILED: ${e.message}`);
434
- }
435
- }
436
- }
437
- // Always create docs dirs and templates, regardless of whether yaml was skipped
438
- for (const dir of ['.crewx/logs', '.claude/commands', 'docs/goal', 'docs/daily', 'docs/wi']) {
439
- try {
440
- (0, fs_1.mkdirSync)((0, path_1.join)(target, dir), { recursive: true });
441
- }
442
- catch (e) {
443
- errors.push(`MKDIR_FAILED:${dir}:${e.message}`);
444
- }
445
- }
446
- const docTemplates = [
447
- { dir: 'docs/goal', file: 'GOAL-TEMPLATE.md', content: GOAL_TEMPLATE },
448
- { dir: 'docs/daily', file: 'DAILY-TEMPLATE.md', content: DAILY_TEMPLATE },
449
- { dir: 'docs/wi', file: 'WI-TEMPLATE.md', content: WI_TEMPLATE },
450
- ];
451
- for (const t of docTemplates) {
452
- const fullPath = (0, path_1.join)(target, t.dir, t.file);
453
- if (force || !(0, fs_1.existsSync)(fullPath)) {
454
- const action = (0, fs_1.existsSync)(fullPath) ? 'updated' : 'created';
455
- (0, fs_1.writeFileSync)(fullPath, t.content, 'utf-8');
456
- console.log(`✅ ${t.dir}/ ${action} (${t.file})`);
457
- }
458
- }
459
- // Always register workspace in ~/.crewx/crewx.db (best-effort, idempotent)
460
- let workspaceId;
461
- let slug;
462
- try {
463
- const ws = new repository_1.WorkspaceRepository().registerWorkspace(target);
464
- workspaceId = ws.id;
465
- slug = ws.slug;
466
- }
467
- catch (e) {
468
- errors.push(`WORKSPACE_REGISTER_FAILED: ${e.message}`);
469
- }
470
- const gitignorePath = (0, path_1.join)(target, '.gitignore');
471
- if (!(0, fs_1.existsSync)(gitignorePath)) {
472
- (0, fs_1.writeFileSync)(gitignorePath, CREWX_GITIGNORE + '\n', 'utf-8');
473
- console.log('✅ .gitignore updated with CrewX entries');
474
- }
475
- else {
476
- const existing = (0, fs_1.readFileSync)(gitignorePath, 'utf-8');
477
- if (!existing.includes(CREWX_MARKER)) {
478
- const separator = existing.endsWith('\n') ? '\n' : '\n\n';
479
- (0, fs_1.appendFileSync)(gitignorePath, separator + CREWX_GITIGNORE + '\n', 'utf-8');
480
- console.log('✅ .gitignore updated with CrewX entries');
481
- }
482
- else {
483
- console.log('ℹ .gitignore already contains CrewX entries');
484
- }
485
- }
486
- // Git auto-initialization
487
- await initGitRepo(target, errors);
488
- // Idempotent statusLine merge into ~/.claude/settings.json
489
- const statusLineResult = ensureClaudeStatusLine();
490
- return { yamlCreated, hookInstalled, errors, skippedReason, workspaceId, slug, ...statusLineResult };
491
- }
492
- function ensureClaudeStatusLine() {
493
- const home = os_1.default.homedir();
494
- const crewxDir = path.join(home, '.crewx');
495
- const scriptPath = path.join(crewxDir, STATUSLINE_SCRIPT_NAME);
496
- const settingsPath = path.join(home, '.claude', 'settings.json');
497
- // Always write/update the dump script itself (idempotent: same content)
498
- try {
499
- (0, fs_1.mkdirSync)(crewxDir, { recursive: true });
500
- (0, fs_1.writeFileSync)(scriptPath, STATUSLINE_SCRIPT_CONTENT, 'utf-8');
501
- }
502
- catch (_) {
503
- return { statusLineConfigured: false, statusLineSkipped: false };
504
- }
505
- const statusLineValue = `node ${scriptPath}`;
506
- let settings = {};
507
- if ((0, fs_1.existsSync)(settingsPath)) {
508
- try {
509
- settings = JSON.parse((0, fs_1.readFileSync)(settingsPath, 'utf-8'));
510
- }
511
- catch (_) {
512
- settings = {};
513
- }
514
- }
515
- if (typeof settings.statusLine === 'string' && settings.statusLine !== '') {
516
- // Already our script — no-op
517
- if (settings.statusLine === statusLineValue) {
518
- console.log('ℹ statusLine already configured (CrewX claude-usage dump)');
519
- return { statusLineConfigured: false, statusLineSkipped: false };
520
- }
521
- // Existing user statusLine — skip, do not overwrite
522
- console.log('ℹ statusLine already set in ~/.claude/settings.json — skipping Claude usage dump setup.\n' +
523
- ' To enable manually, set "statusLine" to: ' +
524
- statusLineValue);
525
- return { statusLineConfigured: false, statusLineSkipped: true };
526
- }
527
- // No existing statusLine — inject ours
528
- try {
529
- settings.statusLine = statusLineValue;
530
- const claudeDir = path.join(home, '.claude');
531
- (0, fs_1.mkdirSync)(claudeDir, { recursive: true });
532
- (0, fs_1.writeFileSync)(settingsPath, JSON.stringify(settings, null, 2) + '\n', 'utf-8');
533
- console.log('✅ statusLine configured for Claude usage dump (~/.claude/settings.json)');
534
- return { statusLineConfigured: true, statusLineSkipped: false };
535
- }
536
- catch (_) {
537
- return { statusLineConfigured: false, statusLineSkipped: false };
538
- }
539
- }
540
- async function initGitRepo(target, errors) {
541
- // Danger path guards — skip git steps but keep init successful
542
- const home = os_1.default.homedir();
543
- if (target === home) {
544
- console.log('ℹ git init skipped: target is home directory');
545
- return;
546
- }
547
- // Check filesystem root
548
- const parsedPath = path.parse(target);
549
- if (parsedPath.root === target || target === '/') {
550
- console.log('ℹ git init skipped: target is filesystem root');
551
- return;
552
- }
553
- // Check if ancestor has .git (target is inside existing git repo)
554
- let checkDir = path.dirname(target);
555
- while (checkDir !== path.parse(checkDir).root) {
556
- if ((0, fs_1.existsSync)((0, path_1.join)(checkDir, '.git'))) {
557
- console.log(`ℹ git init skipped: already inside a git repo (${checkDir})`);
558
- return;
559
- }
560
- const parent = path.dirname(checkDir);
561
- if (parent === checkDir)
562
- break;
563
- checkDir = parent;
564
- }
565
- // Skip if .git already exists in target
566
- if ((0, fs_1.existsSync)((0, path_1.join)(target, '.git'))) {
567
- console.log('ℹ git init skipped: .git already exists');
568
- return;
569
- }
570
- // Initialize git repo
571
- try {
572
- await git.init({ fs: nodeFs, dir: target, defaultBranch: 'main' });
573
- console.log('✅ git repository initialized (main branch)');
574
- }
575
- catch (e) {
576
- errors.push(`GIT_INIT_FAILED: ${e.message}`);
577
- return;
578
- }
579
- // Ensure node_modules/ in .gitignore
580
- const gitignorePath = (0, path_1.join)(target, '.gitignore');
581
- if ((0, fs_1.existsSync)(gitignorePath)) {
582
- const content = (0, fs_1.readFileSync)(gitignorePath, 'utf-8');
583
- if (!content.includes('node_modules/')) {
584
- const separator = content.endsWith('\n') ? '' : '\n';
585
- (0, fs_1.appendFileSync)(gitignorePath, `${separator}node_modules/\n`, 'utf-8');
586
- }
587
- }
588
- else {
589
- (0, fs_1.writeFileSync)(gitignorePath, 'node_modules/\n', 'utf-8');
590
- }
591
- // Initial commit
592
- try {
593
- // Stage all files
594
- await git.add({ fs: nodeFs, dir: target, filepath: '.' });
595
- await git.commit({
596
- fs: nodeFs,
597
- dir: target,
598
- message: 'chore: crewx init',
599
- author: INIT_AUTHOR,
600
- });
601
- console.log('✅ initial commit created (chore: crewx init)');
602
- }
603
- catch (e) {
604
- errors.push(`GIT_COMMIT_FAILED: ${e.message}`);
605
- }
606
- }
272
+ `}function T(t){return t==="cli/claude"||t==="cli/codex"}function S(t){if(t===void 0||t.length===0){return new Error("Missing --provider value. Expected: cli/claude | cli/codex")}return new Error(`Invalid --provider value: "${t}". Expected: cli/claude | cli/codex`)}function z(t){for(let e=0;e<t.length;e+=1){const i=t[e];if(i==="--provider"){const n=t[e+1];if(n===void 0||n.startsWith("--"))throw S(void 0);if(!T(n))throw S(n);return n}if(i?.startsWith("--provider=")){const n=i.slice("--provider=".length);if(!T(n))throw S(n);return n}}return void 0}function b(t,e={}){if(t!==void 0)return t;if((0,f.isProviderAvailable)("cli/claude",e))return"cli/claude";if((0,f.isProviderAvailable)("cli/codex",e))return"cli/codex";return"cli/claude"}async function V(t){const{path:e,skipHook:i=false,force:n=false,provider:r}=t;const c=b(r);const a=[];let p=false;let k=false;let g;if(!(0,s.existsSync)(e)){throw new Error(`PATH_NOT_FOUND: ${e}`)}const v=(0,d.join)(e,"crewx.yaml");const x=(0,d.join)(e,"crewx.yml");if((0,s.existsSync)(v)||(0,s.existsSync)(x)){if(!n){g="yaml-exists"}}if(!g){try{const o=J(P(c));(0,s.writeFileSync)(v,o,"utf-8");p=true}catch(o){throw new Error(`YAML_CREATE_FAILED: ${o.message}`)}if(!i){try{await(0,N.handleHookInstall)({projectRoot:e,yes:true});k=true}catch(o){a.push(`HOOK_INSTALL_FAILED: ${o.message}`)}}}for(const o of[".crewx/logs",".claude/commands","docs/goal","docs/daily","docs/wi","workflows"]){try{(0,s.mkdirSync)((0,d.join)(e,o),{recursive:true})}catch(l){a.push(`MKDIR_FAILED:${o}:${l.message}`)}}const C=[{dir:"docs/goal",file:"GOAL-TEMPLATE.md",content:B},{dir:"docs/daily",file:"DAILY-TEMPLATE.md",content:X},{dir:"docs/wi",file:"WI-TEMPLATE.md",content:U}];for(const o of C){const l=(0,d.join)(e,o.dir,o.file);if(n||!(0,s.existsSync)(l)){const h=(0,s.existsSync)(l)?"updated":"created";(0,s.writeFileSync)(l,o.content,"utf-8");console.log(`\u2705 ${o.dir}/ ${h} (${o.file})`)}}try{const o=(0,f.resolveWorkflowTemplatesPath)();for(const l of[f.WI_DEFAULT_FLOW_FILENAME,f.WI_PLAN_FLOW_FILENAME]){const h=(0,d.join)(o,l);const y=(0,d.join)(e,"workflows",l);if(n||!(0,s.existsSync)(y)){const R=(0,s.existsSync)(y)?"updated":"created";(0,s.copyFileSync)(h,y);console.log(`\u2705 workflows/ ${R} (${l})`)}}}catch(o){a.push(`WORKFLOW_TEMPLATE_FAILED:${o.message}`)}let A;let D;try{const o=new M.WorkspaceRepository().registerWorkspace(e);A=o.id;D=o.slug}catch(o){a.push(`WORKSPACE_REGISTER_FAILED: ${o.message}`)}const m=(0,d.join)(e,".gitignore");if(!(0,s.existsSync)(m)){(0,s.writeFileSync)(m,L+"\n","utf-8");console.log("\u2705 .gitignore updated with CrewX entries")}else{const o=(0,s.readFileSync)(m,"utf-8");if(!o.includes(K)){const l=o.endsWith("\n")?"\n":"\n\n";(0,s.appendFileSync)(m,l+L+"\n","utf-8");console.log("\u2705 .gitignore updated with CrewX entries")}else{console.log("\u2139 .gitignore already contains CrewX entries")}}await Z(e,a);const O=Q();return{yamlCreated:p,hookInstalled:k,errors:a,provider:c,skippedReason:g,workspaceId:A,slug:D,...O}}function Q(){const t=E.default.homedir();const e=u.join(t,".crewx");const i=u.join(e,q);const n=u.join(t,".claude","settings.json");try{(0,s.mkdirSync)(e,{recursive:true});(0,s.writeFileSync)(i,Y,"utf-8")}catch(a){return{statusLineConfigured:false,statusLineSkipped:false}}const r=`node ${i}`;let c={};if((0,s.existsSync)(n)){try{c=JSON.parse((0,s.readFileSync)(n,"utf-8"))}catch(a){c={}}}if(typeof c.statusLine==="string"&&c.statusLine!==""){if(c.statusLine===r){console.log("\u2139 statusLine already configured (CrewX claude-usage dump)");return{statusLineConfigured:false,statusLineSkipped:false}}console.log('\u2139 statusLine already set in ~/.claude/settings.json \u2014 skipping Claude usage dump setup.\n To enable manually, set "statusLine" to: '+r);return{statusLineConfigured:false,statusLineSkipped:true}}try{c.statusLine=r;const a=u.join(t,".claude");(0,s.mkdirSync)(a,{recursive:true});(0,s.writeFileSync)(n,JSON.stringify(c,null,2)+"\n","utf-8");console.log("\u2705 statusLine configured for Claude usage dump (~/.claude/settings.json)");return{statusLineConfigured:true,statusLineSkipped:false}}catch(a){return{statusLineConfigured:false,statusLineSkipped:false}}}async function Z(t,e){const i=E.default.homedir();if(t===i){console.log("\u2139 git init skipped: target is home directory");return}const n=u.parse(t);if(n.root===t||t==="/"){console.log("\u2139 git init skipped: target is filesystem root");return}let r=u.dirname(t);while(r!==u.parse(r).root){if((0,s.existsSync)((0,d.join)(r,".git"))){console.log(`\u2139 git init skipped: already inside a git repo (${r})`);return}const a=u.dirname(r);if(a===r)break;r=a}if((0,s.existsSync)((0,d.join)(t,".git"))){console.log("\u2139 git init skipped: .git already exists");return}try{await _.init({fs:I,dir:t,defaultBranch:"main"});console.log("\u2705 git repository initialized (main branch)")}catch(a){e.push(`GIT_INIT_FAILED: ${a.message}`);return}const c=(0,d.join)(t,".gitignore");if((0,s.existsSync)(c)){const a=(0,s.readFileSync)(c,"utf-8");if(!a.includes("node_modules/")){const p=a.endsWith("\n")?"":"\n";(0,s.appendFileSync)(c,`${p}node_modules/
273
+ `,"utf-8")}}else{(0,s.writeFileSync)(c,"node_modules/\n","utf-8")}try{await _.add({fs:I,dir:t,filepath:"."});await _.commit({fs:I,dir:t,message:"chore: crewx init",author:G});console.log("\u2705 initial commit created (chore: crewx init)")}catch(a){e.push(`GIT_COMMIT_FAILED: ${a.message}`)}}
@@ -1,9 +1,3 @@
1
- /**
2
- * crewx kill handler.
3
- * Kills a running task by ID or kills all running tasks.
4
- *
5
- * Usage:
6
- * crewx kill <task-id> Kill a specific running task
7
- * crewx kill --all Kill all running tasks
8
- */
1
+ /** Compatibility entry point for `crewx kill`; the implementation lives in stop.ts. */
2
+ export { handleStop } from './stop';
9
3
  export declare function handleKill(args: string[]): Promise<void>;
@@ -1,52 +1 @@
1
- "use strict";
2
- /**
3
- * crewx kill handler.
4
- * Kills a running task by ID or kills all running tasks.
5
- *
6
- * Usage:
7
- * crewx kill <task-id> Kill a specific running task
8
- * crewx kill --all Kill all running tasks
9
- */
10
- Object.defineProperty(exports, "__esModule", { value: true });
11
- exports.handleKill = handleKill;
12
- const repository_1 = require("@crewx/sdk/repository");
13
- async function handleKill(args) {
14
- const killAll = args.includes('--all');
15
- const taskId = args.find(a => !a.startsWith('--'));
16
- if (!taskId && !killAll) {
17
- console.error('Error: Please provide a task ID or use --all to kill all running tasks.');
18
- console.error('');
19
- console.error('Usage:');
20
- console.error(' crewx kill <task-id> Kill a running task by ID');
21
- console.error(' crewx kill --all Kill all running tasks');
22
- process.exit(1);
23
- return;
24
- }
25
- const repo = new repository_1.TaskRepository();
26
- if (killAll) {
27
- const running = repo.getRunningTasks();
28
- if (running.length === 0) {
29
- console.log('No running tasks found.');
30
- return;
31
- }
32
- console.log(`Found ${running.length} running task(s). Killing...`);
33
- for (const task of running) {
34
- const r = repo.killTask(task.id);
35
- if (r.killed) {
36
- console.log(`Killed task ${task.id}${r.pid ? ` (PID: ${r.pid})` : ''}`);
37
- }
38
- else {
39
- console.log(`Task ${task.id} could not be killed (may have already finished)`);
40
- }
41
- }
42
- return;
43
- }
44
- const r = repo.killTask(taskId);
45
- if (r.killed) {
46
- console.log(`Killed task ${taskId}${r.pid ? ` (PID: ${r.pid})` : ''}`);
47
- }
48
- else {
49
- console.error(`Error: Task not found or not running: ${taskId}`);
50
- process.exit(1);
51
- }
52
- }
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.handleStop=void 0;exports.handleKill=r;var t=require("./stop");Object.defineProperty(exports,"handleStop",{enumerable:true,get:function(){return t.handleStop}});const n=require("./stop");async function r(e){return(0,n.handleStop)(e,"kill")}