gencode-ai 0.1.0

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 (274) hide show
  1. package/.env.example +11 -0
  2. package/CLAUDE.md +70 -0
  3. package/LICENSE +21 -0
  4. package/README.md +117 -0
  5. package/dist/agent/agent.d.ts +84 -0
  6. package/dist/agent/agent.d.ts.map +1 -0
  7. package/dist/agent/agent.js +233 -0
  8. package/dist/agent/agent.js.map +1 -0
  9. package/dist/agent/index.d.ts +6 -0
  10. package/dist/agent/index.d.ts.map +1 -0
  11. package/dist/agent/index.js +6 -0
  12. package/dist/agent/index.js.map +1 -0
  13. package/dist/agent/types.d.ts +47 -0
  14. package/dist/agent/types.d.ts.map +1 -0
  15. package/dist/agent/types.js +5 -0
  16. package/dist/agent/types.js.map +1 -0
  17. package/dist/cli/components/App.d.ts +14 -0
  18. package/dist/cli/components/App.d.ts.map +1 -0
  19. package/dist/cli/components/App.js +395 -0
  20. package/dist/cli/components/App.js.map +1 -0
  21. package/dist/cli/components/CommandSuggestions.d.ts +13 -0
  22. package/dist/cli/components/CommandSuggestions.d.ts.map +1 -0
  23. package/dist/cli/components/CommandSuggestions.js +32 -0
  24. package/dist/cli/components/CommandSuggestions.js.map +1 -0
  25. package/dist/cli/components/Header.d.ts +9 -0
  26. package/dist/cli/components/Header.d.ts.map +1 -0
  27. package/dist/cli/components/Header.js +13 -0
  28. package/dist/cli/components/Header.js.map +1 -0
  29. package/dist/cli/components/Input.d.ts +13 -0
  30. package/dist/cli/components/Input.d.ts.map +1 -0
  31. package/dist/cli/components/Input.js +27 -0
  32. package/dist/cli/components/Input.js.map +1 -0
  33. package/dist/cli/components/Logo.d.ts +2 -0
  34. package/dist/cli/components/Logo.d.ts.map +1 -0
  35. package/dist/cli/components/Logo.js +8 -0
  36. package/dist/cli/components/Logo.js.map +1 -0
  37. package/dist/cli/components/Messages.d.ts +37 -0
  38. package/dist/cli/components/Messages.d.ts.map +1 -0
  39. package/dist/cli/components/Messages.js +106 -0
  40. package/dist/cli/components/Messages.js.map +1 -0
  41. package/dist/cli/components/ModelSelector.d.ts +13 -0
  42. package/dist/cli/components/ModelSelector.d.ts.map +1 -0
  43. package/dist/cli/components/ModelSelector.js +72 -0
  44. package/dist/cli/components/ModelSelector.js.map +1 -0
  45. package/dist/cli/components/Spinner.d.ts +12 -0
  46. package/dist/cli/components/Spinner.d.ts.map +1 -0
  47. package/dist/cli/components/Spinner.js +45 -0
  48. package/dist/cli/components/Spinner.js.map +1 -0
  49. package/dist/cli/components/index.d.ts +12 -0
  50. package/dist/cli/components/index.d.ts.map +1 -0
  51. package/dist/cli/components/index.js +12 -0
  52. package/dist/cli/components/index.js.map +1 -0
  53. package/dist/cli/components/theme.d.ts +31 -0
  54. package/dist/cli/components/theme.d.ts.map +1 -0
  55. package/dist/cli/components/theme.js +36 -0
  56. package/dist/cli/components/theme.js.map +1 -0
  57. package/dist/cli/index-legacy.d.ts +7 -0
  58. package/dist/cli/index-legacy.d.ts.map +1 -0
  59. package/dist/cli/index-legacy.js +431 -0
  60. package/dist/cli/index-legacy.js.map +1 -0
  61. package/dist/cli/index.d.ts +7 -0
  62. package/dist/cli/index.d.ts.map +1 -0
  63. package/dist/cli/index.js +116 -0
  64. package/dist/cli/index.js.map +1 -0
  65. package/dist/cli/ink-cli.d.ts +7 -0
  66. package/dist/cli/ink-cli.d.ts.map +1 -0
  67. package/dist/cli/ink-cli.js +105 -0
  68. package/dist/cli/ink-cli.js.map +1 -0
  69. package/dist/cli/session-picker.d.ts +16 -0
  70. package/dist/cli/session-picker.d.ts.map +1 -0
  71. package/dist/cli/session-picker.js +280 -0
  72. package/dist/cli/session-picker.js.map +1 -0
  73. package/dist/cli/ui.d.ts +61 -0
  74. package/dist/cli/ui.d.ts.map +1 -0
  75. package/dist/cli/ui.js +364 -0
  76. package/dist/cli/ui.js.map +1 -0
  77. package/dist/config/index.d.ts +7 -0
  78. package/dist/config/index.d.ts.map +1 -0
  79. package/dist/config/index.js +6 -0
  80. package/dist/config/index.js.map +1 -0
  81. package/dist/config/manager.d.ts +31 -0
  82. package/dist/config/manager.d.ts.map +1 -0
  83. package/dist/config/manager.js +65 -0
  84. package/dist/config/manager.js.map +1 -0
  85. package/dist/config/types.d.ts +22 -0
  86. package/dist/config/types.d.ts.map +1 -0
  87. package/dist/config/types.js +6 -0
  88. package/dist/config/types.js.map +1 -0
  89. package/dist/index.d.ts +12 -0
  90. package/dist/index.d.ts.map +1 -0
  91. package/dist/index.js +21 -0
  92. package/dist/index.js.map +1 -0
  93. package/dist/memory/index.d.ts +10 -0
  94. package/dist/memory/index.d.ts.map +1 -0
  95. package/dist/memory/index.js +9 -0
  96. package/dist/memory/index.js.map +1 -0
  97. package/dist/memory/init.d.ts +20 -0
  98. package/dist/memory/init.d.ts.map +1 -0
  99. package/dist/memory/init.js +332 -0
  100. package/dist/memory/init.js.map +1 -0
  101. package/dist/memory/manager.d.ts +85 -0
  102. package/dist/memory/manager.d.ts.map +1 -0
  103. package/dist/memory/manager.js +234 -0
  104. package/dist/memory/manager.js.map +1 -0
  105. package/dist/memory/types.d.ts +74 -0
  106. package/dist/memory/types.d.ts.map +1 -0
  107. package/dist/memory/types.js +6 -0
  108. package/dist/memory/types.js.map +1 -0
  109. package/dist/permissions/index.d.ts +7 -0
  110. package/dist/permissions/index.d.ts.map +1 -0
  111. package/dist/permissions/index.js +6 -0
  112. package/dist/permissions/index.js.map +1 -0
  113. package/dist/permissions/manager.d.ts +32 -0
  114. package/dist/permissions/manager.d.ts.map +1 -0
  115. package/dist/permissions/manager.js +79 -0
  116. package/dist/permissions/manager.js.map +1 -0
  117. package/dist/permissions/types.d.ts +14 -0
  118. package/dist/permissions/types.d.ts.map +1 -0
  119. package/dist/permissions/types.js +17 -0
  120. package/dist/permissions/types.js.map +1 -0
  121. package/dist/providers/anthropic.d.ts +20 -0
  122. package/dist/providers/anthropic.d.ts.map +1 -0
  123. package/dist/providers/anthropic.js +185 -0
  124. package/dist/providers/anthropic.js.map +1 -0
  125. package/dist/providers/gemini.d.ts +21 -0
  126. package/dist/providers/gemini.d.ts.map +1 -0
  127. package/dist/providers/gemini.js +241 -0
  128. package/dist/providers/gemini.js.map +1 -0
  129. package/dist/providers/index.d.ts +34 -0
  130. package/dist/providers/index.d.ts.map +1 -0
  131. package/dist/providers/index.js +72 -0
  132. package/dist/providers/index.js.map +1 -0
  133. package/dist/providers/openai.d.ts +19 -0
  134. package/dist/providers/openai.d.ts.map +1 -0
  135. package/dist/providers/openai.js +221 -0
  136. package/dist/providers/openai.js.map +1 -0
  137. package/dist/providers/types.d.ts +125 -0
  138. package/dist/providers/types.d.ts.map +1 -0
  139. package/dist/providers/types.js +6 -0
  140. package/dist/providers/types.js.map +1 -0
  141. package/dist/session/index.d.ts +6 -0
  142. package/dist/session/index.d.ts.map +1 -0
  143. package/dist/session/index.js +6 -0
  144. package/dist/session/index.js.map +1 -0
  145. package/dist/session/manager.d.ts +101 -0
  146. package/dist/session/manager.d.ts.map +1 -0
  147. package/dist/session/manager.js +295 -0
  148. package/dist/session/manager.js.map +1 -0
  149. package/dist/session/types.d.ts +39 -0
  150. package/dist/session/types.d.ts.map +1 -0
  151. package/dist/session/types.js +10 -0
  152. package/dist/session/types.js.map +1 -0
  153. package/dist/tools/builtin/bash.d.ts +7 -0
  154. package/dist/tools/builtin/bash.d.ts.map +1 -0
  155. package/dist/tools/builtin/bash.js +80 -0
  156. package/dist/tools/builtin/bash.js.map +1 -0
  157. package/dist/tools/builtin/edit.d.ts +7 -0
  158. package/dist/tools/builtin/edit.d.ts.map +1 -0
  159. package/dist/tools/builtin/edit.js +32 -0
  160. package/dist/tools/builtin/edit.js.map +1 -0
  161. package/dist/tools/builtin/glob.d.ts +7 -0
  162. package/dist/tools/builtin/glob.d.ts.map +1 -0
  163. package/dist/tools/builtin/glob.js +36 -0
  164. package/dist/tools/builtin/glob.js.map +1 -0
  165. package/dist/tools/builtin/grep.d.ts +7 -0
  166. package/dist/tools/builtin/grep.d.ts.map +1 -0
  167. package/dist/tools/builtin/grep.js +59 -0
  168. package/dist/tools/builtin/grep.js.map +1 -0
  169. package/dist/tools/builtin/read.d.ts +7 -0
  170. package/dist/tools/builtin/read.d.ts.map +1 -0
  171. package/dist/tools/builtin/read.js +29 -0
  172. package/dist/tools/builtin/read.js.map +1 -0
  173. package/dist/tools/builtin/write.d.ts +7 -0
  174. package/dist/tools/builtin/write.d.ts.map +1 -0
  175. package/dist/tools/builtin/write.js +24 -0
  176. package/dist/tools/builtin/write.js.map +1 -0
  177. package/dist/tools/index.d.ts +38 -0
  178. package/dist/tools/index.d.ts.map +1 -0
  179. package/dist/tools/index.js +32 -0
  180. package/dist/tools/index.js.map +1 -0
  181. package/dist/tools/registry.d.ts +22 -0
  182. package/dist/tools/registry.d.ts.map +1 -0
  183. package/dist/tools/registry.js +71 -0
  184. package/dist/tools/registry.js.map +1 -0
  185. package/dist/tools/types.d.ts +62 -0
  186. package/dist/tools/types.d.ts.map +1 -0
  187. package/dist/tools/types.js +126 -0
  188. package/dist/tools/types.js.map +1 -0
  189. package/docs/README.md +16 -0
  190. package/docs/proposals/0001-web-fetch-tool.md +293 -0
  191. package/docs/proposals/0002-web-search-tool.md +306 -0
  192. package/docs/proposals/0003-task-subagents.md +333 -0
  193. package/docs/proposals/0004-plan-mode.md +338 -0
  194. package/docs/proposals/0005-todo-system.md +299 -0
  195. package/docs/proposals/0006-memory-system.md +539 -0
  196. package/docs/proposals/0007-context-management.md +429 -0
  197. package/docs/proposals/0008-checkpointing.md +327 -0
  198. package/docs/proposals/0009-hooks-system.md +343 -0
  199. package/docs/proposals/0010-mcp-integration.md +382 -0
  200. package/docs/proposals/0011-custom-commands.md +374 -0
  201. package/docs/proposals/0012-ask-user-question.md +317 -0
  202. package/docs/proposals/0013-multi-edit-tool.md +345 -0
  203. package/docs/proposals/0014-lsp-tool.md +478 -0
  204. package/docs/proposals/0015-ls-tool.md +407 -0
  205. package/docs/proposals/0016-kill-shell-tool.md +455 -0
  206. package/docs/proposals/0017-background-tasks.md +489 -0
  207. package/docs/proposals/0018-parallel-tool-execution.md +415 -0
  208. package/docs/proposals/0019-session-enhancements.md +462 -0
  209. package/docs/proposals/0020-session-summarization.md +447 -0
  210. package/docs/proposals/0021-skills-system.md +409 -0
  211. package/docs/proposals/0022-plugin-system.md +467 -0
  212. package/docs/proposals/0023-permission-enhancements.md +470 -0
  213. package/docs/proposals/0024-keyboard-shortcuts.md +443 -0
  214. package/docs/proposals/0025-cost-tracking.md +447 -0
  215. package/docs/proposals/0026-git-integration.md +475 -0
  216. package/docs/proposals/0027-enhanced-read-tool.md +514 -0
  217. package/docs/proposals/0028-enhanced-bash-tool.md +511 -0
  218. package/docs/proposals/0029-notebook-edit-tool.md +413 -0
  219. package/docs/proposals/0030-plugin-marketplace.md +360 -0
  220. package/docs/proposals/0031-command-suggestions.md +295 -0
  221. package/docs/proposals/0032-ide-integrations.md +328 -0
  222. package/docs/proposals/0033-enterprise-deployment.md +221 -0
  223. package/docs/proposals/0034-sandboxing.md +273 -0
  224. package/docs/proposals/0035-auto-updater.md +311 -0
  225. package/docs/proposals/0036-enhanced-glob-tool.md +267 -0
  226. package/docs/proposals/0037-enhanced-grep-tool.md +360 -0
  227. package/docs/proposals/0038-interactive-cli-ui.md +373 -0
  228. package/docs/proposals/0039-streaming-enhancements.md +359 -0
  229. package/docs/proposals/0040-multi-provider-enhancements.md +369 -0
  230. package/docs/proposals/README.md +84 -0
  231. package/docs/proposals/TEMPLATE.md +57 -0
  232. package/docs/proposals/research/claude-code-research.md +307 -0
  233. package/examples/agent-demo.ts +115 -0
  234. package/examples/basic.ts +166 -0
  235. package/package.json +50 -0
  236. package/src/agent/agent.ts +276 -0
  237. package/src/agent/index.ts +6 -0
  238. package/src/agent/types.ts +62 -0
  239. package/src/cli/components/App.tsx +565 -0
  240. package/src/cli/components/CommandSuggestions.tsx +58 -0
  241. package/src/cli/components/Header.tsx +36 -0
  242. package/src/cli/components/Input.tsx +60 -0
  243. package/src/cli/components/Logo.tsx +16 -0
  244. package/src/cli/components/Messages.tsx +210 -0
  245. package/src/cli/components/ModelSelector.tsx +135 -0
  246. package/src/cli/components/Spinner.tsx +72 -0
  247. package/src/cli/components/index.ts +21 -0
  248. package/src/cli/components/theme.ts +36 -0
  249. package/src/cli/index.tsx +136 -0
  250. package/src/config/index.ts +7 -0
  251. package/src/config/manager.ts +77 -0
  252. package/src/config/types.ts +25 -0
  253. package/src/index.ts +86 -0
  254. package/src/permissions/index.ts +7 -0
  255. package/src/permissions/manager.ts +97 -0
  256. package/src/permissions/types.ts +29 -0
  257. package/src/providers/anthropic.ts +224 -0
  258. package/src/providers/gemini.ts +295 -0
  259. package/src/providers/index.ts +97 -0
  260. package/src/providers/openai.ts +261 -0
  261. package/src/providers/types.ts +181 -0
  262. package/src/session/index.ts +6 -0
  263. package/src/session/manager.ts +354 -0
  264. package/src/session/types.ts +49 -0
  265. package/src/tools/builtin/bash.ts +92 -0
  266. package/src/tools/builtin/edit.ts +37 -0
  267. package/src/tools/builtin/glob.ts +42 -0
  268. package/src/tools/builtin/grep.ts +67 -0
  269. package/src/tools/builtin/read.ts +34 -0
  270. package/src/tools/builtin/write.ts +27 -0
  271. package/src/tools/index.ts +36 -0
  272. package/src/tools/registry.ts +83 -0
  273. package/src/tools/types.ts +172 -0
  274. package/tsconfig.json +21 -0
