@crewx/cli 0.8.4-rc.0 → 0.8.4-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. package/README.md +33 -33
  2. package/bin/crewx +2 -2
  3. package/dist/commands/agent.js +23 -23
  4. package/dist/commands/init.js +20 -20
  5. package/dist/commands/task-db.d.ts +33 -0
  6. package/dist/commands/task-db.js +107 -0
  7. package/dist/examples/deny-secrets-plugin.d.ts +22 -0
  8. package/dist/examples/deny-secrets-plugin.js +40 -0
  9. package/dist/main.js +72 -72
  10. package/dist/plugins/examples/echo-hook.d.ts +24 -0
  11. package/dist/plugins/examples/echo-hook.js +60 -0
  12. package/dist/plugins/examples/verify-echo-hook.d.ts +8 -0
  13. package/dist/plugins/examples/verify-echo-hook.js +47 -0
  14. package/dist/plugins/sqlite-tracing.d.ts +11 -0
  15. package/dist/plugins/sqlite-tracing.js +19 -0
  16. package/dist/repository/workspace.repository.d.ts +26 -0
  17. package/dist/repository/workspace.repository.js +111 -0
  18. package/dist/schema/tasks.d.ts +7 -0
  19. package/dist/schema/tasks.js +48 -0
  20. package/package.json +18 -18
  21. package/dist/ai-provider.service.d.ts +0 -34
  22. package/dist/ai-provider.service.js +0 -311
  23. package/dist/ai-provider.service.js.map +0 -1
  24. package/dist/ai.service.d.ts +0 -17
  25. package/dist/ai.service.js +0 -51
  26. package/dist/ai.service.js.map +0 -1
  27. package/dist/app.module.d.ts +0 -5
  28. package/dist/app.module.js +0 -165
  29. package/dist/app.module.js.map +0 -1
  30. package/dist/cli/agent.handler.d.ts +0 -2
  31. package/dist/cli/agent.handler.js +0 -186
  32. package/dist/cli/agent.handler.js.map +0 -1
  33. package/dist/cli/builtin.handler.d.ts +0 -3
  34. package/dist/cli/builtin.handler.js +0 -110
  35. package/dist/cli/builtin.handler.js.map +0 -1
  36. package/dist/cli/chat.handler.d.ts +0 -20
  37. package/dist/cli/chat.handler.js +0 -446
  38. package/dist/cli/chat.handler.js.map +0 -1
  39. package/dist/cli/cli.handler.d.ts +0 -4
  40. package/dist/cli/cli.handler.js +0 -119
  41. package/dist/cli/cli.handler.js.map +0 -1
  42. package/dist/cli/doctor.handler.d.ts +0 -38
  43. package/dist/cli/doctor.handler.js +0 -495
  44. package/dist/cli/doctor.handler.js.map +0 -1
  45. package/dist/cli/execute.handler.d.ts +0 -2
  46. package/dist/cli/execute.handler.js +0 -321
  47. package/dist/cli/execute.handler.js.map +0 -1
  48. package/dist/cli/help.handler.d.ts +0 -2
  49. package/dist/cli/help.handler.js +0 -10
  50. package/dist/cli/help.handler.js.map +0 -1
  51. package/dist/cli/init.handler.d.ts +0 -26
  52. package/dist/cli/init.handler.js +0 -450
  53. package/dist/cli/init.handler.js.map +0 -1
  54. package/dist/cli/log.handler.d.ts +0 -2
  55. package/dist/cli/log.handler.js +0 -69
  56. package/dist/cli/log.handler.js.map +0 -1
  57. package/dist/cli/mcp.handler.d.ts +0 -3
  58. package/dist/cli/mcp.handler.js +0 -121
  59. package/dist/cli/mcp.handler.js.map +0 -1
  60. package/dist/cli/query.handler.d.ts +0 -2
  61. package/dist/cli/query.handler.js +0 -379
  62. package/dist/cli/query.handler.js.map +0 -1
  63. package/dist/cli/skill.handler.d.ts +0 -2
  64. package/dist/cli/skill.handler.js +0 -252
  65. package/dist/cli/skill.handler.js.map +0 -1
  66. package/dist/cli/slack-files.handler.d.ts +0 -2
  67. package/dist/cli/slack-files.handler.js +0 -291
  68. package/dist/cli/slack-files.handler.js.map +0 -1
  69. package/dist/cli/template.handler.d.ts +0 -2
  70. package/dist/cli/template.handler.js +0 -188
  71. package/dist/cli/template.handler.js.map +0 -1
  72. package/dist/cli/templates.handler.d.ts +0 -2
  73. package/dist/cli/templates.handler.js +0 -100
  74. package/dist/cli/templates.handler.js.map +0 -1
  75. package/dist/cli-options.d.ts +0 -39
  76. package/dist/cli-options.js +0 -355
  77. package/dist/cli-options.js.map +0 -1
  78. package/dist/config/timeout.config.d.ts +0 -14
  79. package/dist/config/timeout.config.js +0 -34
  80. package/dist/config/timeout.config.js.map +0 -1
  81. package/dist/conversation/base-conversation-history.provider.d.ts +0 -12
  82. package/dist/conversation/base-conversation-history.provider.js +0 -45
  83. package/dist/conversation/base-conversation-history.provider.js.map +0 -1
  84. package/dist/conversation/cli-conversation-history.provider.d.ts +0 -16
  85. package/dist/conversation/cli-conversation-history.provider.js +0 -111
  86. package/dist/conversation/cli-conversation-history.provider.js.map +0 -1
  87. package/dist/conversation/conversation-provider.factory.d.ts +0 -10
  88. package/dist/conversation/conversation-provider.factory.js +0 -50
  89. package/dist/conversation/conversation-provider.factory.js.map +0 -1
  90. package/dist/conversation/index.d.ts +0 -6
  91. package/dist/conversation/index.js +0 -27
  92. package/dist/conversation/index.js.map +0 -1
  93. package/dist/conversation/slack-conversation-history.provider.d.ts +0 -29
  94. package/dist/conversation/slack-conversation-history.provider.js +0 -302
  95. package/dist/conversation/slack-conversation-history.provider.js.map +0 -1
  96. package/dist/crewx.tool.d.ts +0 -359
  97. package/dist/crewx.tool.js +0 -2501
  98. package/dist/crewx.tool.js.map +0 -1
  99. package/dist/crewx.tool.spec.d.ts +0 -1
  100. package/dist/crewx.tool.spec.js +0 -158
  101. package/dist/crewx.tool.spec.js.map +0 -1
  102. package/dist/guards/bearer-auth.guard.d.ts +0 -7
  103. package/dist/guards/bearer-auth.guard.js +0 -44
  104. package/dist/guards/bearer-auth.guard.js.map +0 -1
  105. package/dist/health.controller.d.ts +0 -6
  106. package/dist/health.controller.js +0 -32
  107. package/dist/health.controller.js.map +0 -1
  108. package/dist/main.js.map +0 -1
  109. package/dist/mcp.controller.d.ts +0 -8
  110. package/dist/mcp.controller.js +0 -62
  111. package/dist/mcp.controller.js.map +0 -1
  112. package/dist/package.json +0 -3
  113. package/dist/providers/dynamic-provider.factory.d.ts +0 -15
  114. package/dist/providers/dynamic-provider.factory.js +0 -133
  115. package/dist/providers/dynamic-provider.factory.js.map +0 -1
  116. package/dist/providers/logger.adapter.d.ts +0 -6
  117. package/dist/providers/logger.adapter.js +0 -102
  118. package/dist/providers/logger.adapter.js.map +0 -1
  119. package/dist/services/agent-loader.service.d.ts +0 -35
  120. package/dist/services/agent-loader.service.js +0 -622
  121. package/dist/services/agent-loader.service.js.map +0 -1
  122. package/dist/services/auth.service.d.ts +0 -9
  123. package/dist/services/auth.service.js +0 -47
  124. package/dist/services/auth.service.js.map +0 -1
  125. package/dist/services/config-validator.service.d.ts +0 -29
  126. package/dist/services/config-validator.service.js +0 -483
  127. package/dist/services/config-validator.service.js.map +0 -1
  128. package/dist/services/config.service.d.ts +0 -45
  129. package/dist/services/config.service.js +0 -352
  130. package/dist/services/config.service.js.map +0 -1
  131. package/dist/services/document-loader.service.d.ts +0 -21
  132. package/dist/services/document-loader.service.js +0 -156
  133. package/dist/services/document-loader.service.js.map +0 -1
  134. package/dist/services/help.service.d.ts +0 -5
  135. package/dist/services/help.service.js +0 -139
  136. package/dist/services/help.service.js.map +0 -1
  137. package/dist/services/intelligent-compression.service.d.ts +0 -20
  138. package/dist/services/intelligent-compression.service.js +0 -179
  139. package/dist/services/intelligent-compression.service.js.map +0 -1
  140. package/dist/services/mcp-client.service.d.ts +0 -26
  141. package/dist/services/mcp-client.service.js +0 -81
  142. package/dist/services/mcp-client.service.js.map +0 -1
  143. package/dist/services/parallel-processing.service.d.ts +0 -108
  144. package/dist/services/parallel-processing.service.js +0 -333
  145. package/dist/services/parallel-processing.service.js.map +0 -1
  146. package/dist/services/provider-bridge.service.d.ts +0 -35
  147. package/dist/services/provider-bridge.service.js +0 -224
  148. package/dist/services/provider-bridge.service.js.map +0 -1
  149. package/dist/services/remote-agent.service.d.ts +0 -50
  150. package/dist/services/remote-agent.service.js +0 -171
  151. package/dist/services/remote-agent.service.js.map +0 -1
  152. package/dist/services/result-formatter.service.d.ts +0 -27
  153. package/dist/services/result-formatter.service.js +0 -126
  154. package/dist/services/result-formatter.service.js.map +0 -1
  155. package/dist/services/skill-loader.service.d.ts +0 -15
  156. package/dist/services/skill-loader.service.js +0 -278
  157. package/dist/services/skill-loader.service.js.map +0 -1
  158. package/dist/services/skill.service.d.ts +0 -67
  159. package/dist/services/skill.service.js +0 -670
  160. package/dist/services/skill.service.js.map +0 -1
  161. package/dist/services/skill.service.spec.d.ts +0 -1
  162. package/dist/services/skill.service.spec.js +0 -35
  163. package/dist/services/skill.service.spec.js.map +0 -1
  164. package/dist/services/task-management.service.d.ts +0 -65
  165. package/dist/services/task-management.service.js +0 -288
  166. package/dist/services/task-management.service.js.map +0 -1
  167. package/dist/services/template.service.d.ts +0 -61
  168. package/dist/services/template.service.js +0 -416
  169. package/dist/services/template.service.js.map +0 -1
  170. package/dist/services/tool-call.service.d.ts +0 -19
  171. package/dist/services/tool-call.service.js +0 -1061
  172. package/dist/services/tool-call.service.js.map +0 -1
  173. package/dist/services/tracing.service.d.ts +0 -200
  174. package/dist/services/tracing.service.js +0 -1290
  175. package/dist/services/tracing.service.js.map +0 -1
  176. package/dist/slack/formatters/message.formatter.d.ts +0 -32
  177. package/dist/slack/formatters/message.formatter.js +0 -352
  178. package/dist/slack/formatters/message.formatter.js.map +0 -1
  179. package/dist/slack/services/slack-file-download.service.d.ts +0 -58
  180. package/dist/slack/services/slack-file-download.service.js +0 -558
  181. package/dist/slack/services/slack-file-download.service.js.map +0 -1
  182. package/dist/slack/slack-bot.d.ts +0 -33
  183. package/dist/slack/slack-bot.js +0 -567
  184. package/dist/slack/slack-bot.js.map +0 -1
  185. package/dist/stderr.logger.d.ts +0 -8
  186. package/dist/stderr.logger.js +0 -26
  187. package/dist/stderr.logger.js.map +0 -1
  188. package/dist/types/usage.types.d.ts +0 -107
  189. package/dist/types/usage.types.js +0 -3
  190. package/dist/types/usage.types.js.map +0 -1
  191. package/dist/utils/config-utils.d.ts +0 -15
  192. package/dist/utils/config-utils.js +0 -69
  193. package/dist/utils/config-utils.js.map +0 -1
  194. package/dist/utils/extract-text.d.ts +0 -1
  195. package/dist/utils/extract-text.js +0 -15
  196. package/dist/utils/extract-text.js.map +0 -1
  197. package/dist/utils/mcp-installer.d.ts +0 -20
  198. package/dist/utils/mcp-installer.js +0 -199
  199. package/dist/utils/mcp-installer.js.map +0 -1
  200. package/dist/utils/project-hash.d.ts +0 -6
  201. package/dist/utils/project-hash.js +0 -70
  202. package/dist/utils/project-hash.js.map +0 -1
  203. package/dist/utils/simple-security.d.ts +0 -3
  204. package/dist/utils/simple-security.js +0 -20
  205. package/dist/utils/simple-security.js.map +0 -1
  206. package/dist/utils/stdin-utils.d.ts +0 -6
  207. package/dist/utils/stdin-utils.js +0 -109
  208. package/dist/utils/stdin-utils.js.map +0 -1
  209. package/dist/utils/template-processor.d.ts +0 -4
  210. package/dist/utils/template-processor.js +0 -266
  211. package/dist/utils/template-processor.js.map +0 -1
  212. package/dist/utils/terminal-message-formatter.d.ts +0 -23
  213. package/dist/utils/terminal-message-formatter.js +0 -136
  214. package/dist/utils/terminal-message-formatter.js.map +0 -1
  215. package/dist/version.d.ts +0 -1
  216. package/dist/version.js +0 -17
  217. package/dist/version.js.map +0 -1
  218. package/dist/workspace.service.d.ts +0 -44
  219. package/dist/workspace.service.js +0 -299
  220. package/dist/workspace.service.js.map +0 -1
