@crewx/cli 0.8.9-rc.2 → 0.8.9-rc.20

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.
@@ -237,7 +237,7 @@ Examples:
237
237
  crewx agent
238
238
  crewx agent ls
239
239
  crewx agent ls --role=PM
240
- crewx agent ls --team="CrewX Core 개발팀"
240
+ crewx agent ls --team="CrewX Core Team"
241
241
  crewx agent ls --provider=claude
242
242
  crewx agent ls --role=PM --provider=claude
243
243
  crewx agent ls --role=PM,general
@@ -13,6 +13,8 @@ export interface InitResult {
13
13
  skippedReason?: 'yaml-exists';
14
14
  workspaceId?: string;
15
15
  slug?: string;
16
+ statusLineConfigured?: boolean;
17
+ statusLineSkipped?: boolean;
16
18
  }
17
19
  /**
18
20
  * Programmatic init — creates crewx.yaml, support dirs, and optionally installs hooks.
@@ -7,12 +7,79 @@
7
7
  * crewx init Create crewx.yaml in current directory
8
8
  * crewx init --force Overwrite existing configuration
9
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
+ };
10
46
  Object.defineProperty(exports, "__esModule", { value: true });
11
47
  exports.handleInit = handleInit;
12
48
  const fs_1 = require("fs");
13
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"));
14
54
  const repository_1 = require("@crewx/sdk/repository");
15
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}
60
+ // Dumps Claude Code rate_limits (stdin payload) to ~/.crewx/claude-usage.json
61
+ const fs = require('fs');
62
+ const os = require('os');
63
+ const path = require('path');
64
+
65
+ const chunks = [];
66
+ process.stdin.on('data', (d) => chunks.push(d));
67
+ process.stdin.on('end', () => {
68
+ try {
69
+ const payload = JSON.parse(Buffer.concat(chunks).toString('utf-8'));
70
+ if (payload && payload.rate_limits) {
71
+ const out = {
72
+ rate_limits: payload.rate_limits,
73
+ updated_at: new Date().toISOString(),
74
+ };
75
+ const dir = path.join(os.homedir(), '.crewx');
76
+ fs.mkdirSync(dir, { recursive: true });
77
+ fs.writeFileSync(path.join(dir, 'claude-usage.json'), JSON.stringify(out, null, 2), 'utf-8');
78
+ }
79
+ } catch (_) {}
80
+ });
81
+ `;
82
+ const INIT_AUTHOR = { name: 'CrewX', email: 'crewx@local' };
16
83
  const CREWX_MARKER = '# CrewX runtime';
17
84
  const CREWX_GITIGNORE = `# CrewX runtime
18
85
  .crewx/
@@ -38,7 +105,7 @@ const DEFAULT_AGENTS = [
38
105
  team: 'core',
39
106
  provider: 'acp/claude',
40
107
  working_directory: './',
41
- description: '요구 분석·설계·작업 분해를 담당',
108
+ description: 'Owns requirements analysis, design, and work breakdown',
42
109
  options: {
43
110
  query: { effort: 'high' },
44
111
  execute: { effort: 'high', mode: 'bypassPermissions' },
@@ -55,7 +122,7 @@ const DEFAULT_AGENTS = [
55
122
  team: 'core',
56
123
  provider: 'acp/claude',
57
124
  working_directory: './',
58
- description: '실제 코드 작성과 테스트',
125
+ description: 'Implements code changes and tests',
59
126
  options: {
60
127
  query: { effort: 'high' },
61
128
  execute: { effort: 'high', mode: 'bypassPermissions' },
@@ -72,7 +139,7 @@ const DEFAULT_AGENTS = [
72
139
  team: 'core',
73
140
  provider: 'acp/claude',
74
141
  working_directory: './',
75
- description: '코드 품질·보안·가독성 리뷰',
142
+ description: 'Reviews code quality, security, and readability',
76
143
  options: {
77
144
  query: { effort: 'high' },
78
145
  execute: { effort: 'high', mode: 'bypassPermissions' },
@@ -91,7 +158,7 @@ notation:
91
158
  auto: "N% auto — L1 progress auto-calculated as weighted average of children"
92
159
  ---
93
160
 
94
- # 목표 제목
161
+ # Goal Title
95
162
 
96
163
  ## Period
97
164
  - Start: YYYY-MM-DD
@@ -99,7 +166,7 @@ notation:
99
166
  - Status: active
100
167
 
101
168
  ## Objective
102
- 목표는...
169
+ Describe the goal...
103
170
 
104
171
  ## Key Results
105
172
  - [ ] KR1:
@@ -260,6 +327,7 @@ npx doc section {design_doc} "{spec_id}"
260
327
  - [ ] \`npx vitest run src/server/\` passes (backend work)
261
328
  - [ ] \`npx vitest run src/ui/\` passes (frontend work)
262
329
  - [ ] (add feature-specific AC)
330
+ - [ ] (when worktree: true) Changes committed to the worktree branch (report commit hash). A completion report without a commit is invalid.
263
331
 
264
332
  ## Completion Report Format
265
333
 
@@ -275,6 +343,11 @@ Pass / Fail
275
343
  ### Test result
276
344
  N tests passed
277
345
 
346
+ ### Commit
347
+ - hash: <commit hash>
348
+ - branch: <worktree branch>
349
+ (empty = completion report invalid — worktree tasks only)
350
+
278
351
  ### Remaining items
279
352
  None / (list if any)
280
353
  \`\`\`
@@ -410,5 +483,124 @@ async function handleInit(opts) {
410
483
  console.log('ℹ .gitignore already contains CrewX entries');
411
484
  }
412
485
  }
413
- return { yamlCreated, hookInstalled, errors, skippedReason, workspaceId, slug };
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
+ }
414
606
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crewx/cli",
3
- "version": "0.8.9-rc.2",
3
+ "version": "0.8.9-rc.20",
4
4
  "license": "UNLICENSED",
5
5
  "engines": {
6
6
  "node": ">=20.19.0"
@@ -23,17 +23,18 @@
23
23
  "dependencies": {
24
24
  "@crewx/adapter-slack": "0.1.4",
25
25
  "better-sqlite3": "*",
26
- "@crewx/memory": "0.1.23",
27
- "@crewx/sdk": "0.8.9-rc.2",
28
- "@crewx/search": "0.1.10",
29
- "@crewx/doc": "0.1.8",
30
- "@crewx/wbs": "0.1.10",
31
- "@crewx/cron": "0.1.10",
32
- "@crewx/workflow": "0.3.22",
26
+ "isomorphic-git": "1.37.1",
27
+ "@crewx/sdk": "0.8.9-rc.20",
28
+ "@crewx/search": "0.1.10-rc.19",
29
+ "@crewx/memory": "0.1.23-rc.36",
30
+ "@crewx/doc": "0.1.9-rc.18",
31
+ "@crewx/cron": "0.1.10-rc.54",
32
+ "@crewx/wbs": "0.1.10-rc.49",
33
33
  "@crewx/skill": "0.1.20",
34
- "@crewx/chromex": "0.1.0",
35
- "@crewx/wi": "0.1.10",
36
- "@crewx/shared": "0.0.5"
34
+ "@crewx/workflow": "0.3.22-rc.36",
35
+ "@crewx/chromex": "0.1.0-rc.56",
36
+ "@crewx/wi": "0.1.10-rc.20",
37
+ "@crewx/shared": "0.0.6-rc.7"
37
38
  },
38
39
  "devDependencies": {
39
40
  "@types/better-sqlite3": "*",