@@ -0,0 +1,455 @@
1
+ # Proposal: KillShell Tool
2
+
3
+ - **Proposal ID**: 0016
4
+ - **Author**: mycode team
5
+ - **Status**: Draft
6
+ - **Created**: 2025-01-15
7
+ - **Updated**: 2025-01-15
8
+
9
+ ## Summary
10
+
11
+ Implement a KillShell tool that terminates background shell processes spawned by the Bash tool. This enables the agent to manage long-running processes, cancel stuck commands, and clean up resources properly.
12
+
13
+ ## Motivation
14
+
15
+ With background task execution (Bash with `run_in_background: true`), the agent needs control over running processes:
16
+
17
+ 1. **Stuck processes**: Commands may hang and need termination
18
+ 2. **Resource cleanup**: Long-running servers need graceful shutdown
19
+ 3. **Task cancellation**: User may want to abort running operations
20
+ 4. **Process management**: Track and control multiple background tasks
21
+ 5. **Memory control**: Prevent runaway processes from consuming resources
22
+
23
+ A KillShell tool provides explicit control over background process lifecycle.
24
+
25
+ ## Claude Code Reference
26
+
27
+ Claude Code's KillShell tool works with background Bash commands:
28
+
29
+ ### Tool Definition
30
+ ```typescript
31
+ KillShell({
32
+ shell_id: "bg-abc123" // ID returned by background Bash command
33
+ })
34
+ ```
35
+
36
+ ### Integration with Bash Tool
37
+ ```typescript
38
+ // Background command returns shell_id
39
+ Bash({
40
+ command: "npm run dev",
41
+ run_in_background: true
42
+ })
43
+ // Returns: { task_id: "bg-abc123", ... }
44
+
45
+ // Later, terminate the process
46
+ KillShell({
47
+ shell_id: "bg-abc123"
48
+ })
49
+ ```
50
+
51
+ ### Key Characteristics
52
+ - Works with shell_id from background tasks
53
+ - Sends appropriate signals (SIGTERM, then SIGKILL)
54
+ - Returns success/failure status
55
+ - Available via /tasks command to view running tasks
56
+
57
+ ## Detailed Design
58
+
59
+ ### API Design
60
+
61
+ ```typescript
62
+ // src/tools/kill-shell/types.ts
63
+ interface KillShellInput {
64
+ shell_id: string; // ID of the background shell to kill
65
+ signal?: 'SIGTERM' | 'SIGKILL' | 'SIGINT'; // Signal to send (default: SIGTERM)
66
+ force?: boolean; // Force kill after timeout (default: true)
67
+ timeout?: number; // Ms to wait before SIGKILL (default: 5000)
68
+ }
69
+
70
+ interface KillShellOutput {
71
+ success: boolean;
72
+ shell_id: string;
73
+ signal_sent: string;
74
+ force_killed?: boolean; // True if SIGKILL was needed
75
+ exit_code?: number;
76
+ error?: string;
77
+ }
78
+
79
+ // Related: Background shell tracking
80
+ interface BackgroundShell {
81
+ id: string;
82
+ pid: number;
83
+ command: string;
84
+ started_at: Date;
85
+ status: 'running' | 'completed' | 'killed' | 'error';
86
+ output_file: string;
87
+ }
88
+ ```
89
+
90
+ ```typescript
91
+ // src/tools/kill-shell/kill-shell-tool.ts
92
+ const killShellTool: Tool<KillShellInput> = {
93
+ name: 'KillShell',
94
+ description: `Terminate a running background shell process.
95
+
96
+ Parameters:
97
+ - shell_id: The ID of the background shell to kill
98
+ (returned by Bash tool with run_in_background=true)
99
+ - signal: Signal to send (SIGTERM, SIGKILL, SIGINT). Default: SIGTERM
100
+ - force: If true, send SIGKILL after timeout. Default: true
101
+ - timeout: Milliseconds to wait before force kill. Default: 5000
102
+
103
+ Use /tasks command to see running background shells and their IDs.
104
+
105
+ Returns success status and whether force kill was required.
106
+ `,
107
+ parameters: z.object({
108
+ shell_id: z.string(),
109
+ signal: z.enum(['SIGTERM', 'SIGKILL', 'SIGINT']).optional().default('SIGTERM'),
110
+ force: z.boolean().optional().default(true),
111
+ timeout: z.number().int().positive().optional().default(5000)
112
+ }),
113
+ execute: async (input, context) => { ... }
114
+ };
115
+ ```
116
+
117
+ ### Implementation Approach
118
+
119
+ 1. **Shell Registry**: Track all background shells
120
+ 2. **Process Lookup**: Find process by shell_id
121
+ 3. **Signal Sending**: Send requested signal
122
+ 4. **Wait/Force**: Wait for exit or force kill
123
+ 5. **Cleanup**: Remove from registry, close files
124
+
125
+ ```typescript
126
+ // src/tools/kill-shell/shell-registry.ts
127
+ class ShellRegistry {
128
+ private shells: Map<string, BackgroundShell> = new Map();
129
+
130
+ register(shell: BackgroundShell): void {
131
+ this.shells.set(shell.id, shell);
132
+ }
133
+
134
+ get(id: string): BackgroundShell | undefined {
135
+ return this.shells.get(id);
136
+ }
137
+
138
+ remove(id: string): boolean {
139
+ return this.shells.delete(id);
140
+ }
141
+
142
+ listRunning(): BackgroundShell[] {
143
+ return Array.from(this.shells.values())
144
+ .filter(s => s.status === 'running');
145
+ }
146
+
147
+ cleanup(): void {
148
+ // Remove completed/killed shells older than 1 hour
149
+ const cutoff = Date.now() - 3600000;
150
+ for (const [id, shell] of this.shells) {
151
+ if (shell.status !== 'running' && shell.started_at.getTime() < cutoff) {
152
+ this.shells.delete(id);
153
+ }
154
+ }
155
+ }
156
+ }
157
+
158
+ export const shellRegistry = new ShellRegistry();
159
+ ```
160
+
161
+ ```typescript
162
+ // Core kill implementation
163
+ async function killShell(input: KillShellInput): Promise<KillShellOutput> {
164
+ const { shell_id, signal = 'SIGTERM', force = true, timeout = 5000 } = input;
165
+
166
+ const shell = shellRegistry.get(shell_id);
167
+ if (!shell) {
168
+ return {
169
+ success: false,
170
+ shell_id,
171
+ signal_sent: signal,
172
+ error: `Shell not found: ${shell_id}`
173
+ };
174
+ }
175
+
176
+ if (shell.status !== 'running') {
177
+ return {
178
+ success: true,
179
+ shell_id,
180
+ signal_sent: 'none',
181
+ error: `Shell already ${shell.status}`
182
+ };
183
+ }
184
+
185
+ try {
186
+ // Send initial signal
187
+ process.kill(shell.pid, signal);
188
+ shell.status = 'killed';
189
+
190
+ // Wait for process to exit
191
+ const exited = await waitForExit(shell.pid, timeout);
192
+
193
+ if (!exited && force) {
194
+ // Force kill if still running
195
+ process.kill(shell.pid, 'SIGKILL');
196
+ await waitForExit(shell.pid, 1000);
197
+
198
+ return {
199
+ success: true,
200
+ shell_id,
201
+ signal_sent: signal,
202
+ force_killed: true
203
+ };
204
+ }
205
+
206
+ return {
207
+ success: exited,
208
+ shell_id,
209
+ signal_sent: signal,
210
+ force_killed: false
211
+ };
212
+ } catch (error) {
213
+ // Process may already be dead
214
+ if ((error as NodeJS.ErrnoException).code === 'ESRCH') {
215
+ shell.status = 'completed';
216
+ return {
217
+ success: true,
218
+ shell_id,
219
+ signal_sent: signal,
220
+ error: 'Process already terminated'
221
+ };
222
+ }
223
+ throw error;
224
+ }
225
+ }
226
+
227
+ async function waitForExit(pid: number, timeout: number): Promise<boolean> {
228
+ const start = Date.now();
229
+ while (Date.now() - start < timeout) {
230
+ try {
231
+ process.kill(pid, 0); // Check if process exists
232
+ await new Promise(r => setTimeout(r, 100));
233
+ } catch {
234
+ return true; // Process exited
235
+ }
236
+ }
237
+ return false; // Timeout
238
+ }
239
+ ```
240
+
241
+ ### Enhanced Bash Tool Integration
242
+
243
+ ```typescript
244
+ // Update to src/tools/builtin/bash.ts
245
+ interface BashInput {
246
+ command: string;
247
+ timeout?: number;
248
+ run_in_background?: boolean; // NEW
249
+ description?: string;
250
+ }
251
+
252
+ interface BashOutput {
253
+ success: boolean;
254
+ stdout: string;
255
+ stderr: string;
256
+ exit_code: number;
257
+ // NEW: For background tasks
258
+ task_id?: string;
259
+ output_file?: string;
260
+ }
261
+
262
+ async function executeBash(input: BashInput, context: ToolContext): Promise<BashOutput> {
263
+ if (input.run_in_background) {
264
+ return executeInBackground(input, context);
265
+ }
266
+ return executeSync(input, context);
267
+ }
268
+
269
+ async function executeInBackground(
270
+ input: BashInput,
271
+ context: ToolContext
272
+ ): Promise<BashOutput> {
273
+ const shellId = generateShellId();
274
+ const outputFile = path.join(os.tmpdir(), `mycode-${shellId}.log`);
275
+
276
+ const child = spawn('bash', ['-c', input.command], {
277
+ cwd: context.cwd,
278
+ detached: true,
279
+ stdio: ['ignore', 'pipe', 'pipe']
280
+ });
281
+
282
+ // Setup output logging
283
+ const logStream = fs.createWriteStream(outputFile);
284
+ child.stdout?.pipe(logStream);
285
+ child.stderr?.pipe(logStream);
286
+
287
+ // Register in shell registry
288
+ shellRegistry.register({
289
+ id: shellId,
290
+ pid: child.pid!,
291
+ command: input.command,
292
+ started_at: new Date(),
293
+ status: 'running',
294
+ output_file: outputFile
295
+ });
296
+
297
+ // Detach process
298
+ child.unref();
299
+
300
+ return {
301
+ success: true,
302
+ stdout: '',
303
+ stderr: '',
304
+ exit_code: -1,
305
+ task_id: shellId,
306
+ output_file: outputFile
307
+ };
308
+ }
309
+ ```
310
+
311
+ ### File Changes
312
+
313
+ | File | Action | Description |
314
+ |------|--------|-------------|
315
+ | `src/tools/kill-shell/types.ts` | Create | Type definitions |
316
+ | `src/tools/kill-shell/kill-shell-tool.ts` | Create | Tool implementation |
317
+ | `src/tools/kill-shell/shell-registry.ts` | Create | Background shell tracking |
318
+ | `src/tools/kill-shell/index.ts` | Create | Module exports |
319
+ | `src/tools/builtin/bash.ts` | Modify | Add background execution |
320
+ | `src/tools/index.ts` | Modify | Register KillShell tool |
321
+ | `src/cli/commands/tasks.ts` | Create | /tasks command |
322
+
323
+ ## User Experience
324
+
325
+ ### View Running Tasks
326
+ ```
327
+ User: /tasks
328
+
329
+ Active Background Tasks:
330
+ ┌────────────────────────────────────────────────────────────┐
331
+ │ ID Command Started Status │
332
+ ├────────────────────────────────────────────────────────────┤
333
+ │ bg-a1b2c3 npm run dev 5 min ago running │
334
+ │ bg-d4e5f6 pytest --watch 2 min ago running │
335
+ │ bg-g7h8i9 docker compose up 10 min ago running │
336
+ └────────────────────────────────────────────────────────────┘
337
+
338
+ Use KillShell tool with shell_id to terminate a task.
339
+ ```
340
+
341
+ ### Kill Background Process
342
+ ```
343
+ User: Stop the npm dev server
344
+
345
+ Agent: I'll terminate the background npm process.
346
+
347
+ [KillShell: shell_id="bg-a1b2c3"]
348
+
349
+ ┌─ Process Terminated ──────────────────────────────┐
350
+ │ Shell ID: bg-a1b2c3 │
351
+ │ Command: npm run dev │
352
+ │ Signal: SIGTERM │
353
+ │ Status: Terminated gracefully │
354
+ └───────────────────────────────────────────────────┘
355
+ ```
356
+
357
+ ### Force Kill Hung Process
358
+ ```
359
+ Agent: [KillShell: shell_id="bg-stuck", timeout=3000]
360
+
361
+ ┌─ Process Force Killed ────────────────────────────┐
362
+ │ Shell ID: bg-stuck │
363
+ │ Signal: SIGTERM → SIGKILL │
364
+ │ Status: Force killed after 3s timeout │
365
+ │ Note: Process did not respond to SIGTERM │
366
+ └───────────────────────────────────────────────────┘
367
+ ```
368
+
369
+ ### Shell Not Found
370
+ ```
371
+ Agent: [KillShell: shell_id="invalid-id"]
372
+
373
+ Error: Shell not found: invalid-id
374
+ Use /tasks to see available background shells.
375
+ ```
376
+
377
+ ## Alternatives Considered
378
+
379
+ ### Alternative 1: Kill via Bash
380
+ Use `kill` command through Bash tool.
381
+
382
+ **Pros**: No new tool needed
383
+ **Cons**: Requires PID tracking, shell escaping risks
384
+ **Decision**: Rejected - Dedicated tool is safer
385
+
386
+ ### Alternative 2: Automatic Cleanup Only
387
+ Kill processes automatically on session end.
388
+
389
+ **Pros**: Simpler, no user action needed
390
+ **Cons**: No mid-session control
391
+ **Decision**: Rejected - Manual control is essential
392
+
393
+ ### Alternative 3: Process Groups
394
+ Use process groups for batch termination.
395
+
396
+ **Pros**: Kill entire process trees
397
+ **Cons**: More complex, may affect other processes
398
+ **Decision**: Deferred - Can add later
399
+
400
+ ## Security Considerations
401
+
402
+ 1. **Registry Isolation**: Only kill processes we spawned
403
+ 2. **PID Validation**: Verify PID still belongs to expected command
404
+ 3. **No Arbitrary Signals**: Only allow safe signals
405
+ 4. **Cleanup on Exit**: Kill orphaned processes on mycode exit
406
+ 5. **User Confirmation**: Consider confirmation for long-running tasks
407
+
408
+ ```typescript
409
+ // Safety check before kill
410
+ function validateShell(shell: BackgroundShell): boolean {
411
+ try {
412
+ // Verify process exists and matches
413
+ const procCommand = getProcessCommand(shell.pid);
414
+ return procCommand.includes(shell.command.slice(0, 20));
415
+ } catch {
416
+ return false;
417
+ }
418
+ }
419
+ ```
420
+
421
+ ## Testing Strategy
422
+
423
+ 1. **Unit Tests**:
424
+ - Shell registration/lookup
425
+ - Signal sending
426
+ - Timeout handling
427
+ - Force kill logic
428
+
429
+ 2. **Integration Tests**:
430
+ - Background command execution
431
+ - Graceful termination
432
+ - Force kill scenarios
433
+ - Process not found
434
+
435
+ 3. **Manual Testing**:
436
+ - Long-running servers
437
+ - Hung processes
438
+ - Multiple concurrent tasks
439
+
440
+ ## Migration Path
441
+
442
+ 1. **Phase 1**: Basic kill with SIGTERM
443
+ 2. **Phase 2**: Force kill with timeout
444
+ 3. **Phase 3**: Shell registry and /tasks command
445
+ 4. **Phase 4**: Process group support
446
+ 5. **Phase 5**: Cleanup automation
447
+
448
+ Requires Enhanced Bash Tool (0028) for full functionality.
449
+
450
+ ## References
451
+
452
+ - [Node.js Child Process](https://nodejs.org/api/child_process.html)
453
+ - [Unix Signals](https://man7.org/linux/man-pages/man7/signal.7.html)
454
+ - [Process Groups and Sessions](https://www.win.tue.nl/~aeb/linux/lk/lk-10.html)
455
+ - [Claude Code Background Tasks](https://code.claude.com/docs/en/tools)