@claude-flow/cli 3.0.0-alpha.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.
Files changed (229) hide show
  1. package/.agentic-flow/intelligence.json +16 -0
  2. package/.claude-flow/metrics/agent-metrics.json +1 -0
  3. package/.claude-flow/metrics/performance.json +87 -0
  4. package/.claude-flow/metrics/task-metrics.json +10 -0
  5. package/README.md +1186 -0
  6. package/__tests__/README.md +140 -0
  7. package/__tests__/TEST_SUMMARY.md +144 -0
  8. package/__tests__/cli.test.ts +558 -0
  9. package/__tests__/commands.test.ts +726 -0
  10. package/__tests__/config-adapter.test.ts +362 -0
  11. package/__tests__/config-loading.test.ts +106 -0
  12. package/__tests__/coverage/.tmp/coverage-0.json +1 -0
  13. package/__tests__/coverage/.tmp/coverage-1.json +1 -0
  14. package/__tests__/coverage/.tmp/coverage-2.json +1 -0
  15. package/__tests__/coverage/.tmp/coverage-3.json +1 -0
  16. package/__tests__/coverage/.tmp/coverage-4.json +1 -0
  17. package/__tests__/coverage/.tmp/coverage-5.json +1 -0
  18. package/__tests__/mcp-client.test.ts +480 -0
  19. package/__tests__/p1-commands.test.ts +1064 -0
  20. package/bin/cli.js +14 -0
  21. package/dist/src/commands/agent.d.ts +8 -0
  22. package/dist/src/commands/agent.d.ts.map +1 -0
  23. package/dist/src/commands/agent.js +803 -0
  24. package/dist/src/commands/agent.js.map +1 -0
  25. package/dist/src/commands/config.d.ts +8 -0
  26. package/dist/src/commands/config.d.ts.map +1 -0
  27. package/dist/src/commands/config.js +406 -0
  28. package/dist/src/commands/config.js.map +1 -0
  29. package/dist/src/commands/hive-mind.d.ts +8 -0
  30. package/dist/src/commands/hive-mind.d.ts.map +1 -0
  31. package/dist/src/commands/hive-mind.js +627 -0
  32. package/dist/src/commands/hive-mind.js.map +1 -0
  33. package/dist/src/commands/hooks.d.ts +8 -0
  34. package/dist/src/commands/hooks.d.ts.map +1 -0
  35. package/dist/src/commands/hooks.js +2098 -0
  36. package/dist/src/commands/hooks.js.map +1 -0
  37. package/dist/src/commands/index.d.ts +51 -0
  38. package/dist/src/commands/index.d.ts.map +1 -0
  39. package/dist/src/commands/index.js +105 -0
  40. package/dist/src/commands/index.js.map +1 -0
  41. package/dist/src/commands/init.d.ts +8 -0
  42. package/dist/src/commands/init.d.ts.map +1 -0
  43. package/dist/src/commands/init.js +532 -0
  44. package/dist/src/commands/init.js.map +1 -0
  45. package/dist/src/commands/mcp.d.ts +11 -0
  46. package/dist/src/commands/mcp.d.ts.map +1 -0
  47. package/dist/src/commands/mcp.js +662 -0
  48. package/dist/src/commands/mcp.js.map +1 -0
  49. package/dist/src/commands/memory.d.ts +8 -0
  50. package/dist/src/commands/memory.d.ts.map +1 -0
  51. package/dist/src/commands/memory.js +911 -0
  52. package/dist/src/commands/memory.js.map +1 -0
  53. package/dist/src/commands/migrate.d.ts +8 -0
  54. package/dist/src/commands/migrate.d.ts.map +1 -0
  55. package/dist/src/commands/migrate.js +398 -0
  56. package/dist/src/commands/migrate.js.map +1 -0
  57. package/dist/src/commands/process.d.ts +10 -0
  58. package/dist/src/commands/process.d.ts.map +1 -0
  59. package/dist/src/commands/process.js +566 -0
  60. package/dist/src/commands/process.js.map +1 -0
  61. package/dist/src/commands/session.d.ts +8 -0
  62. package/dist/src/commands/session.d.ts.map +1 -0
  63. package/dist/src/commands/session.js +750 -0
  64. package/dist/src/commands/session.js.map +1 -0
  65. package/dist/src/commands/start.d.ts +8 -0
  66. package/dist/src/commands/start.d.ts.map +1 -0
  67. package/dist/src/commands/start.js +398 -0
  68. package/dist/src/commands/start.js.map +1 -0
  69. package/dist/src/commands/status.d.ts +8 -0
  70. package/dist/src/commands/status.d.ts.map +1 -0
  71. package/dist/src/commands/status.js +560 -0
  72. package/dist/src/commands/status.js.map +1 -0
  73. package/dist/src/commands/swarm.d.ts +8 -0
  74. package/dist/src/commands/swarm.d.ts.map +1 -0
  75. package/dist/src/commands/swarm.js +573 -0
  76. package/dist/src/commands/swarm.js.map +1 -0
  77. package/dist/src/commands/task.d.ts +8 -0
  78. package/dist/src/commands/task.d.ts.map +1 -0
  79. package/dist/src/commands/task.js +671 -0
  80. package/dist/src/commands/task.js.map +1 -0
  81. package/dist/src/commands/workflow.d.ts +8 -0
  82. package/dist/src/commands/workflow.d.ts.map +1 -0
  83. package/dist/src/commands/workflow.js +617 -0
  84. package/dist/src/commands/workflow.js.map +1 -0
  85. package/dist/src/config-adapter.d.ts +15 -0
  86. package/dist/src/config-adapter.d.ts.map +1 -0
  87. package/dist/src/config-adapter.js +185 -0
  88. package/dist/src/config-adapter.js.map +1 -0
  89. package/dist/src/index.d.ts +55 -0
  90. package/dist/src/index.d.ts.map +1 -0
  91. package/dist/src/index.js +312 -0
  92. package/dist/src/index.js.map +1 -0
  93. package/dist/src/infrastructure/in-memory-repositories.d.ts +68 -0
  94. package/dist/src/infrastructure/in-memory-repositories.d.ts.map +1 -0
  95. package/dist/src/infrastructure/in-memory-repositories.js +264 -0
  96. package/dist/src/infrastructure/in-memory-repositories.js.map +1 -0
  97. package/dist/src/init/claudemd-generator.d.ts +15 -0
  98. package/dist/src/init/claudemd-generator.d.ts.map +1 -0
  99. package/dist/src/init/claudemd-generator.js +626 -0
  100. package/dist/src/init/claudemd-generator.js.map +1 -0
  101. package/dist/src/init/executor.d.ts +11 -0
  102. package/dist/src/init/executor.d.ts.map +1 -0
  103. package/dist/src/init/executor.js +647 -0
  104. package/dist/src/init/executor.js.map +1 -0
  105. package/dist/src/init/helpers-generator.d.ts +42 -0
  106. package/dist/src/init/helpers-generator.d.ts.map +1 -0
  107. package/dist/src/init/helpers-generator.js +613 -0
  108. package/dist/src/init/helpers-generator.js.map +1 -0
  109. package/dist/src/init/index.d.ts +12 -0
  110. package/dist/src/init/index.d.ts.map +1 -0
  111. package/dist/src/init/index.js +15 -0
  112. package/dist/src/init/index.js.map +1 -0
  113. package/dist/src/init/mcp-generator.d.ts +18 -0
  114. package/dist/src/init/mcp-generator.d.ts.map +1 -0
  115. package/dist/src/init/mcp-generator.js +71 -0
  116. package/dist/src/init/mcp-generator.js.map +1 -0
  117. package/dist/src/init/settings-generator.d.ts +14 -0
  118. package/dist/src/init/settings-generator.d.ts.map +1 -0
  119. package/dist/src/init/settings-generator.js +257 -0
  120. package/dist/src/init/settings-generator.js.map +1 -0
  121. package/dist/src/init/statusline-generator.d.ts +14 -0
  122. package/dist/src/init/statusline-generator.d.ts.map +1 -0
  123. package/dist/src/init/statusline-generator.js +206 -0
  124. package/dist/src/init/statusline-generator.js.map +1 -0
  125. package/dist/src/init/types.d.ts +240 -0
  126. package/dist/src/init/types.d.ts.map +1 -0
  127. package/dist/src/init/types.js +210 -0
  128. package/dist/src/init/types.js.map +1 -0
  129. package/dist/src/mcp-client.d.ts +92 -0
  130. package/dist/src/mcp-client.d.ts.map +1 -0
  131. package/dist/src/mcp-client.js +189 -0
  132. package/dist/src/mcp-client.js.map +1 -0
  133. package/dist/src/mcp-server.d.ts +153 -0
  134. package/dist/src/mcp-server.d.ts.map +1 -0
  135. package/dist/src/mcp-server.js +448 -0
  136. package/dist/src/mcp-server.js.map +1 -0
  137. package/dist/src/mcp-tools/agent-tools.d.ts +8 -0
  138. package/dist/src/mcp-tools/agent-tools.d.ts.map +1 -0
  139. package/dist/src/mcp-tools/agent-tools.js +90 -0
  140. package/dist/src/mcp-tools/agent-tools.js.map +1 -0
  141. package/dist/src/mcp-tools/config-tools.d.ts +8 -0
  142. package/dist/src/mcp-tools/config-tools.d.ts.map +1 -0
  143. package/dist/src/mcp-tools/config-tools.js +86 -0
  144. package/dist/src/mcp-tools/config-tools.js.map +1 -0
  145. package/dist/src/mcp-tools/hooks-tools.d.ts +41 -0
  146. package/dist/src/mcp-tools/hooks-tools.d.ts.map +1 -0
  147. package/dist/src/mcp-tools/hooks-tools.js +1646 -0
  148. package/dist/src/mcp-tools/hooks-tools.js.map +1 -0
  149. package/dist/src/mcp-tools/index.d.ts +12 -0
  150. package/dist/src/mcp-tools/index.d.ts.map +1 -0
  151. package/dist/src/mcp-tools/index.js +11 -0
  152. package/dist/src/mcp-tools/index.js.map +1 -0
  153. package/dist/src/mcp-tools/memory-tools.d.ts +8 -0
  154. package/dist/src/mcp-tools/memory-tools.d.ts.map +1 -0
  155. package/dist/src/mcp-tools/memory-tools.js +87 -0
  156. package/dist/src/mcp-tools/memory-tools.js.map +1 -0
  157. package/dist/src/mcp-tools/swarm-tools.d.ts +8 -0
  158. package/dist/src/mcp-tools/swarm-tools.d.ts.map +1 -0
  159. package/dist/src/mcp-tools/swarm-tools.js +67 -0
  160. package/dist/src/mcp-tools/swarm-tools.js.map +1 -0
  161. package/dist/src/mcp-tools/types.d.ts +31 -0
  162. package/dist/src/mcp-tools/types.d.ts.map +1 -0
  163. package/dist/src/mcp-tools/types.js +7 -0
  164. package/dist/src/mcp-tools/types.js.map +1 -0
  165. package/dist/src/output.d.ts +117 -0
  166. package/dist/src/output.d.ts.map +1 -0
  167. package/dist/src/output.js +471 -0
  168. package/dist/src/output.js.map +1 -0
  169. package/dist/src/parser.d.ts +41 -0
  170. package/dist/src/parser.d.ts.map +1 -0
  171. package/dist/src/parser.js +353 -0
  172. package/dist/src/parser.js.map +1 -0
  173. package/dist/src/prompt.d.ts +44 -0
  174. package/dist/src/prompt.d.ts.map +1 -0
  175. package/dist/src/prompt.js +501 -0
  176. package/dist/src/prompt.js.map +1 -0
  177. package/dist/src/types.d.ts +198 -0
  178. package/dist/src/types.d.ts.map +1 -0
  179. package/dist/src/types.js +38 -0
  180. package/dist/src/types.js.map +1 -0
  181. package/dist/tsconfig.tsbuildinfo +1 -0
  182. package/docs/CONFIG_LOADING.md +236 -0
  183. package/docs/IMPLEMENTATION_COMPLETE.md +421 -0
  184. package/docs/MCP_CLIENT_GUIDE.md +620 -0
  185. package/docs/REFACTORING_SUMMARY.md +247 -0
  186. package/package.json +29 -0
  187. package/src/commands/agent.ts +941 -0
  188. package/src/commands/config.ts +452 -0
  189. package/src/commands/hive-mind.ts +762 -0
  190. package/src/commands/hooks.ts +2603 -0
  191. package/src/commands/index.ts +115 -0
  192. package/src/commands/init.ts +597 -0
  193. package/src/commands/mcp.ts +753 -0
  194. package/src/commands/memory.ts +1063 -0
  195. package/src/commands/migrate.ts +447 -0
  196. package/src/commands/process.ts +617 -0
  197. package/src/commands/session.ts +891 -0
  198. package/src/commands/start.ts +457 -0
  199. package/src/commands/status.ts +705 -0
  200. package/src/commands/swarm.ts +648 -0
  201. package/src/commands/task.ts +792 -0
  202. package/src/commands/workflow.ts +742 -0
  203. package/src/config-adapter.ts +210 -0
  204. package/src/index.ts +383 -0
  205. package/src/infrastructure/in-memory-repositories.ts +310 -0
  206. package/src/init/claudemd-generator.ts +631 -0
  207. package/src/init/executor.ts +756 -0
  208. package/src/init/helpers-generator.ts +628 -0
  209. package/src/init/index.ts +60 -0
  210. package/src/init/mcp-generator.ts +83 -0
  211. package/src/init/settings-generator.ts +274 -0
  212. package/src/init/statusline-generator.ts +211 -0
  213. package/src/init/types.ts +447 -0
  214. package/src/mcp-client.ts +227 -0
  215. package/src/mcp-server.ts +571 -0
  216. package/src/mcp-tools/agent-tools.ts +92 -0
  217. package/src/mcp-tools/config-tools.ts +88 -0
  218. package/src/mcp-tools/hooks-tools.ts +1819 -0
  219. package/src/mcp-tools/index.ts +12 -0
  220. package/src/mcp-tools/memory-tools.ts +89 -0
  221. package/src/mcp-tools/swarm-tools.ts +69 -0
  222. package/src/mcp-tools/types.ts +33 -0
  223. package/src/output.ts +593 -0
  224. package/src/parser.ts +417 -0
  225. package/src/prompt.ts +619 -0
  226. package/src/types.ts +287 -0
  227. package/tsconfig.json +16 -0
  228. package/tsconfig.tsbuildinfo +1 -0
  229. package/vitest.config.ts +13 -0
