pi-interactive-shell 0.3.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.
package/CHANGELOG.md ADDED
@@ -0,0 +1,63 @@
1
+ # Changelog
2
+
3
+ All notable changes to the `pi-interactive-shell` extension will be documented in this file.
4
+
5
+ ## [0.3.0] - 2026-01-17
6
+
7
+ ### Added
8
+ - Hands-free mode (`mode: "hands-free"`) for agent-driven monitoring with periodic tail updates.
9
+ - User can take over hands-free sessions by typing anything (except scroll keys).
10
+ - Configurable update settings for hands-free mode (defaults: on-quiet mode, 5s quiet threshold, 60s max interval, 1500 chars/update, 100KB total budget).
11
+ - **Input injection**: Send input to active hands-free sessions via `sessionId` + `input` parameters.
12
+ - Named key support: `up`, `down`, `enter`, `escape`, `ctrl+c`, etc.
13
+ - "Foreground subagents" terminology to distinguish from background subagents (the `subagent` tool).
14
+ - `sessionId` now available in the first update (before overlay opens) for immediate input injection.
15
+ - **Timeout**: Auto-kill process after N milliseconds via `timeout` parameter. Useful for TUI commands that don't exit cleanly (e.g., `pi --help`).
16
+ - **DSR handling**: Automatically responds to cursor position queries (`ESC[6n` / `ESC[?6n`) with actual xterm cursor position. Prevents TUI apps from hanging when querying cursor.
17
+ - **Enhanced key encoding**: Full modifier support (`ctrl+alt+x`, `shift+tab`, `c-m-delete`), hex bytes (`hex: ["0x1b"]`), bracketed paste mode (`paste: "text"`), and all F1-F12 keys.
18
+ - **Human-readable session IDs**: Sessions now get memorable names like `calm-reef`, `swift-cove` instead of `shell-1`, `shell-2`.
19
+ - **Process tree killing**: Kill entire process tree on termination, preventing orphan child processes.
20
+ - **Session name derivation**: Better display names in `/attach` list showing command summary.
21
+ - **Write queue**: Ordered writes to terminal emulator prevent race conditions.
22
+ - **Raw output streaming**: `getRawStream()` method for incremental output reading with `sinceLast` option.
23
+ - **Exit message in terminal**: Process exit status appended to terminal buffer when process exits.
24
+ - **EOL conversion**: Added `convertEol: true` to xterm for consistent line ending handling.
25
+ - **Incremental updates**: Hands-free updates now send only NEW output since last update, not full tail. Dramatically reduces context bloat.
26
+ - **Activity-driven updates (on-quiet mode)**: Default behavior now waits for 5s of output silence before emitting update. Perfect for agent-to-agent delegation where you want complete "thoughts" not fragments.
27
+ - **Update modes**: `handsFree.updateMode` can be `"on-quiet"` (default) or `"interval"`. On-quiet emits when output stops; interval emits on fixed schedule.
28
+ - **Context budget**: Total character budget (default: 100KB, configurable via `handsFree.maxTotalChars`). Updates stop including content when exhausted.
29
+ - **Dynamic settings**: Change update interval and quiet threshold mid-session via `settings: { updateInterval, quietThreshold }`.
30
+ - **Keypad keys**: Added `kp0`-`kp9`, `kp/`, `kp*`, `kp-`, `kp+`, `kp.`, `kpenter` for numpad input.
31
+ - **tmux-style key aliases**: Added `ppage`/`npage` (PageUp/PageDown), `ic`/`dc` (Insert/Delete), `bspace` (Backspace) for compatibility.
32
+
33
+ ### Changed
34
+ - ANSI stripping now uses Node.js built-in `stripVTControlCharacters` for cleaner, more robust output processing.
35
+
36
+ ### Fixed
37
+ - Double unregistration in hands-free session cleanup (now idempotent via `sessionUnregistered` flag).
38
+ - Potential double `done()` call when timeout fires and process exits simultaneously (added `finished` guard).
39
+ - ReattachOverlay: untracked setTimeout for initial countdown could fire after dispose (now tracked).
40
+ - Input type annotation missing `hex` and `paste` fields.
41
+ - Background session auto-cleanup could dispose session while user is viewing it via `/attach` (now cancels timer on reattach).
42
+ - On-quiet mode now flushes pending output before sending "exited" or "user-takeover" notifications (prevents data loss).
43
+ - Interval mode now also flushes pending output on user takeover (was missing the `|| updateMode === "interval"` check).
44
+ - Timeout in hands-free mode now flushes pending output and sends "exited" notification before returning.
45
+ - Exit handler now waits for writeQueue to drain, ensuring exit message is in rawOutput before notification is sent.
46
+
47
+ ### Removed
48
+ - `handsFree.updateLines` option (was defined but unused after switch to incremental char-based updates).
49
+
50
+ ## [0.2.0] - 2026-01-17
51
+
52
+ ### Added
53
+ - Interactive shell overlay tool `interactive_shell` for supervising interactive CLI agent sessions.
54
+ - Detach dialog (double `Esc`) with kill/background/cancel.
55
+ - Background session reattach command: `/attach`.
56
+ - Scroll support: `Shift+Up` / `Shift+Down`.
57
+ - Tail handoff preview included in tool result (bounded).
58
+ - Optional snapshot-to-file transcript handoff (disabled by default).
59
+
60
+ ### Fixed
61
+ - Prevented TUI width crashes by avoiding unbounded terminal escape rendering.
62
+ - Reduced flicker by sanitizing/redrawing in a controlled overlay viewport.
63
+
package/README.md ADDED
@@ -0,0 +1,173 @@
1
+ # Interactive Shell Extension
2
+
3
+ Run AI coding agents (Claude Code, Gemini CLI, Codex, Aider, etc.) as **foreground subagents** inside a pi TUI overlay. The user sees the agent working in real-time and can take over control at any time.
4
+
5
+ This is distinct from **background subagents** (the `subagent` tool) which run pi instances invisibly.
6
+
7
+ ## Foreground vs Background Subagents
8
+
9
+ | | Foreground (`interactive_shell`) | Background (`subagent`) |
10
+ |---|---|---|
11
+ | **Visibility** | User sees overlay | Hidden |
12
+ | **Agents** | Any CLI agent | Pi only |
13
+ | **Output** | Incremental updates | Full capture |
14
+ | **User control** | Can intervene | None |
15
+
16
+ ## Install
17
+
18
+ ```bash
19
+ npx pi-interactive-shell-install
20
+ ```
21
+
22
+ This installs the extension to `~/.pi/agent/extensions/interactive-shell/`, runs `npm install` for dependencies, and creates the skill symlink.
23
+
24
+ **Requirements:** `node-pty` requires build tools (Xcode Command Line Tools on macOS).
25
+
26
+ **Manual install:** If you prefer, clone/copy the files manually and run `npm install` in the extension directory.
27
+
28
+ ## Usage
29
+
30
+ ### Tool: `interactive_shell`
31
+
32
+ **Start a new session:**
33
+ - `command` (string, required): CLI agent command
34
+ - `cwd` (string): working directory
35
+ - `name` (string): session name (used in sessionId)
36
+ - `reason` (string): shown in overlay header (UI-only, not passed to subprocess)
37
+ - `mode` (string): `"interactive"` (default) or `"hands-free"`
38
+ - `timeout` (number): auto-kill after N milliseconds (for TUI commands that don't exit)
39
+ - `handsFree` (object): options for hands-free mode
40
+ - `updateMode` (string): `"on-quiet"` (default) or `"interval"`
41
+ - `updateInterval` (number): max ms between updates, fallback for on-quiet (default: 60000)
42
+ - `quietThreshold` (number): ms of silence before emitting update in on-quiet mode (default: 5000)
43
+ - `updateMaxChars` (number): max chars per update (default: 1500)
44
+ - `maxTotalChars` (number): total char budget for all updates (default: 100000)
45
+ - `handoffPreview` (object): tail preview in tool result
46
+ - `handoffSnapshot` (object): write transcript to file
47
+
48
+ **Send input to active session:**
49
+ - `sessionId` (string, required): session ID from hands-free updates
50
+ - `input` (string | object): input to send
51
+ - As string: raw text/keystrokes (e.g., `"/model\n"`)
52
+ - As object: `{ text?, keys?, hex?, paste? }`
53
+
54
+ **Change settings mid-session:**
55
+ - `sessionId` (string, required): session ID
56
+ - `settings` (object): `{ updateInterval?, quietThreshold? }`
57
+
58
+ ### Command: `/attach`
59
+
60
+ Reattach to background sessions:
61
+ ```
62
+ /attach
63
+ /attach <id>
64
+ ```
65
+
66
+ ## Modes
67
+
68
+ ### Interactive (default)
69
+
70
+ User supervises and controls the session directly.
71
+
72
+ ```typescript
73
+ interactive_shell({ command: 'pi "Review this code"' })
74
+ ```
75
+
76
+ ### Hands-Free (Foreground Subagent)
77
+
78
+ Agent monitors with periodic updates. User sees the overlay and can take over by typing. **Default to `pi`** unless user requests a different agent.
79
+
80
+ ```typescript
81
+ interactive_shell({
82
+ command: 'pi "Fix all lint errors in src/"',
83
+ mode: "hands-free",
84
+ reason: "Fixing lint errors"
85
+ })
86
+ ```
87
+
88
+ **Update modes:**
89
+ - `on-quiet` (default): Emit update after 5s of output silence. Perfect for agent-to-agent delegation.
90
+ - `interval`: Emit on fixed schedule (every 60s). Use when continuous output is expected.
91
+
92
+ **Context budget:**
93
+ - Updates include only NEW output since last update (incremental)
94
+ - Default: 1500 chars per update, 100KB total budget
95
+ - When budget exhausted, updates continue but without content
96
+
97
+ **Status updates (all include `sessionId`):**
98
+ - Initial update - sent immediately when session starts
99
+ - `status: "running"` - incremental output
100
+ - `status: "user-takeover"` - user typed something
101
+ - `status: "exited"` - process finished
102
+
103
+ ### Sending Input to Active Sessions
104
+
105
+ Use `sessionId` from updates to send input:
106
+
107
+ ```typescript
108
+ // Text input
109
+ interactive_shell({ sessionId: "calm-reef", input: "/help\n" })
110
+
111
+ // Named keys
112
+ interactive_shell({ sessionId: "calm-reef", input: { text: "/model", keys: ["enter"] } })
113
+
114
+ // Navigate menus
115
+ interactive_shell({ sessionId: "calm-reef", input: { keys: ["down", "down", "enter"] } })
116
+
117
+ // Hex bytes for raw escape sequences
118
+ interactive_shell({ sessionId: "calm-reef", input: { hex: ["0x1b", "0x5b", "0x41"] } })
119
+
120
+ // Bracketed paste (prevents auto-execution)
121
+ interactive_shell({ sessionId: "calm-reef", input: { paste: "multi\nline\ntext" } })
122
+ ```
123
+
124
+ **Named keys:** `up`, `down`, `left`, `right`, `enter`, `escape`, `tab`, `backspace`, `delete`, `home`, `end`, `pageup`, `pagedown`, `f1`-`f12`, `ctrl+c`, `ctrl+d`, etc.
125
+
126
+ **Keypad keys:** `kp0`-`kp9`, `kp/`, `kp*`, `kp-`, `kp+`, `kp.`, `kpenter`
127
+
128
+ **tmux-style aliases:** `ppage`/`npage` (PageUp/PageDown), `ic`/`dc` (Insert/Delete), `bspace` (Backspace), `btab` (Shift+Tab)
129
+
130
+ **Modifiers:** `ctrl+x`, `alt+x`, `shift+tab`, `ctrl+alt+delete` (or shorthand: `c-x`, `m-x`, `s-tab`)
131
+
132
+ ### Change Settings Mid-Session
133
+
134
+ ```typescript
135
+ interactive_shell({ sessionId: "calm-reef", settings: { updateInterval: 30000 } })
136
+ interactive_shell({ sessionId: "calm-reef", settings: { quietThreshold: 3000 } })
137
+ ```
138
+
139
+ ## Config
140
+
141
+ Global: `~/.pi/agent/interactive-shell.json`
142
+ Project: `<cwd>/.pi/interactive-shell.json`
143
+
144
+ ```json
145
+ {
146
+ "doubleEscapeThreshold": 300,
147
+ "exitAutoCloseDelay": 10,
148
+ "overlayWidthPercent": 95,
149
+ "overlayHeightPercent": 90,
150
+ "scrollbackLines": 5000,
151
+ "ansiReemit": true,
152
+ "handoffPreviewEnabled": true,
153
+ "handoffPreviewLines": 30,
154
+ "handoffPreviewMaxChars": 2000,
155
+ "handoffSnapshotEnabled": false,
156
+ "handoffSnapshotLines": 200,
157
+ "handoffSnapshotMaxChars": 12000,
158
+ "handsFreeUpdateMode": "on-quiet",
159
+ "handsFreeUpdateInterval": 60000,
160
+ "handsFreeQuietThreshold": 5000,
161
+ "handsFreeUpdateMaxChars": 1500,
162
+ "handsFreeMaxTotalChars": 100000
163
+ }
164
+ ```
165
+
166
+ ## Keys
167
+
168
+ | Key | Action |
169
+ |-----|--------|
170
+ | `Esc` twice | Detach dialog (kill/background/cancel) |
171
+ | `Shift+Up/Down` | Scroll (no takeover in hands-free) |
172
+ | `Ctrl+C` | Forwarded to subprocess |
173
+ | Any other key (hands-free) | Triggers user takeover |
package/SKILL.md ADDED
@@ -0,0 +1,368 @@
1
+ ---
2
+ name: interactive-shell
3
+ description: Cheat sheet + workflow for launching interactive coding-agent CLIs (Claude Code, Gemini CLI, Codex CLI, Cursor CLI, and pi itself) via the interactive_shell overlay. The overlay is for interactive supervision only - headless commands should use the bash tool instead.
4
+ ---
5
+
6
+ # Interactive Shell (Skill)
7
+
8
+ Last verified: 2026-01-17
9
+
10
+ ## Foreground vs Background Subagents
11
+
12
+ Pi has two ways to delegate work to other AI coding agents:
13
+
14
+ | | Foreground Subagents | Background Subagents |
15
+ |---|---|---|
16
+ | **Tool** | `interactive_shell` | `subagent` |
17
+ | **Visibility** | User sees overlay in real-time | Hidden from user |
18
+ | **Default agent** | `pi` (others if user requests) | Pi only |
19
+ | **Output** | Minimal (tail preview) | Full output captured |
20
+ | **User control** | Can take over anytime | No intervention |
21
+ | **Best for** | Long tasks needing supervision | Parallel tasks, structured delegation |
22
+
23
+ **Foreground subagents** run in an overlay where the user watches (and can intervene). Use `interactive_shell` with `mode: "hands-free"` to monitor while receiving periodic updates.
24
+
25
+ **Background subagents** run invisibly via the `subagent` tool. Pi-only, but captures full output and supports parallel execution.
26
+
27
+ ## When to Use Foreground Subagents
28
+
29
+ Use `interactive_shell` (foreground) when:
30
+ - The task is **long-running** and the user should see progress
31
+ - The user might want to **intervene or guide** the agent
32
+ - You want **hands-free monitoring** with periodic status updates
33
+ - You need a **different agent's capabilities** (only if user specifies)
34
+
35
+ Use `subagent` (background) when:
36
+ - You need **parallel execution** of multiple tasks
37
+ - You want **full output capture** for processing
38
+ - The task is **quick and deterministic**
39
+ - User doesn't need to see the work happening
40
+
41
+ ### Default Agent Choice
42
+
43
+ **Default to `pi`** for foreground subagents unless the user explicitly requests a different agent:
44
+
45
+ | User says | Agent to use |
46
+ |-----------|--------------|
47
+ | "Run this in hands-free" | `pi` |
48
+ | "Delegate this task" | `pi` |
49
+ | "Use Claude to review this" | `claude` |
50
+ | "Have Gemini analyze this" | `gemini` |
51
+ | "Run aider to fix this" | `aider` |
52
+
53
+ Pi is the default because it's already available, has the same capabilities, and maintains consistency. Only use Claude, Gemini, Codex, or other agents when the user specifically asks for them.
54
+
55
+ ## Foreground Subagent Modes
56
+
57
+ ### Interactive (default)
58
+ User has full control, types directly into the agent.
59
+ ```typescript
60
+ interactive_shell({ command: 'pi' })
61
+ ```
62
+
63
+ ### Interactive with Initial Prompt
64
+ Agent starts working immediately, user supervises.
65
+ ```typescript
66
+ interactive_shell({ command: 'pi "Review this codebase for security issues"' })
67
+ ```
68
+
69
+ ### Hands-Free (Foreground Subagent)
70
+ Agent works autonomously, you receive periodic updates, user can take over anytime.
71
+ ```typescript
72
+ interactive_shell({
73
+ command: 'pi "Fix all TypeScript errors in src/"',
74
+ mode: "hands-free",
75
+ reason: "Fixing TS errors"
76
+ })
77
+ ```
78
+
79
+ This is the primary pattern for **foreground subagents** - you delegate to pi (or another agent if user specifies) while monitoring progress.
80
+
81
+ ## Hands-Free Status Updates
82
+
83
+ When running in hands-free mode, `sessionId` is available immediately in the first update (before the overlay opens). Subsequent updates include:
84
+ - `status: "running"` - update with **incremental output** (only new content since last update)
85
+ - `status: "user-takeover"` - user typed something and took control
86
+ - `status: "exited"` - process exited (final update before tool returns)
87
+
88
+ Updates include budget tracking: `totalCharsSent` and `budgetExhausted` fields.
89
+
90
+ After takeover or exit, the tool continues blocking until the session closes.
91
+
92
+ ### Update Modes
93
+
94
+ **on-quiet (default)**: Updates emit after 5 seconds of output silence. Perfect for agent-to-agent delegation - you receive complete "thoughts" rather than fragments mid-stream.
95
+
96
+ **interval**: Updates emit on a fixed schedule (every 60s). Use when continuous output is expected.
97
+
98
+ ```typescript
99
+ // Default: on-quiet mode (recommended for agent delegation)
100
+ interactive_shell({
101
+ command: 'pi "Fix all TypeScript errors"',
102
+ mode: "hands-free"
103
+ })
104
+
105
+ // Force interval mode for continuous output
106
+ interactive_shell({
107
+ command: 'tail -f /var/log/app.log',
108
+ mode: "hands-free",
109
+ handsFree: { updateMode: "interval", updateInterval: 10000 }
110
+ })
111
+ ```
112
+
113
+ ### Context Budget
114
+
115
+ Updates have a **total character budget** (default: 100KB) to prevent overwhelming your context window:
116
+ - Each update includes only NEW output since the last update (not full tail)
117
+ - Default: 1500 chars max per update, 100KB total budget
118
+ - When budget is exhausted, updates continue but without content (status-only)
119
+ - Configure via `handsFree.maxTotalChars`
120
+
121
+ ```typescript
122
+ // Custom budget for a long task
123
+ interactive_shell({
124
+ command: 'pi "Refactor entire codebase"',
125
+ mode: "hands-free",
126
+ handsFree: { maxTotalChars: 200000 } // 200KB budget
127
+ })
128
+ ```
129
+
130
+ ## Sending Input to Active Sessions
131
+
132
+ Use the `sessionId` from updates to send input to a running hands-free session:
133
+
134
+ ### Basic Input
135
+ ```typescript
136
+ // Send text
137
+ interactive_shell({ sessionId: "shell-1", input: "/help\n" })
138
+
139
+ // Send with named keys
140
+ interactive_shell({ sessionId: "shell-1", input: { text: "/model", keys: ["enter"] } })
141
+
142
+ // Navigate menus
143
+ interactive_shell({ sessionId: "shell-1", input: { keys: ["down", "down", "enter"] } })
144
+
145
+ // Interrupt
146
+ interactive_shell({ sessionId: "shell-1", input: { keys: ["ctrl+c"] } })
147
+ ```
148
+
149
+ ### Named Keys
150
+ | Key | Description |
151
+ |-----|-------------|
152
+ | `up`, `down`, `left`, `right` | Arrow keys |
153
+ | `enter`, `return` | Enter/Return |
154
+ | `escape`, `esc` | Escape |
155
+ | `tab`, `shift+tab` (or `btab`) | Tab / Back-tab |
156
+ | `backspace`, `bspace` | Backspace |
157
+ | `delete`, `del`, `dc` | Delete |
158
+ | `insert`, `ic` | Insert |
159
+ | `home`, `end` | Home/End |
160
+ | `pageup`, `pgup`, `ppage` | Page Up |
161
+ | `pagedown`, `pgdn`, `npage` | Page Down |
162
+ | `f1`-`f12` | Function keys |
163
+ | `kp0`-`kp9`, `kp/`, `kp*`, `kp-`, `kp+`, `kp.`, `kpenter` | Keypad keys |
164
+ | `ctrl+c`, `ctrl+d`, `ctrl+z` | Control sequences |
165
+ | `ctrl+a` through `ctrl+z` | All control keys |
166
+
167
+ Note: `ic`/`dc`, `ppage`/`npage`, `bspace` are tmux-style aliases for compatibility.
168
+
169
+ ### Modifier Combinations
170
+ Supports `ctrl+`, `alt+`, `shift+` prefixes (or shorthand `c-`, `m-`, `s-`):
171
+ ```typescript
172
+ // Cancel
173
+ { keys: ["ctrl+c"] }
174
+
175
+ // Alt+Tab
176
+ { keys: ["alt+tab"] }
177
+
178
+ // Ctrl+Alt+Delete
179
+ { keys: ["ctrl+alt+delete"] }
180
+
181
+ // Shorthand syntax
182
+ { keys: ["c-c", "m-x", "s-tab"] }
183
+ ```
184
+
185
+ ### Hex Bytes (Advanced)
186
+ Send raw escape sequences:
187
+ ```typescript
188
+ { hex: ["0x1b", "0x5b", "0x41"] } // ESC[A (up arrow)
189
+ ```
190
+
191
+ ### Bracketed Paste
192
+ Paste multiline text without triggering autocompletion/execution:
193
+ ```typescript
194
+ { paste: "function foo() {\n return 42;\n}" }
195
+ ```
196
+
197
+ ### Model Selection Example
198
+ ```typescript
199
+ // Step 1: Open model selector
200
+ interactive_shell({ sessionId: "shell-1", input: { text: "/model", keys: ["enter"] } })
201
+
202
+ // Step 2: Filter and select (after ~500ms delay)
203
+ interactive_shell({ sessionId: "shell-1", input: { text: "sonnet", keys: ["enter"] } })
204
+
205
+ // Or navigate with arrows:
206
+ interactive_shell({ sessionId: "shell-1", input: { keys: ["down", "down", "down", "enter"] } })
207
+ ```
208
+
209
+ ### Context Compaction
210
+ ```typescript
211
+ interactive_shell({ sessionId: "shell-1", input: { text: "/compact", keys: ["enter"] } })
212
+ ```
213
+
214
+ ### Changing Update Settings
215
+ Adjust timing during a session:
216
+ ```typescript
217
+ // Change max interval (fallback for on-quiet mode)
218
+ interactive_shell({ sessionId: "calm-reef", settings: { updateInterval: 120000 } })
219
+
220
+ // Change quiet threshold (how long to wait after output stops)
221
+ interactive_shell({ sessionId: "calm-reef", settings: { quietThreshold: 3000 } })
222
+
223
+ // Both at once
224
+ interactive_shell({ sessionId: "calm-reef", settings: { updateInterval: 30000, quietThreshold: 2000 } })
225
+ ```
226
+
227
+ ## CLI Cheat Sheet
228
+
229
+ ### Claude Code (`claude`)
230
+
231
+ | Mode | Command |
232
+ |------|---------|
233
+ | Interactive (idle) | `claude` |
234
+ | Interactive (prompted) | `claude "Explain this project"` |
235
+ | Headless (use bash, not overlay) | `claude -p "Explain this function"` |
236
+
237
+ ### Gemini CLI (`gemini`)
238
+
239
+ | Mode | Command |
240
+ |------|---------|
241
+ | Interactive (idle) | `gemini` |
242
+ | Interactive (prompted) | `gemini -i "Explain this codebase"` |
243
+ | Headless (use bash, not overlay) | `gemini -p "What is fine tuning?"` |
244
+
245
+ ### Codex CLI (`codex`)
246
+
247
+ | Mode | Command |
248
+ |------|---------|
249
+ | Interactive (idle) | `codex` |
250
+ | Interactive (prompted) | `codex "Explain this codebase"` |
251
+ | Headless (use bash, not overlay) | `codex exec "summarize the repo"` |
252
+
253
+ ### Cursor CLI (`cursor-agent`)
254
+
255
+ | Mode | Command |
256
+ |------|---------|
257
+ | Interactive (idle) | `cursor-agent` |
258
+ | Interactive (prompted) | `cursor-agent "review this repo"` |
259
+ | Headless (use bash, not overlay) | `cursor-agent -p "find issues" --output-format text` |
260
+
261
+ ### Pi (`pi`)
262
+
263
+ | Mode | Command |
264
+ |------|---------|
265
+ | Interactive (idle) | `pi` |
266
+ | Interactive (prompted) | `pi "List all .ts files"` |
267
+ | Headless (use bash, not overlay) | `pi -p "List all .ts files"` |
268
+
269
+ Note: Delegating pi to pi is recursive - usually prefer `subagent` for pi-to-pi delegation.
270
+
271
+ ## Prompt Packaging Rules
272
+
273
+ The `reason` parameter is **UI-only** - it's shown in the overlay header but NOT passed to the subprocess.
274
+
275
+ To give the agent an initial prompt, embed it in the `command`:
276
+ ```typescript
277
+ // WRONG - agent starts idle, reason is just UI text
278
+ interactive_shell({ command: 'claude', reason: 'Review the codebase' })
279
+
280
+ // RIGHT - agent receives the prompt
281
+ interactive_shell({ command: 'claude "Review the codebase"', reason: 'Code review' })
282
+ ```
283
+
284
+ ## Handoff Options
285
+
286
+ ### Tail Preview (default)
287
+ Last 30 lines included in tool result. Good for seeing errors/final status.
288
+
289
+ ### Snapshot to File
290
+ Write full transcript to `~/.pi/agent/cache/interactive-shell/snapshot-*.log`:
291
+ ```typescript
292
+ interactive_shell({
293
+ command: 'claude "Fix bugs"',
294
+ handoffSnapshot: { enabled: true, lines: 200 }
295
+ })
296
+ ```
297
+
298
+ ### Artifact Handoff (recommended for complex tasks)
299
+ Instruct the delegated agent to write a handoff file:
300
+ ```
301
+ Write your findings to .pi/delegation/claude-handoff.md including:
302
+ - What you did
303
+ - Files changed
304
+ - Any errors
305
+ - Next steps for the main agent
306
+ ```
307
+
308
+ ## Safe TUI Capture
309
+
310
+ **Never run TUI agents via bash** - they hang even with `--help`. Use `interactive_shell` with `timeout` instead:
311
+
312
+ ```typescript
313
+ interactive_shell({
314
+ command: "pi --help",
315
+ mode: "hands-free",
316
+ timeout: 5000 // Auto-kill after 5 seconds
317
+ })
318
+ ```
319
+
320
+ The process is killed after timeout and captured output is returned in the handoff preview. This is useful for:
321
+ - Getting CLI help from TUI applications
322
+ - Capturing output from commands that don't exit cleanly
323
+ - Any TUI command where you need quick output without user interaction
324
+
325
+ For pi CLI documentation, you can also read directly: `/opt/homebrew/lib/node_modules/@mariozechner/pi-coding-agent/README.md`
326
+
327
+ ## Quick Reference
328
+
329
+ **Start foreground subagent (hands-free, default to pi):**
330
+ ```typescript
331
+ interactive_shell({
332
+ command: 'pi "Implement the feature described in SPEC.md"',
333
+ mode: "hands-free",
334
+ reason: "Implementing feature"
335
+ })
336
+ // Returns sessionId in updates, e.g., "shell-1"
337
+ ```
338
+
339
+ **Send input to active session:**
340
+ ```typescript
341
+ // Text with enter
342
+ interactive_shell({ sessionId: "calm-reef", input: "/compact\n" })
343
+
344
+ // Named keys
345
+ interactive_shell({ sessionId: "calm-reef", input: { text: "/model", keys: ["enter"] } })
346
+
347
+ // Menu navigation
348
+ interactive_shell({ sessionId: "calm-reef", input: { keys: ["down", "down", "enter"] } })
349
+ ```
350
+
351
+ **Change update frequency:**
352
+ ```typescript
353
+ interactive_shell({ sessionId: "calm-reef", settings: { updateInterval: 60000 } })
354
+ ```
355
+
356
+ **Foreground subagent (user requested different agent):**
357
+ ```typescript
358
+ interactive_shell({
359
+ command: 'claude "Review this code for security issues"',
360
+ mode: "hands-free",
361
+ reason: "Security review with Claude"
362
+ })
363
+ ```
364
+
365
+ **Background subagent:**
366
+ ```typescript
367
+ subagent({ agent: "scout", task: "Find all TODO comments" })
368
+ ```