claws-code 0.8.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 (180) hide show
  1. package/.claude/commands/claws-auto.md +90 -0
  2. package/.claude/commands/claws-bin.md +28 -0
  3. package/.claude/commands/claws-cleanup.md +28 -0
  4. package/.claude/commands/claws-do.md +82 -0
  5. package/.claude/commands/claws-fix.md +40 -0
  6. package/.claude/commands/claws-goal.md +111 -0
  7. package/.claude/commands/claws-help.md +54 -0
  8. package/.claude/commands/claws-plan.md +103 -0
  9. package/.claude/commands/claws-report.md +29 -0
  10. package/.claude/commands/claws-status.md +37 -0
  11. package/.claude/commands/claws-update.md +32 -0
  12. package/.claude/commands/claws.md +64 -0
  13. package/.claude/rules/claws-default-behavior.md +76 -0
  14. package/.claude/settings.json +112 -0
  15. package/.claude/settings.local.json +19 -0
  16. package/.claude/skills/claws-auto-engine/SKILL.md +97 -0
  17. package/.claude/skills/claws-goal-tracker/SKILL.md +106 -0
  18. package/.claude/skills/claws-prompt-templates/SKILL.md +203 -0
  19. package/.claude/skills/claws-wave-lead/SKILL.md +126 -0
  20. package/.claude/skills/claws-wave-subworker/SKILL.md +60 -0
  21. package/CHANGELOG.md +1949 -0
  22. package/LICENSE +21 -0
  23. package/README.md +420 -0
  24. package/bin/cli.js +84 -0
  25. package/cli.js +223 -0
  26. package/docs/ARCHITECTURE.md +511 -0
  27. package/docs/event-protocol.md +588 -0
  28. package/docs/features.md +562 -0
  29. package/docs/guide.md +891 -0
  30. package/docs/index.html +716 -0
  31. package/docs/protocol.md +323 -0
  32. package/extension/.vscodeignore +15 -0
  33. package/extension/CHANGELOG.md +1906 -0
  34. package/extension/LICENSE +21 -0
  35. package/extension/README.md +137 -0
  36. package/extension/docs/features.md +424 -0
  37. package/extension/docs/protocol.md +197 -0
  38. package/extension/esbuild.mjs +25 -0
  39. package/extension/icon.png +0 -0
  40. package/extension/native/.metadata.json +10 -0
  41. package/extension/native/node-pty/LICENSE +69 -0
  42. package/extension/native/node-pty/README.md +165 -0
  43. package/extension/native/node-pty/lib/conpty_console_list_agent.js +16 -0
  44. package/extension/native/node-pty/lib/conpty_console_list_agent.js.map +1 -0
  45. package/extension/native/node-pty/lib/eventEmitter2.js +47 -0
  46. package/extension/native/node-pty/lib/eventEmitter2.js.map +1 -0
  47. package/extension/native/node-pty/lib/index.js +52 -0
  48. package/extension/native/node-pty/lib/index.js.map +1 -0
  49. package/extension/native/node-pty/lib/interfaces.js +7 -0
  50. package/extension/native/node-pty/lib/interfaces.js.map +1 -0
  51. package/extension/native/node-pty/lib/shared/conout.js +11 -0
  52. package/extension/native/node-pty/lib/shared/conout.js.map +1 -0
  53. package/extension/native/node-pty/lib/terminal.js +190 -0
  54. package/extension/native/node-pty/lib/terminal.js.map +1 -0
  55. package/extension/native/node-pty/lib/types.js +7 -0
  56. package/extension/native/node-pty/lib/types.js.map +1 -0
  57. package/extension/native/node-pty/lib/unixTerminal.js +346 -0
  58. package/extension/native/node-pty/lib/unixTerminal.js.map +1 -0
  59. package/extension/native/node-pty/lib/utils.js +39 -0
  60. package/extension/native/node-pty/lib/utils.js.map +1 -0
  61. package/extension/native/node-pty/lib/windowsConoutConnection.js +125 -0
  62. package/extension/native/node-pty/lib/windowsConoutConnection.js.map +1 -0
  63. package/extension/native/node-pty/lib/windowsPtyAgent.js +320 -0
  64. package/extension/native/node-pty/lib/windowsPtyAgent.js.map +1 -0
  65. package/extension/native/node-pty/lib/windowsTerminal.js +199 -0
  66. package/extension/native/node-pty/lib/windowsTerminal.js.map +1 -0
  67. package/extension/native/node-pty/lib/worker/conoutSocketWorker.js +22 -0
  68. package/extension/native/node-pty/lib/worker/conoutSocketWorker.js.map +1 -0
  69. package/extension/native/node-pty/package.json +64 -0
  70. package/extension/native/node-pty/prebuilds/darwin-arm64/pty.node +0 -0
  71. package/extension/native/node-pty/prebuilds/darwin-arm64/spawn-helper +0 -0
  72. package/extension/native/node-pty/prebuilds/darwin-x64/pty.node +0 -0
  73. package/extension/native/node-pty/prebuilds/darwin-x64/spawn-helper +0 -0
  74. package/extension/native/node-pty/prebuilds/win32-arm64/conpty/OpenConsole.exe +0 -0
  75. package/extension/native/node-pty/prebuilds/win32-arm64/conpty/conpty.dll +0 -0
  76. package/extension/native/node-pty/prebuilds/win32-arm64/conpty.node +0 -0
  77. package/extension/native/node-pty/prebuilds/win32-arm64/conpty_console_list.node +0 -0
  78. package/extension/native/node-pty/prebuilds/win32-arm64/pty.node +0 -0
  79. package/extension/native/node-pty/prebuilds/win32-arm64/winpty-agent.exe +0 -0
  80. package/extension/native/node-pty/prebuilds/win32-arm64/winpty.dll +0 -0
  81. package/extension/native/node-pty/prebuilds/win32-x64/conpty/OpenConsole.exe +0 -0
  82. package/extension/native/node-pty/prebuilds/win32-x64/conpty/conpty.dll +0 -0
  83. package/extension/native/node-pty/prebuilds/win32-x64/conpty.node +0 -0
  84. package/extension/native/node-pty/prebuilds/win32-x64/conpty_console_list.node +0 -0
  85. package/extension/native/node-pty/prebuilds/win32-x64/pty.node +0 -0
  86. package/extension/native/node-pty/prebuilds/win32-x64/winpty-agent.exe +0 -0
  87. package/extension/native/node-pty/prebuilds/win32-x64/winpty.dll +0 -0
  88. package/extension/package-lock.json +605 -0
  89. package/extension/package.json +343 -0
  90. package/extension/scripts/bundle-native.mjs +104 -0
  91. package/extension/scripts/deploy-dev.mjs +60 -0
  92. package/extension/src/ansi-strip.ts +52 -0
  93. package/extension/src/backends/vscode/claws-pty.ts +483 -0
  94. package/extension/src/backends/vscode/status-bar.ts +99 -0
  95. package/extension/src/backends/vscode/vscode-backend.ts +282 -0
  96. package/extension/src/capture-store.ts +125 -0
  97. package/extension/src/event-log.ts +629 -0
  98. package/extension/src/event-schemas.ts +478 -0
  99. package/extension/src/extension.js +492 -0
  100. package/extension/src/extension.ts +873 -0
  101. package/extension/src/lifecycle-engine.ts +60 -0
  102. package/extension/src/lifecycle-rules.ts +171 -0
  103. package/extension/src/lifecycle-store.ts +506 -0
  104. package/extension/src/peer-registry.ts +176 -0
  105. package/extension/src/pipeline-registry.ts +82 -0
  106. package/extension/src/platform.ts +64 -0
  107. package/extension/src/protocol.ts +532 -0
  108. package/extension/src/server-config.ts +98 -0
  109. package/extension/src/server.ts +2210 -0
  110. package/extension/src/task-registry.ts +51 -0
  111. package/extension/src/terminal-backend.ts +211 -0
  112. package/extension/src/terminal-manager.ts +395 -0
  113. package/extension/src/topic-registry.ts +70 -0
  114. package/extension/src/topic-utils.ts +46 -0
  115. package/extension/src/transport.ts +45 -0
  116. package/extension/src/uninstall-cleanup.ts +232 -0
  117. package/extension/src/wave-registry.ts +314 -0
  118. package/extension/src/websocket-transport.ts +153 -0
  119. package/extension/tsconfig.json +23 -0
  120. package/lib/capabilities.js +145 -0
  121. package/lib/dry-run.js +43 -0
  122. package/lib/install.js +1018 -0
  123. package/lib/mcp-setup.js +92 -0
  124. package/lib/platform.js +240 -0
  125. package/lib/preflight.js +152 -0
  126. package/lib/shell-hook.js +343 -0
  127. package/lib/uninstall.js +162 -0
  128. package/lib/verify.js +166 -0
  129. package/mcp_server.js +3529 -0
  130. package/package.json +48 -0
  131. package/rules/claws-default-behavior.md +72 -0
  132. package/scripts/_helpers/atomic-file.mjs +137 -0
  133. package/scripts/_helpers/fix-repair.js +64 -0
  134. package/scripts/_helpers/json-safe.mjs +218 -0
  135. package/scripts/bump-version.sh +84 -0
  136. package/scripts/codegen/gen-docs.mjs +61 -0
  137. package/scripts/codegen/gen-json-schema.mjs +62 -0
  138. package/scripts/codegen/gen-mcp-tools.mjs +358 -0
  139. package/scripts/codegen/gen-types.mjs +172 -0
  140. package/scripts/codegen/index.mjs +42 -0
  141. package/scripts/dev-hooks/check-extension-dirs.js +77 -0
  142. package/scripts/dev-hooks/check-open-claws-terminals.js +70 -0
  143. package/scripts/dev-hooks/check-stale-main.js +55 -0
  144. package/scripts/dev-hooks/check-tag-pushed.js +51 -0
  145. package/scripts/dev-hooks/check-tag-vs-main.js +56 -0
  146. package/scripts/dev-vsix-install.sh +60 -0
  147. package/scripts/fix.sh +702 -0
  148. package/scripts/gen-client-types.mjs +81 -0
  149. package/scripts/git-hooks/pre-commit +31 -0
  150. package/scripts/hooks/lifecycle-state.js +61 -0
  151. package/scripts/hooks/package.json +4 -0
  152. package/scripts/hooks/post-tool-use-claws.js +292 -0
  153. package/scripts/hooks/pre-bash-no-verify-block.js +72 -0
  154. package/scripts/hooks/pre-tool-use-claws.js +206 -0
  155. package/scripts/hooks/session-start-claws.js +97 -0
  156. package/scripts/hooks/stop-claws.js +88 -0
  157. package/scripts/inject-claude-md.js +205 -0
  158. package/scripts/inject-dev-hooks.js +96 -0
  159. package/scripts/inject-global-claude-md.js +140 -0
  160. package/scripts/inject-settings-hooks.js +370 -0
  161. package/scripts/install.ps1 +146 -0
  162. package/scripts/install.sh +1729 -0
  163. package/scripts/monitor-arm-watch.js +155 -0
  164. package/scripts/rebuild-node-pty.sh +245 -0
  165. package/scripts/report.sh +232 -0
  166. package/scripts/shell-hook.fish +164 -0
  167. package/scripts/shell-hook.ps1 +33 -0
  168. package/scripts/shell-hook.sh +232 -0
  169. package/scripts/stream-events.js +399 -0
  170. package/scripts/terminal-wrapper.sh +36 -0
  171. package/scripts/test-enforcement.sh +132 -0
  172. package/scripts/test-install.sh +174 -0
  173. package/scripts/test-installer-parity.sh +135 -0
  174. package/scripts/test-template-enforcement.sh +76 -0
  175. package/scripts/uninstall.sh +143 -0
  176. package/scripts/update.sh +337 -0
  177. package/scripts/verify-release.sh +323 -0
  178. package/scripts/verify-wrapped.sh +194 -0
  179. package/templates/CLAUDE.global.md +135 -0
  180. package/templates/CLAUDE.project.md +37 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Anish Neunaha
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,137 @@
1
+ ![Claws](../docs/images/social-preview.png)
2
+
3
+ # Claws — Programmable Terminal Bridge
4
+
5
+ Turn every VS Code terminal into a programmable endpoint your AI agent can drive.
6
+
7
+ ---
8
+
9
+ ## What it does
10
+
11
+ Claws is a VS Code extension that runs a local socket server inside your editor. Any external process — Claude Code, an orchestration script, a CI runner — connects over Unix socket and gets full programmatic control of every terminal: list, create, send text, execute commands with captured output, read pty logs, and close. No plugins in the terminal, no shell integration required.
12
+
13
+ The key feature is **wrapped terminals**: Claws uses VS Code's native Pseudoterminal API (backed by `node-pty`) to capture every pty byte into an in-memory ring buffer. That buffer is readable via the `claws_read_log` MCP tool with ANSI escapes stripped — giving AI agents clean, structured visibility into Claude Code sessions, build logs, vim sessions, or any TUI. Combine this with 39 MCP tools across 6 categories (terminal control, pub/sub, tasks, lifecycle, waves, RPC/schemas) and you get a full AI orchestration substrate inside your editor.
14
+
15
+ ---
16
+
17
+ ## Demo
18
+
19
+ ![](../docs/images/before-after.png)
20
+
21
+ ---
22
+
23
+ ## Quick Install
24
+
25
+ 1. **Install the extension** from the VS Code Marketplace (search `Claws: Programmable Terminal Bridge`)
26
+ 2. **Run the project installer** from your project root:
27
+ ```bash
28
+ bash <(curl -fsSL https://raw.githubusercontent.com/neunaha/claws/main/scripts/install.sh)
29
+ ```
30
+ This writes `.mcp.json`, `.claws-bin/mcp_server.js`, and `.claude/commands/` into your project. Re-run in each project you want Claws in.
31
+ 3. **Reload VS Code** (`Cmd+Shift+P` → `Developer: Reload Window`) then restart Claude Code from the project root so it picks up `.mcp.json` and loads the 39 Claws tools. If tools don't appear, run `/claws-fix`.
32
+
33
+ ---
34
+
35
+ ## The 8 Commands
36
+
37
+ | Command | What it does |
38
+ |---|---|
39
+ | `/claws` | Live dashboard — terminal count, socket state, version |
40
+ | `/claws-do <task>` | Universal verb — classifies any task and runs the right tool |
41
+ | `/claws-status` | Show all active terminals and their lifecycle state |
42
+ | `/claws-cleanup` | Close all worker terminals; leave user-created ones untouched |
43
+ | `/claws-help` | Full reference for every command and MCP tool |
44
+ | `/claws-fix` | Diagnose and auto-repair a broken installation in one command |
45
+ | `/claws-report` | Bundle logs and diagnostics into a shareable file for bug reports |
46
+ | `/claws-update` | Pull latest version and rebuild in place |
47
+
48
+ ---
49
+
50
+ ## Key Capabilities
51
+
52
+ ### `claws_done()` — one-tool completion
53
+
54
+ ![](../docs/images/claws-done-completion.png)
55
+
56
+ Workers call `claws_done()` as their final act. The tool reads `CLAWS_TERMINAL_ID` from the worker's environment (injected at spawn), publishes `system.worker.completed` to the Claws event bus, and closes the terminal — all in one atomic call, zero arguments. No marker scanning, no manual polling.
57
+
58
+ ### Worker fleet — parallel Claude workers with auto-monitoring
59
+
60
+ ![](../docs/images/architecture.png)
61
+
62
+ `claws_fleet(workers=[…])` spawns N wrapped terminals in parallel, boots Claude Code in each with full permissions, delivers missions via bracketed paste, and returns `terminal_ids` + `correlation_ids` immediately. The orchestrator polls completion with `claws_workers_wait` or arms per-worker Monitors via `stream-events.js --wait <uuid>`. `claws_dispatch_subworker` enables Wave Army patterns with LEAD + sub-worker coordination.
63
+
64
+ ### Wrapped pty capture — every byte logged, ANSI-stripped
65
+
66
+ ![](../docs/images/wrapped-terminal.png)
67
+
68
+ Wrapped terminals use VS Code's `Pseudoterminal` API with `node-pty` — no `script(1)`, no rendering corruption. Every byte flows through the extension's `onDidWrite` event into a ring buffer. `claws_read_log` returns clean text with ANSI escapes stripped, enabling AI agents to read back TUI sessions they can't otherwise see.
69
+
70
+ ### Safety gate — warn before sending into TUIs
71
+
72
+ ![](../docs/images/cap-safety.png)
73
+
74
+ Before sending text, Claws checks whether the foreground process is a shell or a TUI (Claude Code, vim, htop). If it's a TUI, the send proceeds with a warning — the caller decides. Pass `strict: true` to hard-block. This is what makes it safe to automate terminals that also have human users.
75
+
76
+ ### Self-diagnosis — `/claws-fix` repairs the install chain
77
+
78
+ ![](../docs/images/cap-mcp.png)
79
+
80
+ `/claws-fix` runs a structured diagnostic sequence: checks the socket, verifies MCP registration in `.mcp.json`, probes `node-pty` load path, validates the hook chain, and repairs any broken layer it finds. **Health Check** (`cmd+alt+c h`) gives an instant introspection snapshot. The status bar item shows live socket state at a glance.
81
+
82
+ ---
83
+
84
+ ## Settings Reference
85
+
86
+ | Setting | Default | Description |
87
+ |---|---|---|
88
+ | `claws.socketPath` | `.claws/claws.sock` | Relative path from workspace root for the Unix socket |
89
+ | `claws.logDirectory` | `.claws/terminals` | Relative path for wrapped terminal pty logs |
90
+ | `claws.defaultWrapped` | `false` | Create all new terminals as wrapped by default |
91
+ | `claws.maxOutputBytes` | `262144` | Max bytes buffered per command event (256 KB) |
92
+ | `claws.maxHistory` | `500` | Max command events in the ring buffer |
93
+ | `claws.maxCaptureBytes` | `1048576` | Max per-terminal output in the in-memory capture buffer (1 MB) |
94
+ | `claws.execTimeoutMs` | `180000` | Default exec command timeout in milliseconds (180 s) |
95
+ | `claws.pollLimit` | `100` | Max history events returned by a single `poll` request |
96
+ | `claws.heartbeatIntervalMs` | `60000` | Interval between `system.heartbeat` events (0 = disable) |
97
+ | `claws.strictEventValidation` | `false` | Reject publish requests that fail schema validation |
98
+ | `claws.auth.enabled` | `false` | Require HMAC-SHA256 token on hello requests |
99
+ | `claws.auth.tokenPath` | `.claws/auth.token` | Path to the shared secret file for token validation |
100
+ | `claws.webSocket.enabled` | `false` | [Planned] Enable WebSocket server for cross-device access |
101
+ | `claws.webSocket.port` | `5678` | [Planned] TCP port for the WebSocket server |
102
+
103
+ ---
104
+
105
+ ## Keyboard Shortcuts
106
+
107
+ | Shortcut | Action |
108
+ |---|---|
109
+ | `cmd+alt+c h` (Mac) / `ctrl+alt+c h` (Win/Linux) | Health Check — instant introspection snapshot |
110
+ | `cmd+alt+c l` / `ctrl+alt+c l` | Show Log — open the Claws Output channel |
111
+ | `cmd+alt+c s` / `ctrl+alt+c s` | Show Status — markdown runtime block |
112
+
113
+ ---
114
+
115
+ ## What's New in v0.7
116
+
117
+ - **`claws_done()` is now the primary completion signal** — one zero-arg MCP call publishes `system.worker.completed`, closes the terminal, and frees the orchestrator. No more marker scanning.
118
+ - **Wave Army** — `claws_fleet` and `claws_dispatch_subworker` enable parallel Claude worker fleets with LEAD orchestration, heartbeat protocol, and per-role phase events.
119
+ - **Non-blocking workers by default** — mission-mode `claws_worker` returns immediately with `terminal_id` + `correlation_id`; blocking is opt-in. The MCP stdio transport no longer hangs on long missions.
120
+ - **Behavioral injection enforcement** — a 5-layer chain (global `CLAUDE.md` → project `CLAUDE.md` block → SessionStart hook → PreToolUse hook → Stop hook) ensures workers follow the terminal hygiene contract even across cold boots.
121
+ - **LH-9 TTL watchdog** — workers that exceed their TTL or violate the heartbeat contract are automatically terminated with a `wave_violation` event; the orchestrator is never left waiting on a dead worker.
122
+ - **8-command set** — 27 commands consolidated to 8. `/claws-do` routes into exec, worker, fleet, and wave buckets automatically.
123
+ - **`stream-events.js --wait <uuid>`** — native Node.js completion waiter replaces fragile awk/grep pipelines; per-worker Monitors self-exit on the first matching `system.worker.completed` event.
124
+
125
+ ---
126
+
127
+ ## Windows / WSL
128
+
129
+ The core extension and MCP server work on Windows and WSL. Wrapped terminal pty capture uses VS Code's native `Pseudoterminal` API (backed by `node-pty`) rather than `script(1)`, so there are no BSD vs GNU compatibility differences. The `install.sh` project setup script requires a bash environment — run it from WSL or Git Bash on Windows. On WSL, the Unix socket path (`.claws/claws.sock`) resolves inside the WSL filesystem; cross-boundary socket access is not supported.
130
+
131
+ ---
132
+
133
+ ## Links
134
+
135
+ - [GitHub](https://github.com/neunaha/claws) — source, issues, contributing
136
+ - [Documentation](https://github.com/neunaha/claws/tree/main/docs) — protocol spec, guide, feature reference
137
+ - [Issues](https://github.com/neunaha/claws/issues) — bug reports and feature requests
@@ -0,0 +1,424 @@
1
+ # Claws — Complete Feature Reference
2
+
3
+ Everything the extension can do, in depth. For the quick overview, see the [README](../README.md).
4
+
5
+ ---
6
+
7
+ ## Table of Contents
8
+
9
+ - [Terminal Discovery](#terminal-discovery)
10
+ - [Terminal Creation](#terminal-creation)
11
+ - [Wrapped Terminals](#wrapped-terminals)
12
+ - [Text Injection (send)](#text-injection)
13
+ - [Command Execution (exec)](#command-execution)
14
+ - [Pty Log Reading (readLog)](#pty-log-reading)
15
+ - [Event Streaming (poll)](#event-streaming)
16
+ - [Terminal Profile — Dropdown Integration](#terminal-profile)
17
+ - [Safety Gate](#safety-gate)
18
+ - [Bracketed Paste](#bracketed-paste)
19
+ - [Configuration Reference](#configuration-reference)
20
+ - [Socket Server Internals](#socket-server-internals)
21
+ - [Cross-Device Control](#cross-device-control)
22
+
23
+ ---
24
+
25
+ ## Terminal Discovery
26
+
27
+ **Command**: `list`
28
+
29
+ Returns every open VS Code terminal with full metadata:
30
+
31
+ | Field | Type | Description |
32
+ |---|---|---|
33
+ | `id` | string | Stable numeric ID, persists for the terminal's lifetime |
34
+ | `name` | string | Terminal display name (user-set or auto-assigned) |
35
+ | `pid` | number | Shell process ID |
36
+ | `hasShellIntegration` | boolean | Whether VS Code's shell integration is active |
37
+ | `active` | boolean | Whether this is the currently focused terminal |
38
+ | `logPath` | string or null | Absolute path to the pty log file (null if not wrapped) |
39
+
40
+ **Why stable IDs matter**: VS Code's terminal API identifies terminals by object reference internally. Claws assigns each terminal a monotonically increasing numeric ID at first sight and holds it in a `WeakMap`. The ID survives terminal renames, focus changes, and extension reloads within the same VS Code session. External clients use this ID for every subsequent command — no fragile name-matching.
41
+
42
+ **Example response**:
43
+ ```json
44
+ {
45
+ "ok": true,
46
+ "terminals": [
47
+ {"id": "1", "name": "zsh", "pid": 45123, "hasShellIntegration": true, "active": false, "logPath": null},
48
+ {"id": "3", "name": "build-worker", "pid": 45890, "hasShellIntegration": false, "active": true, "logPath": "/project/.claws/terminals/claws-3.log"}
49
+ ]
50
+ }
51
+ ```
52
+
53
+ ---
54
+
55
+ ## Terminal Creation
56
+
57
+ **Command**: `create`
58
+
59
+ Opens a new VS Code integrated terminal with full control over its configuration.
60
+
61
+ | Parameter | Type | Default | Description |
62
+ |---|---|---|---|
63
+ | `name` | string | `"claws"` | Display name in the terminal panel |
64
+ | `cwd` | string | workspace root | Working directory |
65
+ | `wrapped` | boolean | `false` | Wrap in `script(1)` for pty logging |
66
+ | `show` | boolean | `true` | Show the terminal panel and focus it |
67
+ | `shellPath` | string | system default | Override the shell binary |
68
+ | `env` | object | `{}` | Additional environment variables |
69
+
70
+ **Returns**: `{ id, logPath }` — the new terminal's stable ID and (if wrapped) the absolute path to its pty log file.
71
+
72
+ **Terminal naming**: the `name` parameter sets the tab label in VS Code's terminal panel. Use descriptive names for orchestration (`"lint-worker"`, `"test-runner"`, `"ai-session-1"`) so you can identify terminals visually.
73
+
74
+ **Working directory**: defaults to the workspace root. Set `cwd` to any absolute path to start the terminal elsewhere — useful for monorepo setups where different workers operate in different packages.
75
+
76
+ ---
77
+
78
+ ## Wrapped Terminals
79
+
80
+ The core innovation. A wrapped terminal runs your shell inside `script(1)`:
81
+
82
+ ```
83
+ VS Code Terminal Panel
84
+ └── script(1) process
85
+ └── /bin/zsh (your actual shell)
86
+ └── whatever you run (claude, npm, vim, etc.)
87
+ ```
88
+
89
+ `script(1)` is a standard Unix utility (ships with macOS and Linux) that records everything that flows through a pseudo-terminal to a file. Claws sets the output file to `.claws/terminals/claws-<id>.log` and passes it via the `CLAWS_TERM_LOG` environment variable.
90
+
91
+ ### What gets captured
92
+
93
+ Everything. Every byte that the terminal renders:
94
+
95
+ - Shell prompts and command echoes
96
+ - stdout and stderr from every command
97
+ - Interactive TUI rendering (Claude Code's Ink framework, vim's ncurses, htop's dashboard)
98
+ - ANSI escape sequences (colors, cursor movement, screen clearing)
99
+ - Control characters
100
+
101
+ ### What you get back (after ANSI stripping)
102
+
103
+ Clean, readable text. Claws strips ANSI CSI sequences (`\e[...m`, `\e[...H`, etc.), OSC sequences (`\e]...BEL`), and control characters (`\x00-\x1f` except `\n` and `\t`). The result is what a human would read if they were watching the terminal.
104
+
105
+ ### Visual impact
106
+
107
+ Zero. A wrapped terminal looks, feels, and behaves identically to a regular terminal. The `script(1)` layer adds no visible latency, no changed prompts, no extra processes in the shell's job table. The user cannot tell the difference unless they check for the `CLAWS_WRAPPED=1` environment variable.
108
+
109
+ ### Log buffering
110
+
111
+ `script(1)` buffers output before writing to disk. On macOS with the default settings (no `-F` flag), there's a ~1-2 second delay before new content appears in the log file. This is intentional — aggressive flushing (`-F` flag) causes visual corruption in Ink-based TUI renderers (like Claude Code) by splitting their atomic frame updates across flush boundaries.
112
+
113
+ ### Creating wrapped terminals
114
+
115
+ Three ways:
116
+
117
+ 1. **From the dropdown**: Click the arrow next to `+` in the terminal panel → "Claws Wrapped Terminal"
118
+ 2. **From code**: `client.create("name", wrapped=True)`
119
+ 3. **From the socket**: `{"cmd": "create", "name": "name", "wrapped": true}`
120
+
121
+ ### The wrapper script
122
+
123
+ Located at `scripts/terminal-wrapper.sh`. It:
124
+
125
+ 1. Creates the log directory if missing
126
+ 2. Truncates the log file (fresh start)
127
+ 3. Sets `CLAWS_WRAPPED=1` in the environment
128
+ 4. Exec-replaces itself with `script -q "$CLAWS_TERM_LOG" /bin/zsh -il`
129
+
130
+ The script is resolved at runtime: Claws checks for a workspace-local `scripts/terminal-wrapper.sh` first, then falls back to the extension-bundled copy.
131
+
132
+ ---
133
+
134
+ ## Text Injection
135
+
136
+ **Command**: `send`
137
+
138
+ Sends text into any terminal's input stream. This is equivalent to a human typing — the text appears at whatever input cursor is active (shell prompt, TUI input field, REPL prompt).
139
+
140
+ | Parameter | Type | Default | Description |
141
+ |---|---|---|---|
142
+ | `id` | string | required | Target terminal ID |
143
+ | `text` | string | required | Text to send |
144
+ | `newline` | boolean | `true` | Append Enter (newline) after the text |
145
+
146
+ **Single-line**: `{"cmd": "send", "id": "3", "text": "ls -la"}` — sends `ls -la\n` into the terminal.
147
+
148
+ **Raw keystrokes**: Set `newline: false` and send control characters directly:
149
+ - `\r` — Enter (carriage return, needed for some TUIs)
150
+ - `\x03` — Ctrl+C (interrupt)
151
+ - `\x04` — Ctrl+D (EOF)
152
+ - `\x1a` — Ctrl+Z (suspend)
153
+ - `\x1b` — Escape
154
+
155
+ **Sending to TUI sessions**: When the terminal is running Claude Code, vim, or any interactive program, `send` delivers text to that program's input handler. This is how AI orchestration works — you send a prompt as text into a Claude Code session, and Claude Code processes it as a user turn.
156
+
157
+ ---
158
+
159
+ ## Command Execution
160
+
161
+ **Command**: `exec`
162
+
163
+ Runs a shell command in a terminal and captures structured output. Unlike `send`, `exec` waits for the command to finish and returns the result.
164
+
165
+ | Parameter | Type | Default | Description |
166
+ |---|---|---|---|
167
+ | `id` | string | auto-created | Target terminal ID |
168
+ | `command` | string | required | Shell command to run |
169
+ | `timeoutMs` | number | `180000` | Max wait time in milliseconds |
170
+
171
+ **Returns**:
172
+ ```json
173
+ {
174
+ "ok": true,
175
+ "terminalId": "3",
176
+ "commandLine": "npm test",
177
+ "output": "PASS src/utils.test.ts\nTests: 5 passed\n",
178
+ "exitCode": 0
179
+ }
180
+ ```
181
+
182
+ ### How file-based capture works
183
+
184
+ Shell integration (`onDidEndTerminalShellExecution`) is unreliable in many terminal configurations. Claws uses a robust alternative:
185
+
186
+ 1. Wraps your command: `{ your_command; } > /tmp/claws-exec/abc123.out 2>&1; echo $? > /tmp/claws-exec/abc123.done`
187
+ 2. Sends the wrapped command via `send`
188
+ 3. Polls for the `.done` marker file
189
+ 4. Reads the output file and exit code
190
+ 5. Cleans up both temp files
191
+
192
+ This works in **every terminal type** — wrapped, unwrapped, with or without shell integration, bash, zsh, fish.
193
+
194
+ ### Auto-created exec terminal
195
+
196
+ If you call `exec` without specifying a terminal `id`, Claws automatically creates (or reuses) a terminal named `claws-work` for execution. This is the simplest path for scripts that just need to run commands.
197
+
198
+ ### Timeout handling
199
+
200
+ If the command doesn't produce a `.done` file within `timeoutMs`, `exec` returns an error with whatever partial output was captured. The command itself keeps running in the terminal — Claws doesn't kill it.
201
+
202
+ ---
203
+
204
+ ## Pty Log Reading
205
+
206
+ **Command**: `readLog`
207
+
208
+ Reads a wrapped terminal's pty log file with optional ANSI stripping.
209
+
210
+ | Parameter | Type | Default | Description |
211
+ |---|---|---|---|
212
+ | `id` | string | required | Terminal ID (must be wrapped) |
213
+ | `offset` | number | tail of file | Byte offset to start reading from |
214
+ | `limit` | number | `524288` | Max bytes to read (512KB) |
215
+ | `strip` | boolean | `true` | Strip ANSI escape sequences |
216
+
217
+ **Returns**:
218
+ ```json
219
+ {
220
+ "ok": true,
221
+ "bytes": "$ npm test\nPASS src/utils.test.ts\nTests: 5 passed\n$ ",
222
+ "offset": 4096,
223
+ "nextOffset": 4350,
224
+ "totalSize": 4350,
225
+ "truncated": false,
226
+ "logPath": "/project/.claws/terminals/claws-3.log"
227
+ }
228
+ ```
229
+
230
+ ### Incremental tailing
231
+
232
+ Use `offset` and `nextOffset` for efficient tailing without re-reading the entire file:
233
+
234
+ ```python
235
+ cursor = 0
236
+ while True:
237
+ resp = client._send({"cmd": "readLog", "id": term_id, "offset": cursor})
238
+ if resp["nextOffset"] > cursor:
239
+ print(resp["bytes"]) # new content
240
+ cursor = resp["nextOffset"]
241
+ time.sleep(1)
242
+ ```
243
+
244
+ ### ANSI stripping
245
+
246
+ When `strip: true` (default), Claws removes:
247
+ - CSI sequences: `\e[0m`, `\e[31;1m`, `\e[2J`, `\e[H`, etc.
248
+ - OSC sequences: `\e]0;title\a`, `\e]133;...`, etc.
249
+ - Control characters: `\x00`-`\x08`, `\x0b`-`\x1a`, `\x1c`-`\x1f`, `\x7f`
250
+
251
+ Set `strip: false` to get the raw pty output with all escape sequences intact — useful for terminal replay or debugging rendering issues.
252
+
253
+ ### Errors
254
+
255
+ - `"terminal X is not wrapped (no log path)"` — you called readLog on an unwrapped terminal. Create it with `wrapped: true`.
256
+ - `"read failed: ..."` — file I/O error (permissions, disk full, etc.)
257
+
258
+ ---
259
+
260
+ ## Event Streaming
261
+
262
+ **Command**: `poll`
263
+
264
+ Returns shell-integration command-completion events since a cursor position.
265
+
266
+ | Parameter | Type | Default | Description |
267
+ |---|---|---|---|
268
+ | `since` | number | `0` | Sequence cursor — return only events after this |
269
+
270
+ Each event contains:
271
+
272
+ | Field | Type | Description |
273
+ |---|---|---|
274
+ | `seq` | number | Monotonically increasing sequence number |
275
+ | `terminalId` | string | Which terminal this event came from |
276
+ | `terminalName` | string | Terminal display name at time of event |
277
+ | `commandLine` | string | The command that was executed |
278
+ | `output` | string | Captured stdout (up to `maxOutputBytes`) |
279
+ | `exitCode` | number | Process exit code |
280
+ | `startedAt` | number | Epoch ms when the command started |
281
+ | `endedAt` | number | Epoch ms when the command finished |
282
+
283
+ **Cursor-based pagination**: Save the `cursor` from each response and pass it as `since` in the next call. You'll only receive new events.
284
+
285
+ **Reliability note**: `poll` depends on VS Code's `onDidEndTerminalShellExecution` API, which requires shell integration to be active. It's unreliable in wrapped terminals (where shell integration often doesn't inject) and in TUI sessions. For those cases, use `readLog` instead.
286
+
287
+ **Ring buffer**: Claws stores the last `maxHistory` events (default 500). Older events are dropped. If you poll infrequently, you may miss events that were pushed out of the buffer.
288
+
289
+ ---
290
+
291
+ ## Terminal Profile
292
+
293
+ Claws registers a terminal profile so "Claws Wrapped Terminal" appears in the VS Code terminal dropdown (the arrow next to `+`).
294
+
295
+ When selected:
296
+ 1. Claws reserves a terminal ID and computes a log path
297
+ 2. A new terminal opens with `scripts/terminal-wrapper.sh` as the shell
298
+ 3. The `CLAWS_TERM_LOG` environment variable points to the log file
299
+ 4. `onDidOpenTerminal` fires, Claws associates the terminal with the reserved ID
300
+
301
+ The profile name includes the ID: "Claws Wrapped 5". This is used for internal matching and can be renamed by the user after creation without affecting Claws.
302
+
303
+ ---
304
+
305
+ ## Safety Gate
306
+
307
+ Before `send` injects text, Claws inspects the terminal's process tree to detect the foreground process:
308
+
309
+ 1. Reads the terminal's shell PID from VS Code's API
310
+ 2. Runs `pgrep -P <pid>` to find child processes
311
+ 3. Checks if the foreground child is a known shell (`bash`, `zsh`, `fish`, `sh`, `dash`, `ksh`)
312
+ 4. If it's not a shell (e.g., `claude`, `vim`, `less`, `top`, `python3`), emits a warning
313
+
314
+ **Default behavior**: warn and proceed. The send goes through with a `[warning: foreground is 'vim' (not a shell)]` prefix in the response. The caller decides whether to continue.
315
+
316
+ **Strict mode**: Pass `strict: true` in the send request. Claws will refuse the send and return an error instead of a warning.
317
+
318
+ **Why warn instead of block**: The primary use case for Claws is AI pair programming, where you intentionally send prompts into Claude Code's TUI input. Blocking that would defeat the purpose. The warning exists to catch accidental sends (e.g., a script meant to run a shell command but the terminal is in vim).
319
+
320
+ ---
321
+
322
+ ## Bracketed Paste
323
+
324
+ When `send` receives multi-line text (contains `\n`), it automatically wraps it in bracketed paste mode:
325
+
326
+ ```
327
+ \x1b[200~your multi-line text here\x1b[201~
328
+ ```
329
+
330
+ This tells the terminal to treat the entire block as a single paste operation. Without it, each `\n` in the text would be interpreted as a separate Enter keystroke, causing the shell to execute each line independently — breaking multi-line commands, heredocs, and prompt text.
331
+
332
+ After the bracketed paste block, Claws sends a separate `\r` (carriage return) to submit the pasted content.
333
+
334
+ **Disable with `paste: false`** if you want raw line-by-line behavior.
335
+
336
+ ---
337
+
338
+ ## Configuration Reference
339
+
340
+ All settings live under the `claws` namespace in VS Code's settings (`settings.json`).
341
+
342
+ ### `claws.socketPath`
343
+ - **Type**: string
344
+ - **Default**: `.claws/claws.sock`
345
+ - **Description**: Path to the Unix domain socket, relative to the workspace root. Claws creates the parent directory if it doesn't exist. The socket is created with `chmod 600` (owner-only access).
346
+
347
+ ### `claws.logDirectory`
348
+ - **Type**: string
349
+ - **Default**: `.claws/terminals`
350
+ - **Description**: Directory where wrapped terminal pty logs are stored. Each terminal gets its own file: `claws-<id>.log`. Add `.claws/` to your `.gitignore`.
351
+
352
+ ### `claws.defaultWrapped`
353
+ - **Type**: boolean
354
+ - **Default**: `false`
355
+ - **Description**: When `true`, every terminal created via the Claws API (not via VS Code's `+` button) is automatically wrapped with pty logging. Useful for AI orchestration setups where you always want readable terminals.
356
+
357
+ ### `claws.maxOutputBytes`
358
+ - **Type**: number
359
+ - **Default**: `262144` (256KB)
360
+ - **Description**: Maximum bytes of stdout captured per shell-integration command event. Larger outputs are truncated with a `[...truncated N bytes]` note. Does not affect `readLog` (which has its own `MAX_READLOG_BYTES` of 512KB).
361
+
362
+ ### `claws.maxHistory`
363
+ - **Type**: number
364
+ - **Default**: `500`
365
+ - **Description**: Maximum number of command-completion events retained in the ring buffer for `poll`. Older events are dropped FIFO. Increase if you poll infrequently and don't want to miss events.
366
+
367
+ ---
368
+
369
+ ## Socket Server Internals
370
+
371
+ ### Lifecycle
372
+
373
+ 1. **Activation**: Claws activates on `onStartupFinished`. It reads the workspace root, constructs the socket path, creates the directory, and starts a `net.createServer` listener.
374
+ 2. **Connection**: Each client gets its own socket connection. Multiple clients can connect simultaneously. Requests are handled independently.
375
+ 3. **Protocol**: Newline-delimited JSON. Each `\n`-terminated line is parsed as a JSON request, handled asynchronously, and the response is written back as a `\n`-terminated JSON line.
376
+ 4. **Deactivation**: On VS Code shutdown or extension deactivation, the server is closed and the socket file is unlinked.
377
+
378
+ ### Error handling
379
+
380
+ - Malformed JSON → `{"ok": false, "error": "bad json"}`
381
+ - Unknown command → `{"ok": false, "error": "unknown cmd: X"}`
382
+ - Missing terminal → `{"ok": false, "error": "unknown terminal id X"}`
383
+ - Handler exceptions → `{"ok": false, "error": "Error message"}`
384
+
385
+ ### Security
386
+
387
+ - Socket created with `chmod 600` — only the current user can connect
388
+ - No authentication on Unix socket (same-user access is the trust boundary)
389
+ - WebSocket transport (planned) will add token-based auth + TLS
390
+
391
+ ---
392
+
393
+ ## Cross-Device Control
394
+
395
+ **Status**: Planned for v0.3
396
+
397
+ ### Current workaround — SSH tunnel
398
+
399
+ You can control a remote VS Code instance today using an SSH tunnel:
400
+
401
+ ```bash
402
+ # On your local machine:
403
+ ssh -L 9999:/remote/workspace/.claws/claws.sock user@remote-host
404
+
405
+ # Then connect locally:
406
+ from claws import ClawsClient
407
+ client = ClawsClient("/tmp/claws-remote.sock") # forwarded socket
408
+ ```
409
+
410
+ ### Planned architecture
411
+
412
+ ```
413
+ Device A (controller) Device B (workspace)
414
+ ┌──────────────┐ ┌──────────────────┐
415
+ │ Python/Node │◄── WebSocket ─►│ Claws Extension │
416
+ │ client │ + TLS │ (VS Code) │
417
+ └──────────────┘ + token └──────────────────┘
418
+ ```
419
+
420
+ - **WebSocket transport**: opt-in alongside Unix socket
421
+ - **Token auth**: generated per-session, shown in the Claws output panel
422
+ - **TLS**: self-signed or ACME for encrypted connections
423
+ - **mDNS discovery**: auto-discover Claws-enabled VS Code instances on your LAN
424
+ - **Team config**: named devices with per-terminal read/write access control