@@ -0,0 +1,792 @@
1
+ /**
2
+ * V3 CLI Task Command
3
+ * Task management for Claude Flow
4
+ */
5
+
6
+ import type { Command, CommandContext, CommandResult } from '../types.js';
7
+ import { output } from '../output.js';
8
+ import { select, confirm, input, multiSelect } from '../prompt.js';
9
+ import { callMCPTool, MCPClientError } from '../mcp-client.js';
10
+
11
+ // Task types
12
+ const TASK_TYPES = [
13
+ { value: 'implementation', label: 'Implementation', hint: 'Feature implementation' },
14
+ { value: 'bug-fix', label: 'Bug Fix', hint: 'Fix a bug or issue' },
15
+ { value: 'refactoring', label: 'Refactoring', hint: 'Code refactoring' },
16
+ { value: 'testing', label: 'Testing', hint: 'Write or update tests' },
17
+ { value: 'documentation', label: 'Documentation', hint: 'Documentation updates' },
18
+ { value: 'research', label: 'Research', hint: 'Research and analysis' },
19
+ { value: 'review', label: 'Review', hint: 'Code review' },
20
+ { value: 'optimization', label: 'Optimization', hint: 'Performance optimization' },
21
+ { value: 'security', label: 'Security', hint: 'Security audit or fix' },
22
+ { value: 'custom', label: 'Custom', hint: 'Custom task type' }
23
+ ];
24
+
25
+ // Task priorities
26
+ const TASK_PRIORITIES = [
27
+ { value: 'critical', label: 'Critical', hint: 'Highest priority' },
28
+ { value: 'high', label: 'High', hint: 'Important task' },
29
+ { value: 'normal', label: 'Normal', hint: 'Standard priority' },
30
+ { value: 'low', label: 'Low', hint: 'Lower priority' }
31
+ ];
32
+
33
+ // Format task status with color
34
+ function formatStatus(status: string): string {
35
+ switch (status) {
36
+ case 'completed':
37
+ return output.success(status);
38
+ case 'running':
39
+ case 'in_progress':
40
+ return output.info(status);
41
+ case 'pending':
42
+ case 'queued':
43
+ return output.warning(status);
44
+ case 'failed':
45
+ case 'cancelled':
46
+ return output.error(status);
47
+ default:
48
+ return status;
49
+ }
50
+ }
51
+
52
+ // Format priority with color
53
+ function formatPriority(priority: string): string {
54
+ switch (priority) {
55
+ case 'critical':
56
+ return output.error(priority);
57
+ case 'high':
58
+ return output.warning(priority);
59
+ case 'normal':
60
+ return priority;
61
+ case 'low':
62
+ return output.dim(priority);
63
+ default:
64
+ return priority;
65
+ }
66
+ }
67
+
68
+ // Create subcommand
69
+ const createCommand: Command = {
70
+ name: 'create',
71
+ aliases: ['new', 'add'],
72
+ description: 'Create a new task',
73
+ options: [
74
+ {
75
+ name: 'type',
76
+ short: 't',
77
+ description: 'Task type',
78
+ type: 'string',
79
+ choices: TASK_TYPES.map(t => t.value)
80
+ },
81
+ {
82
+ name: 'description',
83
+ short: 'd',
84
+ description: 'Task description',
85
+ type: 'string'
86
+ },
87
+ {
88
+ name: 'priority',
89
+ short: 'p',
90
+ description: 'Task priority',
91
+ type: 'string',
92
+ choices: TASK_PRIORITIES.map(p => p.value),
93
+ default: 'normal'
94
+ },
95
+ {
96
+ name: 'assign',
97
+ short: 'a',
98
+ description: 'Assign to agent(s)',
99
+ type: 'string'
100
+ },
101
+ {
102
+ name: 'tags',
103
+ description: 'Comma-separated tags',
104
+ type: 'string'
105
+ },
106
+ {
107
+ name: 'parent',
108
+ description: 'Parent task ID',
109
+ type: 'string'
110
+ },
111
+ {
112
+ name: 'dependencies',
113
+ description: 'Comma-separated task IDs that must complete first',
114
+ type: 'string'
115
+ },
116
+ {
117
+ name: 'timeout',
118
+ description: 'Task timeout in seconds',
119
+ type: 'number',
120
+ default: 300
121
+ }
122
+ ],
123
+ action: async (ctx: CommandContext): Promise<CommandResult> => {
124
+ let taskType = ctx.flags.type as string;
125
+ let description = ctx.flags.description as string;
126
+ let priority = ctx.flags.priority as string;
127
+
128
+ // Interactive mode
129
+ if (!taskType && ctx.interactive) {
130
+ taskType = await select({
131
+ message: 'Select task type:',
132
+ options: TASK_TYPES
133
+ });
134
+ }
135
+
136
+ if (!description && ctx.interactive) {
137
+ description = await input({
138
+ message: 'Task description:',
139
+ validate: (v) => v.length > 0 || 'Description is required'
140
+ });
141
+ }
142
+
143
+ if (!taskType || !description) {
144
+ output.printError('Task type and description are required');
145
+ output.printInfo('Use --type and --description flags, or run in interactive mode');
146
+ return { success: false, exitCode: 1 };
147
+ }
148
+
149
+ if (!priority && ctx.interactive) {
150
+ priority = await select({
151
+ message: 'Select priority:',
152
+ options: TASK_PRIORITIES,
153
+ default: 'normal'
154
+ });
155
+ }
156
+
157
+ // Parse tags and dependencies
158
+ const tags = ctx.flags.tags ? (ctx.flags.tags as string).split(',').map(t => t.trim()) : [];
159
+ const dependencies = ctx.flags.dependencies
160
+ ? (ctx.flags.dependencies as string).split(',').map(d => d.trim())
161
+ : [];
162
+
163
+ output.writeln();
164
+ output.printInfo(`Creating ${taskType} task...`);
165
+
166
+ try {
167
+ const result = await callMCPTool<{
168
+ taskId: string;
169
+ type: string;
170
+ description: string;
171
+ priority: string;
172
+ status: string;
173
+ createdAt: string;
174
+ assignedTo?: string[];
175
+ tags: string[];
176
+ }>('task/create', {
177
+ type: taskType,
178
+ description,
179
+ priority: priority || 'normal',
180
+ assignedTo: ctx.flags.assign ? [ctx.flags.assign] : undefined,
181
+ parentId: ctx.flags.parent,
182
+ dependencies,
183
+ tags,
184
+ timeout: ctx.flags.timeout,
185
+ metadata: {
186
+ source: 'cli',
187
+ createdBy: 'user'
188
+ }
189
+ });
190
+
191
+ output.writeln();
192
+ output.printSuccess(`Task created: ${result.taskId}`);
193
+ output.writeln();
194
+
195
+ output.printTable({
196
+ columns: [
197
+ { key: 'property', header: 'Property', width: 15 },
198
+ { key: 'value', header: 'Value', width: 40 }
199
+ ],
200
+ data: [
201
+ { property: 'ID', value: result.taskId },
202
+ { property: 'Type', value: result.type },
203
+ { property: 'Description', value: result.description },
204
+ { property: 'Priority', value: formatPriority(result.priority) },
205
+ { property: 'Status', value: formatStatus(result.status) },
206
+ { property: 'Assigned To', value: result.assignedTo?.join(', ') || 'Unassigned' },
207
+ { property: 'Tags', value: result.tags.join(', ') || 'None' },
208
+ { property: 'Created', value: new Date(result.createdAt).toLocaleString() }
209
+ ]
210
+ });
211
+
212
+ if (ctx.flags.format === 'json') {
213
+ output.printJson(result);
214
+ }
215
+
216
+ return { success: true, data: result };
217
+ } catch (error) {
218
+ if (error instanceof MCPClientError) {
219
+ output.printError(`Failed to create task: ${error.message}`);
220
+ } else {
221
+ output.printError(`Unexpected error: ${String(error)}`);
222
+ }
223
+ return { success: false, exitCode: 1 };
224
+ }
225
+ }
226
+ };
227
+
228
+ // List subcommand
229
+ const listCommand: Command = {
230
+ name: 'list',
231
+ aliases: ['ls'],
232
+ description: 'List tasks',
233
+ options: [
234
+ {
235
+ name: 'status',
236
+ short: 's',
237
+ description: 'Filter by status',
238
+ type: 'string',
239
+ choices: ['pending', 'running', 'completed', 'failed', 'cancelled', 'all']
240
+ },
241
+ {
242
+ name: 'type',
243
+ short: 't',
244
+ description: 'Filter by task type',
245
+ type: 'string'
246
+ },
247
+ {
248
+ name: 'priority',
249
+ short: 'p',
250
+ description: 'Filter by priority',
251
+ type: 'string'
252
+ },
253
+ {
254
+ name: 'agent',
255
+ short: 'a',
256
+ description: 'Filter by assigned agent',
257
+ type: 'string'
258
+ },
259
+ {
260
+ name: 'limit',
261
+ short: 'l',
262
+ description: 'Maximum number of tasks to show',
263
+ type: 'number',
264
+ default: 20
265
+ },
266
+ {
267
+ name: 'all',
268
+ description: 'Show all tasks including completed',
269
+ type: 'boolean',
270
+ default: false
271
+ }
272
+ ],
273
+ action: async (ctx: CommandContext): Promise<CommandResult> => {
274
+ const status = ctx.flags.all ? 'all' : (ctx.flags.status as string) || 'pending,running';
275
+ const limit = ctx.flags.limit as number;
276
+
277
+ try {
278
+ const result = await callMCPTool<{
279
+ tasks: Array<{
280
+ id: string;
281
+ type: string;
282
+ description: string;
283
+ priority: string;
284
+ status: string;
285
+ assignedTo?: string[];
286
+ progress: number;
287
+ createdAt: string;
288
+ }>;
289
+ total: number;
290
+ }>('task/list', {
291
+ status,
292
+ type: ctx.flags.type,
293
+ priority: ctx.flags.priority,
294
+ agentId: ctx.flags.agent,
295
+ limit,
296
+ offset: 0
297
+ });
298
+
299
+ if (ctx.flags.format === 'json') {
300
+ output.printJson(result);
301
+ return { success: true, data: result };
302
+ }
303
+
304
+ output.writeln();
305
+ output.writeln(output.bold('Tasks'));
306
+ output.writeln();
307
+
308
+ if (result.tasks.length === 0) {
309
+ output.printInfo('No tasks found matching criteria');
310
+ return { success: true, data: result };
311
+ }
312
+
313
+ output.printTable({
314
+ columns: [
315
+ { key: 'id', header: 'ID', width: 15 },
316
+ { key: 'type', header: 'Type', width: 15 },
317
+ { key: 'description', header: 'Description', width: 30 },
318
+ { key: 'priority', header: 'Priority', width: 10 },
319
+ { key: 'status', header: 'Status', width: 12 },
320
+ { key: 'progress', header: 'Progress', width: 10 }
321
+ ],
322
+ data: result.tasks.map(t => ({
323
+ id: t.id,
324
+ type: t.type,
325
+ description: t.description.length > 27
326
+ ? t.description.slice(0, 27) + '...'
327
+ : t.description,
328
+ priority: formatPriority(t.priority),
329
+ status: formatStatus(t.status),
330
+ progress: `${t.progress}%`
331
+ }))
332
+ });
333
+
334
+ output.writeln();
335
+ output.printInfo(`Showing ${result.tasks.length} of ${result.total} tasks`);
336
+
337
+ return { success: true, data: result };
338
+ } catch (error) {
339
+ if (error instanceof MCPClientError) {
340
+ output.printError(`Failed to list tasks: ${error.message}`);
341
+ } else {
342
+ output.printError(`Unexpected error: ${String(error)}`);
343
+ }
344
+ return { success: false, exitCode: 1 };
345
+ }
346
+ }
347
+ };
348
+
349
+ // Status subcommand (get task details)
350
+ const statusCommand: Command = {
351
+ name: 'status',
352
+ aliases: ['info', 'get'],
353
+ description: 'Get task status and details',
354
+ options: [
355
+ {
356
+ name: 'id',
357
+ description: 'Task ID',
358
+ type: 'string'
359
+ },
360
+ {
361
+ name: 'logs',
362
+ description: 'Include execution logs',
363
+ type: 'boolean',
364
+ default: false
365
+ }
366
+ ],
367
+ action: async (ctx: CommandContext): Promise<CommandResult> => {
368
+ let taskId = ctx.args[0] || ctx.flags.id as string;
369
+
370
+ if (!taskId && ctx.interactive) {
371
+ taskId = await input({
372
+ message: 'Enter task ID:',
373
+ validate: (v) => v.length > 0 || 'Task ID is required'
374
+ });
375
+ }
376
+
377
+ if (!taskId) {
378
+ output.printError('Task ID is required');
379
+ return { success: false, exitCode: 1 };
380
+ }
381
+
382
+ try {
383
+ const result = await callMCPTool<{
384
+ id: string;
385
+ type: string;
386
+ description: string;
387
+ priority: string;
388
+ status: string;
389
+ progress: number;
390
+ assignedTo?: string[];
391
+ parentId?: string;
392
+ dependencies: string[];
393
+ dependents: string[];
394
+ tags: string[];
395
+ createdAt: string;
396
+ startedAt?: string;
397
+ completedAt?: string;
398
+ result?: unknown;
399
+ error?: string;
400
+ logs?: Array<{ timestamp: string; level: string; message: string }>;
401
+ metrics?: {
402
+ executionTime: number;
403
+ retries: number;
404
+ tokensUsed: number;
405
+ };
406
+ }>('task/status', {
407
+ taskId,
408
+ includeLogs: ctx.flags.logs,
409
+ includeMetrics: true
410
+ });
411
+
412
+ if (ctx.flags.format === 'json') {
413
+ output.printJson(result);
414
+ return { success: true, data: result };
415
+ }
416
+
417
+ output.writeln();
418
+ output.printBox(
419
+ [
420
+ `Type: ${result.type}`,
421
+ `Status: ${formatStatus(result.status)}`,
422
+ `Priority: ${formatPriority(result.priority)}`,
423
+ `Progress: ${result.progress}%`,
424
+ '',
425
+ `Description: ${result.description}`
426
+ ].join('\n'),
427
+ `Task: ${result.id}`
428
+ );
429
+
430
+ // Assignment info
431
+ output.writeln();
432
+ output.writeln(output.bold('Assignment'));
433
+ output.printTable({
434
+ columns: [
435
+ { key: 'property', header: 'Property', width: 15 },
436
+ { key: 'value', header: 'Value', width: 40 }
437
+ ],
438
+ data: [
439
+ { property: 'Assigned To', value: result.assignedTo?.join(', ') || 'Unassigned' },
440
+ { property: 'Parent Task', value: result.parentId || 'None' },
441
+ { property: 'Dependencies', value: result.dependencies.join(', ') || 'None' },
442
+ { property: 'Dependents', value: result.dependents.join(', ') || 'None' },
443
+ { property: 'Tags', value: result.tags.join(', ') || 'None' }
444
+ ]
445
+ });
446
+
447
+ // Timeline
448
+ output.writeln();
449
+ output.writeln(output.bold('Timeline'));
450
+ output.printTable({
451
+ columns: [
452
+ { key: 'event', header: 'Event', width: 15 },
453
+ { key: 'time', header: 'Time', width: 30 }
454
+ ],
455
+ data: [
456
+ { event: 'Created', time: new Date(result.createdAt).toLocaleString() },
457
+ { event: 'Started', time: result.startedAt ? new Date(result.startedAt).toLocaleString() : '-' },
458
+ { event: 'Completed', time: result.completedAt ? new Date(result.completedAt).toLocaleString() : '-' }
459
+ ]
460
+ });
461
+
462
+ // Metrics
463
+ if (result.metrics) {
464
+ output.writeln();
465
+ output.writeln(output.bold('Metrics'));
466
+ output.printTable({
467
+ columns: [
468
+ { key: 'metric', header: 'Metric', width: 20 },
469
+ { key: 'value', header: 'Value', width: 20, align: 'right' }
470
+ ],
471
+ data: [
472
+ { metric: 'Execution Time', value: `${(result.metrics.executionTime / 1000).toFixed(2)}s` },
473
+ { metric: 'Retries', value: result.metrics.retries },
474
+ { metric: 'Tokens Used', value: result.metrics.tokensUsed.toLocaleString() }
475
+ ]
476
+ });
477
+ }
478
+
479
+ // Error if failed
480
+ if (result.status === 'failed' && result.error) {
481
+ output.writeln();
482
+ output.printError(`Error: ${result.error}`);
483
+ }
484
+
485
+ // Logs if requested
486
+ if (ctx.flags.logs && result.logs && result.logs.length > 0) {
487
+ output.writeln();
488
+ output.writeln(output.bold('Execution Logs'));
489
+ for (const log of result.logs.slice(-20)) {
490
+ const time = new Date(log.timestamp).toLocaleTimeString();
491
+ const level = log.level === 'error' ? output.error(`[${log.level}]`) :
492
+ log.level === 'warn' ? output.warning(`[${log.level}]`) :
493
+ output.dim(`[${log.level}]`);
494
+ output.writeln(` ${output.dim(time)} ${level} ${log.message}`);
495
+ }
496
+ }
497
+
498
+ return { success: true, data: result };
499
+ } catch (error) {
500
+ if (error instanceof MCPClientError) {
501
+ output.printError(`Failed to get task status: ${error.message}`);
502
+ } else {
503
+ output.printError(`Unexpected error: ${String(error)}`);
504
+ }
505
+ return { success: false, exitCode: 1 };
506
+ }
507
+ }
508
+ };
509
+
510
+ // Cancel subcommand
511
+ const cancelCommand: Command = {
512
+ name: 'cancel',
513
+ aliases: ['abort', 'stop'],
514
+ description: 'Cancel a running task',
515
+ options: [
516
+ {
517
+ name: 'force',
518
+ short: 'f',
519
+ description: 'Force cancel without confirmation',
520
+ type: 'boolean',
521
+ default: false
522
+ },
523
+ {
524
+ name: 'reason',
525
+ short: 'r',
526
+ description: 'Cancellation reason',
527
+ type: 'string'
528
+ }
529
+ ],
530
+ action: async (ctx: CommandContext): Promise<CommandResult> => {
531
+ const taskId = ctx.args[0];
532
+ const force = ctx.flags.force as boolean;
533
+ const reason = ctx.flags.reason as string;
534
+
535
+ if (!taskId) {
536
+ output.printError('Task ID is required');
537
+ return { success: false, exitCode: 1 };
538
+ }
539
+
540
+ if (!force && ctx.interactive) {
541
+ const confirmed = await confirm({
542
+ message: `Are you sure you want to cancel task ${taskId}?`,
543
+ default: false
544
+ });
545
+
546
+ if (!confirmed) {
547
+ output.printInfo('Operation cancelled');
548
+ return { success: true };
549
+ }
550
+ }
551
+
552
+ try {
553
+ const result = await callMCPTool<{
554
+ taskId: string;
555
+ cancelled: boolean;
556
+ previousStatus: string;
557
+ cancelledAt: string;
558
+ }>('task/cancel', {
559
+ taskId,
560
+ reason: reason || 'Cancelled by user via CLI'
561
+ });
562
+
563
+ output.writeln();
564
+ output.printSuccess(`Task ${taskId} cancelled`);
565
+ output.printInfo(`Previous status: ${result.previousStatus}`);
566
+
567
+ if (ctx.flags.format === 'json') {
568
+ output.printJson(result);
569
+ }
570
+
571
+ return { success: true, data: result };
572
+ } catch (error) {
573
+ if (error instanceof MCPClientError) {
574
+ output.printError(`Failed to cancel task: ${error.message}`);
575
+ } else {
576
+ output.printError(`Unexpected error: ${String(error)}`);
577
+ }
578
+ return { success: false, exitCode: 1 };
579
+ }
580
+ }
581
+ };
582
+
583
+ // Assign subcommand
584
+ const assignCommand: Command = {
585
+ name: 'assign',
586
+ description: 'Assign a task to agent(s)',
587
+ options: [
588
+ {
589
+ name: 'agent',
590
+ short: 'a',
591
+ description: 'Agent ID(s) to assign (comma-separated)',
592
+ type: 'string'
593
+ },
594
+ {
595
+ name: 'unassign',
596
+ description: 'Remove current assignment',
597
+ type: 'boolean',
598
+ default: false
599
+ }
600
+ ],
601
+ action: async (ctx: CommandContext): Promise<CommandResult> => {
602
+ const taskId = ctx.args[0];
603
+ const agentIds = ctx.flags.agent as string;
604
+ const unassign = ctx.flags.unassign as boolean;
605
+
606
+ if (!taskId) {
607
+ output.printError('Task ID is required');
608
+ return { success: false, exitCode: 1 };
609
+ }
610
+
611
+ if (!agentIds && !unassign) {
612
+ // Interactive agent selection
613
+ if (ctx.interactive) {
614
+ try {
615
+ const agents = await callMCPTool<{
616
+ agents: Array<{ id: string; type: string; status: string }>;
617
+ }>('agent/list', { status: 'active,idle' });
618
+
619
+ if (agents.agents.length === 0) {
620
+ output.printWarning('No available agents');
621
+ return { success: false, exitCode: 1 };
622
+ }
623
+
624
+ const selectedAgents = await multiSelect({
625
+ message: 'Select agent(s) to assign:',
626
+ options: agents.agents.map(a => ({
627
+ value: a.id,
628
+ label: a.id,
629
+ hint: `${a.type} - ${a.status}`
630
+ })),
631
+ required: true
632
+ });
633
+
634
+ if (selectedAgents.length === 0) {
635
+ output.printInfo('No agents selected');
636
+ return { success: true };
637
+ }
638
+
639
+ // Continue with assignment
640
+ const result = await callMCPTool<{
641
+ taskId: string;
642
+ assignedTo: string[];
643
+ previouslyAssigned: string[];
644
+ }>('task/assign', {
645
+ taskId,
646
+ agentIds: selectedAgents
647
+ });
648
+
649
+ output.writeln();
650
+ output.printSuccess(`Task ${taskId} assigned to ${result.assignedTo.join(', ')}`);
651
+
652
+ return { success: true, data: result };
653
+ } catch (error) {
654
+ if (error instanceof Error && error.message === 'User cancelled') {
655
+ output.printInfo('Operation cancelled');
656
+ return { success: true };
657
+ }
658
+ throw error;
659
+ }
660
+ }
661
+
662
+ output.printError('Agent ID is required. Use --agent flag or run in interactive mode');
663
+ return { success: false, exitCode: 1 };
664
+ }
665
+
666
+ try {
667
+ const result = await callMCPTool<{
668
+ taskId: string;
669
+ assignedTo: string[];
670
+ previouslyAssigned: string[];
671
+ }>('task/assign', {
672
+ taskId,
673
+ agentIds: unassign ? [] : agentIds.split(',').map(id => id.trim()),
674
+ unassign
675
+ });
676
+
677
+ output.writeln();
678
+ if (unassign) {
679
+ output.printSuccess(`Task ${taskId} unassigned`);
680
+ } else {
681
+ output.printSuccess(`Task ${taskId} assigned to ${result.assignedTo.join(', ')}`);
682
+ }
683
+
684
+ if (ctx.flags.format === 'json') {
685
+ output.printJson(result);
686
+ }
687
+
688
+ return { success: true, data: result };
689
+ } catch (error) {
690
+ if (error instanceof MCPClientError) {
691
+ output.printError(`Failed to assign task: ${error.message}`);
692
+ } else {
693
+ output.printError(`Unexpected error: ${String(error)}`);
694
+ }
695
+ return { success: false, exitCode: 1 };
696
+ }
697
+ }
698
+ };
699
+
700
+ // Retry subcommand
701
+ const retryCommand: Command = {
702
+ name: 'retry',
703
+ aliases: ['rerun'],
704
+ description: 'Retry a failed task',
705
+ options: [
706
+ {
707
+ name: 'reset-state',
708
+ description: 'Reset task state completely',
709
+ type: 'boolean',
710
+ default: false
711
+ }
712
+ ],
713
+ action: async (ctx: CommandContext): Promise<CommandResult> => {
714
+ const taskId = ctx.args[0];
715
+ const resetState = ctx.flags['reset-state'] as boolean;
716
+
717
+ if (!taskId) {
718
+ output.printError('Task ID is required');
719
+ return { success: false, exitCode: 1 };
720
+ }
721
+
722
+ try {
723
+ const result = await callMCPTool<{
724
+ taskId: string;
725
+ newTaskId: string;
726
+ previousStatus: string;
727
+ status: string;
728
+ }>('task/retry', {
729
+ taskId,
730
+ resetState
731
+ });
732
+
733
+ output.writeln();
734
+ output.printSuccess(`Task ${taskId} retried`);
735
+ output.printInfo(`New task ID: ${result.newTaskId}`);
736
+ output.printInfo(`Status: ${formatStatus(result.status)}`);
737
+
738
+ if (ctx.flags.format === 'json') {
739
+ output.printJson(result);
740
+ }
741
+
742
+ return { success: true, data: result };
743
+ } catch (error) {
744
+ if (error instanceof MCPClientError) {
745
+ output.printError(`Failed to retry task: ${error.message}`);
746
+ } else {
747
+ output.printError(`Unexpected error: ${String(error)}`);
748
+ }
749
+ return { success: false, exitCode: 1 };
750
+ }
751
+ }
752
+ };
753
+
754
+ // Main task command
755
+ export const taskCommand: Command = {
756
+ name: 'task',
757
+ description: 'Task management commands',
758
+ subcommands: [createCommand, listCommand, statusCommand, cancelCommand, assignCommand, retryCommand],
759
+ options: [],
760
+ examples: [
761
+ { command: 'claude-flow task create -t implementation -d "Add user auth"', description: 'Create a task' },
762
+ { command: 'claude-flow task list', description: 'List pending/running tasks' },
763
+ { command: 'claude-flow task list --all', description: 'List all tasks' },
764
+ { command: 'claude-flow task status task-123', description: 'Get task details' },
765
+ { command: 'claude-flow task cancel task-123', description: 'Cancel a task' },
766
+ { command: 'claude-flow task assign task-123 --agent coder-1', description: 'Assign task to agent' },
767
+ { command: 'claude-flow task retry task-123', description: 'Retry a failed task' }
768
+ ],
769
+ action: async (ctx: CommandContext): Promise<CommandResult> => {
770
+ // Show help if no subcommand
771
+ output.writeln();
772
+ output.writeln(output.bold('Task Management Commands'));
773
+ output.writeln();
774
+ output.writeln('Usage: claude-flow task <subcommand> [options]');
775
+ output.writeln();
776
+ output.writeln('Subcommands:');
777
+ output.printList([
778
+ `${output.highlight('create')} - Create a new task`,
779
+ `${output.highlight('list')} - List tasks`,
780
+ `${output.highlight('status')} - Get task details`,
781
+ `${output.highlight('cancel')} - Cancel a running task`,
782
+ `${output.highlight('assign')} - Assign task to agent(s)`,
783
+ `${output.highlight('retry')} - Retry a failed task`
784
+ ]);
785
+ output.writeln();
786
+ output.writeln('Run "claude-flow task <subcommand> --help" for subcommand help');
787
+
788
+ return { success: true };
789
+ }
790
+ };
791
+
792
+ export default taskCommand;