package/README.md CHANGED
@@ -1,33 +1,33 @@
1
- # CrewX CLI
2
-
3
- > Build AI agent teams from your terminal.
4
-
5
- [![npm version](https://img.shields.io/npm/v/@crewx/cli.svg)](https://www.npmjs.com/package/@crewx/cli)
6
- [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)
7
-
8
- ## Installation
9
-
10
- ```bash
11
- npm install -g @crewx/cli
12
- ```
13
-
14
- ## Quick Start
15
-
16
- ```bash
17
- crewx q "@assistant hello"
18
- crewx x "@coder implement feature X"
19
- crewx agent list
20
- ```
21
-
22
- Run `crewx --help` for the full list.
23
-
24
- ## What is CrewX?
25
-
26
- CrewX lets you define AI agents in a single `crewx.yaml` and call them from the terminal.
27
-
28
- This repository contains the **CrewX CLI** — a thin wrapper over the [`@crewx/sdk`](https://www.npmjs.com/package/@crewx/sdk) runtime (distributed via npm).
29
-
30
- ## License
31
-
32
- CLI source: [Apache-2.0](LICENSE).
33
- `@crewx/sdk` runtime: proprietary on npm.
1
+ # CrewX CLI
2
+
3
+ > Build AI agent teams from your terminal.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@crewx/cli.svg)](https://www.npmjs.com/package/@crewx/cli)
6
+ [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ npm install -g @crewx/cli
12
+ ```
13
+
14
+ ## Quick Start
15
+
16
+ ```bash
17
+ crewx q "@assistant hello"
18
+ crewx x "@coder implement feature X"
19
+ crewx agent list
20
+ ```
21
+
22
+ Run `crewx --help` for the full list.
23
+
24
+ ## What is CrewX?
25
+
26
+ CrewX lets you define AI agents in a single `crewx.yaml` and call them from the terminal.
27
+
28
+ This repository contains the **CrewX CLI** — a thin wrapper over the [`@crewx/sdk`](https://www.npmjs.com/package/@crewx/sdk) runtime (distributed via npm).
29
+
30
+ ## License
31
+
32
+ CLI source: [Apache-2.0](LICENSE).
33
+ `@crewx/sdk` runtime: proprietary on npm.
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
  }
@@ -64,28 +64,28 @@ function indentBlock(text, spaces) {
64
64
  }
65
65
  function generateDefaultYaml(agents) {
66
66
  const agentBlocks = agents
67
- .map((a) => ` - id: "${a.id}"
68
- name: "${a.name}"
69
- role: "${a.role}"
70
- team: "${a.team}"
71
- provider: "${a.provider}"
72
- working_directory: "${a.working_directory}"
73
- description: "${a.description}"
74
- inline:
75
- model: "${a.inline.model}"
76
- system_prompt: |
67
+ .map((a) => ` - id: "${a.id}"
68
+ name: "${a.name}"
69
+ role: "${a.role}"
70
+ team: "${a.team}"
71
+ provider: "${a.provider}"
72
+ working_directory: "${a.working_directory}"
73
+ description: "${a.description}"
74
+ inline:
75
+ model: "${a.inline.model}"
76
+ system_prompt: |
77
77
  ${indentBlock(a.inline.system_prompt, 8)}`)
78
78
  .join('\n\n');
79
- return `# CrewX Agents Configuration
80
- # Generated by 'crewx init'
81
-
82
- agents:
83
- ${agentBlocks}
84
-
85
- # Usage examples:
86
- # crewx query "@planner analyze this codebase"
87
- # crewx execute "@developer implement the feature described above"
88
- # crewx agent ls
79
+ return `# CrewX Agents Configuration
80
+ # Generated by 'crewx init'
81
+
82
+ agents:
83
+ ${agentBlocks}
84
+
85
+ # Usage examples:
86
+ # crewx query "@planner analyze this codebase"
87
+ # crewx execute "@developer implement the feature described above"
88
+ # crewx agent ls
89
89
  `;
90
90
  }
91
91
  /**
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Shared SQLite helper for ps/kill/result CLI commands.
3
+ * Reads from (or writes to) the global ~/.crewx/crewx.db
4
+ * populated by SqliteTracingPlugin.
5
+ */
6
+ import BetterSqlite3 from 'better-sqlite3';
7
+ export type TaskStatus = 'running' | 'success' | 'failed';
8
+ export interface TaskRow {
9
+ id: string;
10
+ agent_id: string;
11
+ prompt: string;
12
+ mode: string;
13
+ status: TaskStatus;
14
+ pid: number | null;
15
+ started_at: string;
16
+ completed_at: string | null;
17
+ result: string | null;
18
+ error: string | null;
19
+ duration_ms: number | null;
20
+ }
21
+ export declare function getDbPath(dbRoot?: string): string;
22
+ export declare function openDb(readonly?: boolean, dbRoot?: string): InstanceType<typeof BetterSqlite3> | null;
23
+ /** Return all tasks with status='running'. */
24
+ export declare function getRunningTasks(dbRoot?: string): TaskRow[];
25
+ /** Return all tasks ordered by started_at desc. */
26
+ export declare function getAllTasks(dbRoot?: string): TaskRow[];
27
+ /** Return a single task by id, or undefined if not found. */
28
+ export declare function getTask(id: string, dbRoot?: string): TaskRow | undefined;
29
+ /** Send SIGTERM to the task's pid and mark it failed. Returns ok/message. */
30
+ export declare function killTask(id: string, dbRoot?: string): {
31
+ ok: boolean;
32
+ message: string;
33
+ };
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ /**
3
+ * Shared SQLite helper for ps/kill/result CLI commands.
4
+ * Reads from (or writes to) the global ~/.crewx/crewx.db
5
+ * populated by SqliteTracingPlugin.
6
+ */
7
+ var __importDefault = (this && this.__importDefault) || function (mod) {
8
+ return (mod && mod.__esModule) ? mod : { "default": mod };
9
+ };
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.getDbPath = getDbPath;
12
+ exports.openDb = openDb;
13
+ exports.getRunningTasks = getRunningTasks;
14
+ exports.getAllTasks = getAllTasks;
15
+ exports.getTask = getTask;
16
+ exports.killTask = killTask;
17
+ const fs_1 = require("fs");
18
+ const path_1 = require("path");
19
+ const os_1 = require("os");
20
+ const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
21
+ function getDbPath(dbRoot) {
22
+ return (0, path_1.join)(dbRoot ?? (0, os_1.homedir)(), '.crewx', 'crewx.db');
23
+ }
24
+ function openDb(readonly = true, dbRoot) {
25
+ const dbPath = getDbPath(dbRoot);
26
+ if (!(0, fs_1.existsSync)(dbPath))
27
+ return null;
28
+ return new better_sqlite3_1.default(dbPath, { readonly });
29
+ }
30
+ /** Return all tasks with status='running'. */
31
+ function getRunningTasks(dbRoot) {
32
+ const db = openDb(true, dbRoot);
33
+ if (!db)
34
+ return [];
35
+ try {
36
+ return db.prepare(`SELECT id, agent_id, prompt, mode, status, pid, started_at, completed_at,
37
+ result, error, duration_ms
38
+ FROM tasks WHERE status = 'running' ORDER BY started_at DESC`).all();
39
+ }
40
+ finally {
41
+ db.close();
42
+ }
43
+ }
44
+ /** Return all tasks ordered by started_at desc. */
45
+ function getAllTasks(dbRoot) {
46
+ const db = openDb(true, dbRoot);
47
+ if (!db)
48
+ return [];
49
+ try {
50
+ return db.prepare(`SELECT id, agent_id, prompt, mode, status, pid, started_at, completed_at,
51
+ result, error, duration_ms
52
+ FROM tasks ORDER BY started_at DESC`).all();
53
+ }
54
+ finally {
55
+ db.close();
56
+ }
57
+ }
58
+ /** Return a single task by id, or undefined if not found. */
59
+ function getTask(id, dbRoot) {
60
+ const db = openDb(true, dbRoot);
61
+ if (!db)
62
+ return undefined;
63
+ try {
64
+ return db.prepare(`SELECT id, agent_id, prompt, mode, status, pid, started_at, completed_at,
65
+ result, error, duration_ms
66
+ FROM tasks WHERE id = ?`).get(id);
67
+ }
68
+ finally {
69
+ db.close();
70
+ }
71
+ }
72
+ /** Send SIGTERM to the task's pid and mark it failed. Returns ok/message. */
73
+ function killTask(id, dbRoot) {
74
+ const db = openDb(false, dbRoot);
75
+ if (!db)
76
+ return { ok: false, message: `crewx.db not found — no running tasks.` };
77
+ try {
78
+ const task = db.prepare(`SELECT id, status, pid FROM tasks WHERE id = ?`).get(id);
79
+ if (!task) {
80
+ return { ok: false, message: `Task not found: ${id}` };
81
+ }
82
+ if (task.status !== 'running') {
83
+ return { ok: false, message: `Task ${id} is not running (status: ${task.status})` };
84
+ }
85
+ if (task.pid) {
86
+ try {
87
+ process.kill(task.pid, 'SIGTERM');
88
+ }
89
+ catch (err) {
90
+ const code = err.code;
91
+ if (code !== 'ESRCH') {
92
+ return {
93
+ ok: false,
94
+ message: `Failed to kill PID ${task.pid}: ${err instanceof Error ? err.message : String(err)}`,
95
+ };
96
+ }
97
+ // ESRCH = process already gone — still clean up the record
98
+ }
99
+ }
100
+ db.prepare(`UPDATE tasks SET status='failed', error='killed by user',
101
+ completed_at=?, pid=NULL WHERE id=?`).run(new Date().toISOString(), id);
102
+ return { ok: true, message: `Killed task ${id}${task.pid ? ` (PID: ${task.pid})` : ''}` };
103
+ }
104
+ finally {
105
+ db.close();
106
+ }
107
+ }
@@ -0,0 +1,22 @@
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
+ }
@@ -0,0 +1,40 @@
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;
package/dist/main.js CHANGED
@@ -218,78 +218,78 @@ async function main() {
218
218
  process.exit(1);
219
219
  }
220
220
  function printHelp() {
221
- console.log(`
222
- CrewX CLI v${version_1.CLI_VERSION}
223
-
224
- Usage:
225
- crewx Launch web dashboard + open browser (default)
226
- crewx <command> [options]
227
-
228
- UI Modes:
229
- crewx Web dashboard (port 8150, random token, auto-open)
230
- crewx serve [options] Web server (explicit)
231
- --port <N> Port (default: 8150)
232
- --token <T> MCP bearer token (⚠️ use --token-file in shared shells)
233
- --token-file <PATH> Read bearer token from file
234
- --no-open Do not auto-open browser
235
- crewx electron [--overlay] Launch Electron (desktop or overlay window)
236
-
237
- Query / Execute:
238
- q|query "@agent <message>" Query an agent (quoted single string)
239
- x|execute "@agent <task>" Execute a task with an agent (quoted single string)
240
-
241
- @agent is optional — defaults to @crewx when omitted.
242
-
243
- Common flags:
244
- --thread <name> Conversation thread
245
- --provider <cli/xxx> Provider override
246
- --metadata <json> Extra metadata (JSON object, double-quoted). Propagated to events/hooks/tracing.
247
- Invalid JSON aborts with exit code 2.
248
- e.g. --metadata='{"workflow_id":"wf-1"}'
249
- --verbose Debug output mode (default: raw response only)
250
- --config/-c <path> Config file path (default: CREWX_CONFIG or crewx.yaml)
251
- --output-format <fmt> Output format (json|text|stream-json)
252
- --effort <level> Model effort (high|medium|low)
253
- -f/--prompt-file <path> Read task body from file (bypasses argv length limits)
254
- -- End of flags; remaining tokens treated as message text
255
- e.g. crewx q "@agent label" -- --flag-in-message
256
-
257
- Agent Management:
258
- agent ls [options] List configured agents
259
- --role <value> Filter by role (comma-separated for OR match)
260
- --team <value> Filter by team (comma-separated for OR match)
261
- --provider <value> Filter by provider (comma-separated for OR match)
262
- agent prompt <@id> Show rendered system prompt for an agent
263
-
264
- Task Management:
265
- ps List running tasks
266
- kill <task-id> Kill a running task
267
- kill --all Kill all running tasks
268
- result [task-id] Get task result (or list recent tasks)
269
-
270
- Logs & Diagnostics:
271
- log [ls|<task-id>] View task logs
272
- doctor [--config <path>] Run system diagnosis
273
- init [--force] [--config <p>] Initialize crewx.yaml
274
-
275
- Built-in Tools:
276
- memory <args> Memory tool
277
- search <args> Search tool
278
- doc <args> Doc tool
279
- wbs <args> WBS tool
280
- cron <args> Cron tool
281
- workflow <args> Workflow tool
282
- skill <args> Skill tool
283
-
284
- Hook Platform:
285
- hook install [--yes] Install PreToolUse hook in .claude/settings.json
286
- hook uninstall Remove crewx hook from .claude/settings.json
287
- hook status Show hook installation status and plugins
288
- hook-dispatch Internal: IPC router called by Claude (stdin→stdout)
289
-
290
- Global Options:
291
- --help, -h Show this help
292
- --version, -v Show version
221
+ console.log(`
222
+ CrewX CLI v${version_1.CLI_VERSION}
223
+
224
+ Usage:
225
+ crewx Launch web dashboard + open browser (default)
226
+ crewx <command> [options]
227
+
228
+ UI Modes:
229
+ crewx Web dashboard (port 8150, random token, auto-open)
230
+ crewx serve [options] Web server (explicit)
231
+ --port <N> Port (default: 8150)
232
+ --token <T> MCP bearer token (⚠️ use --token-file in shared shells)
233
+ --token-file <PATH> Read bearer token from file
234
+ --no-open Do not auto-open browser
235
+ crewx electron [--overlay] Launch Electron (desktop or overlay window)
236
+
237
+ Query / Execute:
238
+ q|query "@agent <message>" Query an agent (quoted single string)
239
+ x|execute "@agent <task>" Execute a task with an agent (quoted single string)
240
+
241
+ @agent is optional — defaults to @crewx when omitted.
242
+
243
+ Common flags:
244
+ --thread <name> Conversation thread
245
+ --provider <cli/xxx> Provider override
246
+ --metadata <json> Extra metadata (JSON object, double-quoted). Propagated to events/hooks/tracing.
247
+ Invalid JSON aborts with exit code 2.
248
+ e.g. --metadata='{"workflow_id":"wf-1"}'
249
+ --verbose Debug output mode (default: raw response only)
250
+ --config/-c <path> Config file path (default: CREWX_CONFIG or crewx.yaml)
251
+ --output-format <fmt> Output format (json|text|stream-json)
252
+ --effort <level> Model effort (high|medium|low)
253
+ -f/--prompt-file <path> Read task body from file (bypasses argv length limits)
254
+ -- End of flags; remaining tokens treated as message text
255
+ e.g. crewx q "@agent label" -- --flag-in-message
256
+
257
+ Agent Management:
258
+ agent ls [options] List configured agents
259
+ --role <value> Filter by role (comma-separated for OR match)
260
+ --team <value> Filter by team (comma-separated for OR match)
261
+ --provider <value> Filter by provider (comma-separated for OR match)
262
+ agent prompt <@id> Show rendered system prompt for an agent
263
+
264
+ Task Management:
265
+ ps List running tasks
266
+ kill <task-id> Kill a running task
267
+ kill --all Kill all running tasks
268
+ result [task-id] Get task result (or list recent tasks)
269
+
270
+ Logs & Diagnostics:
271
+ log [ls|<task-id>] View task logs
272
+ doctor [--config <path>] Run system diagnosis
273
+ init [--force] [--config <p>] Initialize crewx.yaml
274
+
275
+ Built-in Tools:
276
+ memory <args> Memory tool
277
+ search <args> Search tool
278
+ doc <args> Doc tool
279
+ wbs <args> WBS tool
280
+ cron <args> Cron tool
281
+ workflow <args> Workflow tool
282
+ skill <args> Skill tool
283
+
284
+ Hook Platform:
285
+ hook install [--yes] Install PreToolUse hook in .claude/settings.json
286
+ hook uninstall Remove crewx hook from .claude/settings.json
287
+ hook status Show hook installation status and plugins
288
+ hook-dispatch Internal: IPC router called by Claude (stdin→stdout)
289
+
290
+ Global Options:
291
+ --help, -h Show this help
292
+ --version, -v Show version
293
293
  `.trim());
294
294
  }
295
295
  main().catch((err) => {
@@ -0,0 +1,24 @@
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
+ }
@@ -0,0 +1,60 @@
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;
@@ -0,0 +1,8 @@
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 {};