@crewx/cli 0.8.0 → 0.8.1-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/crewx CHANGED
@@ -1,2 +1,2 @@
1
- #!/usr/bin/env node
2
- require('../dist/main.js');
1
+ #!/usr/bin/env node
2
+ require('../dist/main.js');
@@ -219,28 +219,28 @@ function loadAgentSkills() {
219
219
  }
220
220
  }
221
221
  function printAgentHelp() {
222
- console.log(`
223
- CrewX Agent Management
224
-
225
- Usage:
226
- crewx agent # List configured agents (default)
227
- crewx agent ls # List configured agents
228
- crewx agent list # Alias for ls
229
- crewx agent prompt <id> # Inspect rendered agent prompt
230
-
231
- Filter Options (for agent ls):
232
- --role <value> Filter by agent role (comma-separated for multiple: PM,Dev)
233
- --team <value> Filter by agent team (comma-separated for multiple)
234
- --provider <value> Filter by provider (comma-separated, partial match: claude)
235
-
236
- Examples:
237
- crewx agent
238
- crewx agent ls
239
- crewx agent ls --role=PM
240
- crewx agent ls --team="CrewX Core 개발팀"
241
- crewx agent ls --provider=claude
242
- crewx agent ls --role=PM --provider=claude
243
- crewx agent ls --role=PM,general
244
- CREWX_CONFIG=./crewx.yaml crewx agent list
222
+ console.log(`
223
+ CrewX Agent Management
224
+
225
+ Usage:
226
+ crewx agent # List configured agents (default)
227
+ crewx agent ls # List configured agents
228
+ crewx agent list # Alias for ls
229
+ crewx agent prompt <id> # Inspect rendered agent prompt
230
+
231
+ Filter Options (for agent ls):
232
+ --role <value> Filter by agent role (comma-separated for multiple: PM,Dev)
233
+ --team <value> Filter by agent team (comma-separated for multiple)
234
+ --provider <value> Filter by provider (comma-separated, partial match: claude)
235
+
236
+ Examples:
237
+ crewx agent
238
+ crewx agent ls
239
+ crewx agent ls --role=PM
240
+ crewx agent ls --team="CrewX Core 개발팀"
241
+ crewx agent ls --provider=claude
242
+ crewx agent ls --role=PM --provider=claude
243
+ crewx agent ls --role=PM,general
244
+ CREWX_CONFIG=./crewx.yaml crewx agent list
245
245
  `.trim());
246
246
  }
@@ -56,27 +56,27 @@ function escapeYamlBlock(text) {
56
56
  }
57
57
  function generateDefaultYaml(agents) {
58
58
  const agentBlocks = agents
59
- .map((a) => ` - id: "${a.id}"
60
- name: "${a.name}"
61
- role: "${a.role}"
62
- team: "${a.team}"
63
- provider: "${a.provider}"
64
- default_model: "${a.default_model}"
65
- working_directory: "${a.working_directory}"
66
- description: "${a.description}"
67
- system_prompt: |
59
+ .map((a) => ` - id: "${a.id}"
60
+ name: "${a.name}"
61
+ role: "${a.role}"
62
+ team: "${a.team}"
63
+ provider: "${a.provider}"
64
+ default_model: "${a.default_model}"
65
+ working_directory: "${a.working_directory}"
66
+ description: "${a.description}"
67
+ system_prompt: |
68
68
  ${escapeYamlBlock(a.system_prompt)}`)
69
69
  .join('\n\n');
70
- return `# CrewX Agents Configuration
71
- # Generated by 'crewx init'
72
-
73
- agents:
74
- ${agentBlocks}
75
-
76
- # Usage examples:
77
- # crewx query "@planner analyze this codebase"
78
- # crewx execute "@developer implement the feature described above"
79
- # crewx agent ls
70
+ return `# CrewX Agents Configuration
71
+ # Generated by 'crewx init'
72
+
73
+ agents:
74
+ ${agentBlocks}
75
+
76
+ # Usage examples:
77
+ # crewx query "@planner analyze this codebase"
78
+ # crewx execute "@developer implement the feature described above"
79
+ # crewx agent ls
80
80
  `;
81
81
  }
82
82
  /**
@@ -33,8 +33,8 @@ function getRunningTasks(dbRoot) {
33
33
  if (!db)
34
34
  return [];
35
35
  try {
36
- return db.prepare(`SELECT id, agent_id, prompt, mode, status, pid, started_at, completed_at,
37
- result, error, duration_ms
36
+ return db.prepare(`SELECT id, agent_id, prompt, mode, status, pid, started_at, completed_at,
37
+ result, error, duration_ms
38
38
  FROM tasks WHERE status = 'running' ORDER BY started_at DESC`).all();
39
39
  }
40
40
  finally {
@@ -47,8 +47,8 @@ function getAllTasks(dbRoot) {
47
47
  if (!db)
48
48
  return [];
49
49
  try {
50
- return db.prepare(`SELECT id, agent_id, prompt, mode, status, pid, started_at, completed_at,
51
- result, error, duration_ms
50
+ return db.prepare(`SELECT id, agent_id, prompt, mode, status, pid, started_at, completed_at,
51
+ result, error, duration_ms
52
52
  FROM tasks ORDER BY started_at DESC`).all();
53
53
  }
54
54
  finally {
@@ -61,8 +61,8 @@ function getTask(id, dbRoot) {
61
61
  if (!db)
62
62
  return undefined;
63
63
  try {
64
- return db.prepare(`SELECT id, agent_id, prompt, mode, status, pid, started_at, completed_at,
65
- result, error, duration_ms
64
+ return db.prepare(`SELECT id, agent_id, prompt, mode, status, pid, started_at, completed_at,
65
+ result, error, duration_ms
66
66
  FROM tasks WHERE id = ?`).get(id);
67
67
  }
68
68
  finally {
@@ -97,7 +97,7 @@ function killTask(id, dbRoot) {
97
97
  // ESRCH = process already gone — still clean up the record
98
98
  }
99
99
  }
100
- db.prepare(`UPDATE tasks SET status='failed', error='killed by user',
100
+ db.prepare(`UPDATE tasks SET status='failed', error='killed by user',
101
101
  completed_at=?, pid=NULL WHERE id=?`).run(new Date().toISOString(), id);
102
102
  return { ok: true, message: `Killed task ${id}${task.pid ? ` (PID: ${task.pid})` : ''}` };
103
103
  }
package/dist/main.js CHANGED
@@ -234,65 +234,65 @@ async function runSkill(skillArgs) {
234
234
  });
235
235
  }
236
236
  function printHelp() {
237
- console.log(`
238
- CrewX CLI v${version_1.CLI_VERSION}
239
-
240
- Usage:
241
- crewx <command> [options]
242
-
243
- Query / Execute:
244
- q|query [@agent] <message> Query an agent (read-only)
245
- x|execute [@agent] <task> Execute a task with an agent (write-capable)
246
-
247
- @agent is optional — defaults to @crewx when omitted.
248
-
249
- Common flags:
250
- --thread <name> Conversation thread
251
- --provider <cli/xxx> Provider override
252
- --metadata <json> Extra metadata (JSON object, double-quoted). Propagated to events/hooks/tracing.
253
- Invalid JSON aborts with exit code 2.
254
- e.g. --metadata='{"workflow_id":"wf-1"}'
255
- --verbose Debug output mode (default: raw response only)
256
- --config/-c <path> Config file path (default: CREWX_CONFIG or crewx.yaml)
257
- --output-format <fmt> Output format (json|text|stream-json)
258
- --effort <level> Model effort (high|medium|low)
259
-
260
- Agent Management:
261
- agent ls [options] List configured agents
262
- --role <value> Filter by role (comma-separated for OR match)
263
- --team <value> Filter by team (comma-separated for OR match)
264
- --provider <value> Filter by provider (comma-separated for OR match)
265
- agent prompt <@id> Show rendered system prompt for an agent
266
-
267
- Task Management:
268
- ps List running tasks
269
- kill <task-id> Kill a running task
270
- kill --all Kill all running tasks
271
- result [task-id] Get task result (or list recent tasks)
272
-
273
- Logs & Diagnostics:
274
- log [ls|<task-id>] View task logs
275
- doctor [--config <path>] Run system diagnosis
276
- init [--force] [--config <p>] Initialize crewx.yaml
277
-
278
- Built-in Tools:
279
- memory <args> Memory tool
280
- search <args> Search tool
281
- doc <args> Doc tool
282
- wbs <args> WBS tool
283
- cron <args> Cron tool
284
- workflow <args> Workflow tool
285
- skill <args> Skill tool
286
-
287
- Hook Platform:
288
- hook install [--yes] Install PreToolUse hook in .claude/settings.json
289
- hook uninstall Remove crewx hook from .claude/settings.json
290
- hook status Show hook installation status and plugins
291
- hook-dispatch Internal: IPC router called by Claude (stdin→stdout)
292
-
293
- Global Options:
294
- --help, -h Show this help
295
- --version, -v Show version
237
+ console.log(`
238
+ CrewX CLI v${version_1.CLI_VERSION}
239
+
240
+ Usage:
241
+ crewx <command> [options]
242
+
243
+ Query / Execute:
244
+ q|query [@agent] <message> Query an agent (read-only)
245
+ x|execute [@agent] <task> Execute a task with an agent (write-capable)
246
+
247
+ @agent is optional — defaults to @crewx when omitted.
248
+
249
+ Common flags:
250
+ --thread <name> Conversation thread
251
+ --provider <cli/xxx> Provider override
252
+ --metadata <json> Extra metadata (JSON object, double-quoted). Propagated to events/hooks/tracing.
253
+ Invalid JSON aborts with exit code 2.
254
+ e.g. --metadata='{"workflow_id":"wf-1"}'
255
+ --verbose Debug output mode (default: raw response only)
256
+ --config/-c <path> Config file path (default: CREWX_CONFIG or crewx.yaml)
257
+ --output-format <fmt> Output format (json|text|stream-json)
258
+ --effort <level> Model effort (high|medium|low)
259
+
260
+ Agent Management:
261
+ agent ls [options] List configured agents
262
+ --role <value> Filter by role (comma-separated for OR match)
263
+ --team <value> Filter by team (comma-separated for OR match)
264
+ --provider <value> Filter by provider (comma-separated for OR match)
265
+ agent prompt <@id> Show rendered system prompt for an agent
266
+
267
+ Task Management:
268
+ ps List running tasks
269
+ kill <task-id> Kill a running task
270
+ kill --all Kill all running tasks
271
+ result [task-id] Get task result (or list recent tasks)
272
+
273
+ Logs & Diagnostics:
274
+ log [ls|<task-id>] View task logs
275
+ doctor [--config <path>] Run system diagnosis
276
+ init [--force] [--config <p>] Initialize crewx.yaml
277
+
278
+ Built-in Tools:
279
+ memory <args> Memory tool
280
+ search <args> Search tool
281
+ doc <args> Doc tool
282
+ wbs <args> WBS tool
283
+ cron <args> Cron tool
284
+ workflow <args> Workflow tool
285
+ skill <args> Skill tool
286
+
287
+ Hook Platform:
288
+ hook install [--yes] Install PreToolUse hook in .claude/settings.json
289
+ hook uninstall Remove crewx hook from .claude/settings.json
290
+ hook status Show hook installation status and plugins
291
+ hook-dispatch Internal: IPC router called by Claude (stdin→stdout)
292
+
293
+ Global Options:
294
+ --help, -h Show this help
295
+ --version, -v Show version
296
296
  `.trim());
297
297
  }
298
298
  main().catch((err) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crewx/cli",
3
- "version": "0.8.0",
3
+ "version": "0.8.1-rc.1",
4
4
  "license": "UNLICENSED",
5
5
  "engines": {
6
6
  "node": ">=20.19.0"
@@ -27,12 +27,12 @@
27
27
  "dependencies": {
28
28
  "@crewx/adapter-slack": "0.1.3",
29
29
  "better-sqlite3": "*",
30
- "@crewx/sdk": "0.8.0",
31
- "@crewx/doc": "0.1.7",
30
+ "@crewx/memory": "0.1.9",
32
31
  "@crewx/wbs": "0.1.8",
33
- "@crewx/search": "0.1.8",
32
+ "@crewx/sdk": "0.8.1-rc.1",
34
33
  "@crewx/cron": "0.1.7",
35
- "@crewx/memory": "0.1.9",
34
+ "@crewx/doc": "0.1.7",
35
+ "@crewx/search": "0.1.8",
36
36
  "@crewx/workflow": "0.3.7",
37
37
  "@crewx/skill": "0.1.6",
38
38
  "@crewx/shared": "0.0.4"
@@ -1,22 +0,0 @@
1
- /**
2
- * DenyIfTouchesSecretsPlugin — Phase 0 demo HookPlugin.
3
- *
4
- * Denies Bash tool calls whose command string contains ".env".
5
- * Pure string matching — trivially bypassable (see README).
6
- *
7
- * SECURITY NOTE:
8
- * Do NOT include tool.input content in deny reasons.
9
- * Use static messages only to prevent prompt injection.
10
- * ✅ return ctx.deny('Secrets-related command');
11
- * ❌ return ctx.deny(`Blocked: ${cmd}`);
12
- */
13
- import { HookPlugin } from '@crewx/sdk/hooks';
14
- import type { HookContext, HookResult } from '@crewx/sdk/hooks';
15
- export declare class DenyIfTouchesSecretsPlugin extends HookPlugin {
16
- readonly name = "deny-secrets";
17
- readonly version = "0.1.0";
18
- readonly capabilities: {
19
- required: readonly ["deny"];
20
- };
21
- run(ctx: HookContext): Promise<HookResult>;
22
- }
@@ -1,40 +0,0 @@
1
- "use strict";
2
- /**
3
- * DenyIfTouchesSecretsPlugin — Phase 0 demo HookPlugin.
4
- *
5
- * Denies Bash tool calls whose command string contains ".env".
6
- * Pure string matching — trivially bypassable (see README).
7
- *
8
- * SECURITY NOTE:
9
- * Do NOT include tool.input content in deny reasons.
10
- * Use static messages only to prevent prompt injection.
11
- * ✅ return ctx.deny('Secrets-related command');
12
- * ❌ return ctx.deny(`Blocked: ${cmd}`);
13
- */
14
- Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.DenyIfTouchesSecretsPlugin = void 0;
16
- const hooks_1 = require("@crewx/sdk/hooks");
17
- const SECRET_PATTERNS = ['.env', 'credentials.json', 'service-account-key.json'];
18
- const SHELL_TOOL_NAMES = new Set(['Bash', 'shell', 'local_shell']);
19
- class DenyIfTouchesSecretsPlugin extends hooks_1.HookPlugin {
20
- name = 'deny-secrets';
21
- version = '0.1.0';
22
- capabilities = { required: ['deny'] };
23
- async run(ctx) {
24
- if (!SHELL_TOOL_NAMES.has(ctx.tool.rawName) && ctx.tool.name !== 'shell') {
25
- return ctx.pass();
26
- }
27
- const input = ctx.tool.input;
28
- const command = input?.command;
29
- if (typeof command !== 'string') {
30
- return ctx.pass();
31
- }
32
- for (const pattern of SECRET_PATTERNS) {
33
- if (command.includes(pattern)) {
34
- return ctx.deny('Secrets-related command');
35
- }
36
- }
37
- return ctx.pass();
38
- }
39
- }
40
- exports.DenyIfTouchesSecretsPlugin = DenyIfTouchesSecretsPlugin;
@@ -1,24 +0,0 @@
1
- /**
2
- * EchoObserverPlugin — Tool observer that echoes events to a JSONL log.
3
- *
4
- * Observes tool:before / tool:after events from the Crewx event bus
5
- * and appends them as JSONL to ~/.crewx/logs/echo-hook.log.
6
- * Pure observer — no flow control (deny/inject/modify not applicable).
7
- */
8
- import { ToolObserverPlugin } from '@crewx/sdk/hooks';
9
- import type { ObserverContext, ObserverResult } from '@crewx/sdk/hooks';
10
- export declare class EchoHookPlugin extends ToolObserverPlugin {
11
- readonly name = "echo-hook";
12
- readonly version = "0.0.1";
13
- readonly on: {
14
- beforeTool: true;
15
- afterTool: true;
16
- beforePrompt: true;
17
- sessionStart: true;
18
- };
19
- private readonly logPath;
20
- constructor(logDir?: string);
21
- run(ctx: ObserverContext): Promise<ObserverResult>;
22
- private ensureLogDir;
23
- private echo;
24
- }
@@ -1,60 +0,0 @@
1
- "use strict";
2
- /**
3
- * EchoObserverPlugin — Tool observer that echoes events to a JSONL log.
4
- *
5
- * Observes tool:before / tool:after events from the Crewx event bus
6
- * and appends them as JSONL to ~/.crewx/logs/echo-hook.log.
7
- * Pure observer — no flow control (deny/inject/modify not applicable).
8
- */
9
- Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.EchoHookPlugin = void 0;
11
- const fs_1 = require("fs");
12
- const path_1 = require("path");
13
- const os_1 = require("os");
14
- const hooks_1 = require("@crewx/sdk/hooks");
15
- class EchoHookPlugin extends hooks_1.ToolObserverPlugin {
16
- name = 'echo-hook';
17
- version = '0.0.1';
18
- on = {
19
- beforeTool: true,
20
- afterTool: true,
21
- beforePrompt: true,
22
- sessionStart: true,
23
- };
24
- logPath;
25
- constructor(logDir) {
26
- super();
27
- this.logPath = (0, path_1.join)(logDir ?? (0, os_1.homedir)(), '.crewx', 'logs', 'echo-hook.log');
28
- this.ensureLogDir();
29
- }
30
- async run(ctx) {
31
- this.echo(ctx);
32
- return ctx.pass();
33
- }
34
- ensureLogDir() {
35
- const dir = (0, path_1.dirname)(this.logPath);
36
- if (!(0, fs_1.existsSync)(dir)) {
37
- (0, fs_1.mkdirSync)(dir, { recursive: true, mode: 0o700 });
38
- }
39
- }
40
- echo(ctx) {
41
- try {
42
- const line = JSON.stringify({
43
- timestamp: new Date().toISOString(),
44
- event: ctx.event,
45
- traceId: ctx.traceId,
46
- agent: ctx.agent,
47
- provider: ctx.provider,
48
- thread: ctx.thread,
49
- tool: ctx.tool,
50
- cwd: ctx.cwd,
51
- sessionId: ctx.sessionId,
52
- });
53
- (0, fs_1.appendFileSync)(this.logPath, line + '\n', { encoding: 'utf8', mode: 0o600 });
54
- }
55
- catch {
56
- // Non-fatal
57
- }
58
- }
59
- }
60
- exports.EchoHookPlugin = EchoHookPlugin;
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env npx tsx
2
- /**
3
- * Phase 0 e2e verification — EchoHookPlugin logs Claude Code tool calls.
4
- *
5
- * Run: npx tsx packages/cli/src/plugins/examples/verify-echo-hook.ts
6
- * Prereq: claude CLI installed, crewx.yaml with @claude agent
7
- */
8
- export {};
@@ -1,47 +0,0 @@
1
- #!/usr/bin/env npx tsx
2
- "use strict";
3
- /**
4
- * Phase 0 e2e verification — EchoHookPlugin logs Claude Code tool calls.
5
- *
6
- * Run: npx tsx packages/cli/src/plugins/examples/verify-echo-hook.ts
7
- * Prereq: claude CLI installed, crewx.yaml with @claude agent
8
- */
9
- Object.defineProperty(exports, "__esModule", { value: true });
10
- const sdk_1 = require("@crewx/sdk");
11
- const echo_hook_1 = require("./echo-hook");
12
- const fs_1 = require("fs");
13
- const path_1 = require("path");
14
- const os_1 = require("os");
15
- const LOG_PATH = (0, path_1.join)((0, os_1.homedir)(), '.crewx', 'logs', 'echo-hook.log');
16
- async function main() {
17
- if ((0, fs_1.existsSync)(LOG_PATH))
18
- (0, fs_1.unlinkSync)(LOG_PATH);
19
- const crewx = await sdk_1.Crewx.loadYaml('crewx.yaml');
20
- await crewx.use(new echo_hook_1.EchoHookPlugin());
21
- console.log('[verify] querying @claude with "ls"...');
22
- await crewx.query('@claude', 'Run ls in the current directory. Use the Bash tool.');
23
- await crewx.close();
24
- if (!(0, fs_1.existsSync)(LOG_PATH)) {
25
- console.error('[FAIL] echo-hook.log not created');
26
- process.exit(1);
27
- }
28
- const lines = (0, fs_1.readFileSync)(LOG_PATH, 'utf8').trim().split('\n');
29
- const entries = lines.map((l) => JSON.parse(l));
30
- const hasBeforeTool = entries.some((e) => e.event === 'beforeTool');
31
- const hasTraceId = entries.every((e) => e.traceId?.startsWith('tsk_'));
32
- const hasToolName = entries
33
- .filter((e) => e.event === 'beforeTool')
34
- .every((e) => typeof e.tool?.rawName === 'string' && e.tool.rawName.length > 0);
35
- console.log(`[verify] entries: ${entries.length}`);
36
- console.log(`[verify] beforeTool: ${hasBeforeTool}`);
37
- console.log(`[verify] traceId: ${hasTraceId}`);
38
- console.log(`[verify] toolName: ${hasToolName}`);
39
- if (hasBeforeTool && hasTraceId && hasToolName) {
40
- console.log('[PASS] Phase 0 e2e verification passed');
41
- }
42
- else {
43
- console.error('[FAIL] Some checks failed');
44
- process.exit(1);
45
- }
46
- }
47
- main().catch((err) => { console.error(err); process.exit(1); });
@@ -1,13 +0,0 @@
1
- /**
2
- * CLI convenience wrapper for SqliteTracingPlugin.
3
- * Accepts a dbRoot string or an options object so existing CLI tests can pass
4
- * a temp directory path directly.
5
- */
6
- import { SqliteTracingPlugin as SdkPlugin } from '@crewx/sdk/plugins';
7
- export type { SqliteTracingPluginOptions } from '@crewx/sdk/plugins';
8
- export declare class SqliteTracingPlugin extends SdkPlugin {
9
- constructor(dbRootOrOpts?: string | {
10
- dbRoot?: string;
11
- version?: string;
12
- });
13
- }
@@ -1,20 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SqliteTracingPlugin = void 0;
4
- /**
5
- * CLI convenience wrapper for SqliteTracingPlugin.
6
- * Accepts a dbRoot string or an options object so existing CLI tests can pass
7
- * a temp directory path directly.
8
- */
9
- const plugins_1 = require("@crewx/sdk/plugins");
10
- class SqliteTracingPlugin extends plugins_1.SqliteTracingPlugin {
11
- constructor(dbRootOrOpts) {
12
- if (typeof dbRootOrOpts === 'string') {
13
- super({ dbRoot: dbRootOrOpts });
14
- }
15
- else {
16
- super(dbRootOrOpts);
17
- }
18
- }
19
- }
20
- exports.SqliteTracingPlugin = SqliteTracingPlugin;