An extension for Pi coding agent that lets Pi autonomously run interactive CLIs in an observable TUI overlay. Pi controls the subprocess while you watch - take over anytime.
pi-interactive-shell-extension.mp4
interactive_shell({ command: 'vim config.yaml' })Some tasks need interactive CLIs - editors, REPLs, database shells, long-running processes. Pi can launch them in an overlay where:
- User watches - See exactly what's happening in real-time
- User takes over - Type anything to gain control
- Agent monitors - Query status, send input, decide when done
Works with any CLI: vim, htop, psql, ssh, docker logs -f, npm run dev, git rebase -i, etc.
npx pi-interactive-shellInstalls to ~/.pi/agent/extensions/interactive-shell/.
The interactive-shell skill is automatically symlinked to ~/.pi/agent/skills/interactive-shell/.
Requires: Node.js, build tools for node-pty (Xcode CLI tools on macOS).
User controls the session directly:
interactive_shell({ command: 'vim package.json' })
interactive_shell({ command: 'psql -d mydb' })
interactive_shell({ command: 'ssh user@server' })Agent monitors while user watches. Returns immediately with sessionId:
// Start a long-running process
interactive_shell({
command: 'npm run dev',
mode: "hands-free",
reason: "Dev server"
})
// → { sessionId: "calm-reef", status: "running" }
// Query status (rate-limited to 60s)
interactive_shell({ sessionId: "calm-reef" })
// → { status: "running", output: "...", runtime: 45000 }
// Send input if needed
interactive_shell({ sessionId: "calm-reef", inputKeys: ["ctrl+c"] })
// Kill when done
interactive_shell({ sessionId: "calm-reef", kill: true })User sees the overlay in real-time. Type anything to take over control.
Capture output from TUI apps that don't exit cleanly:
interactive_shell({
command: "htop",
mode: "hands-free",
timeout: 3000 // Kill after 3s, return captured output
})For fire-and-forget single-task delegations, enable auto-exit to kill the session after 5s of output silence:
interactive_shell({
command: 'cursor-agent -f "Fix the bug in auth.ts"',
mode: "hands-free",
handsFree: { autoExitOnQuiet: true }
})For multi-turn sessions where you need back-and-forth interaction, leave it disabled (default) and use kill: true when done.
// Text
interactive_shell({ sessionId: "calm-reef", input: "SELECT * FROM users;\n" })
// Named keys
interactive_shell({ sessionId: "calm-reef", inputKeys: ["ctrl+c"] })
interactive_shell({ sessionId: "calm-reef", inputKeys: ["down", "down", "enter"] })
// Bracketed paste (multiline without execution)
interactive_shell({ sessionId: "calm-reef", inputPaste: "line1\nline2\nline3" })
// Hex bytes (raw escape sequences)
interactive_shell({ sessionId: "calm-reef", inputHex: ["0x1b", "0x5b", "0x41"] })
// Combine text with keys
interactive_shell({ sessionId: "calm-reef", input: "y", inputKeys: ["enter"] })// Default: 20 lines, 5KB
interactive_shell({ sessionId: "calm-reef" })
// More lines (max: 200)
interactive_shell({ sessionId: "calm-reef", outputLines: 100 })
// Incremental pagination (server tracks position)
interactive_shell({ sessionId: "calm-reef", outputLines: 50, incremental: true })
// Drain mode (raw stream since last query)
interactive_shell({ sessionId: "calm-reef", drain: true })- Ctrl+Q → "Run in background"
/attachor/attach <id>to reattach
| Key | Action |
|---|---|
| Ctrl+Q | Detach dialog |
| Shift+Up/Down | Scroll history |
| Any key (hands-free) | Take over control |
Configuration files (project overrides global):
- Global:
~/.pi/agent/interactive-shell.json - Project:
.pi/interactive-shell.json
{
"overlayWidthPercent": 95,
"overlayHeightPercent": 45,
"scrollbackLines": 5000,
"exitAutoCloseDelay": 10,
"minQueryIntervalSeconds": 60,
"handsFreeUpdateMode": "on-quiet",
"handsFreeUpdateInterval": 60000,
"handsFreeQuietThreshold": 5000,
"handsFreeUpdateMaxChars": 1500,
"handsFreeMaxTotalChars": 100000,
"handoffPreviewEnabled": true,
"handoffPreviewLines": 30,
"handoffPreviewMaxChars": 2000,
"handoffSnapshotEnabled": false,
"ansiReemit": true
}| Setting | Default | Description |
|---|---|---|
overlayWidthPercent |
95 | Overlay width (10-100%) |
overlayHeightPercent |
45 | Overlay height (20-90%) |
scrollbackLines |
5000 | Terminal scrollback buffer |
exitAutoCloseDelay |
10 | Seconds before auto-close after exit |
minQueryIntervalSeconds |
60 | Rate limit between agent queries |
handsFreeUpdateMode |
"on-quiet" | "on-quiet" or "interval" |
handsFreeQuietThreshold |
5000 | Silence duration before update (ms) |
handsFreeUpdateInterval |
60000 | Max interval between updates (ms) |
handsFreeUpdateMaxChars |
1500 | Max chars per update |
handsFreeMaxTotalChars |
100000 | Total char budget for updates |
handoffPreviewEnabled |
true | Include tail in tool result |
handoffSnapshotEnabled |
false | Write transcript on detach/exit |
ansiReemit |
true | Preserve ANSI colors in output |
interactive_shell → node-pty → subprocess
↓
xterm-headless (terminal emulation)
↓
TUI overlay (pi rendering)
Full PTY. The subprocess thinks it's in a real terminal.
For orchestrating multi-agent chains (scout → planner → worker → reviewer) with file-based handoff and auto-continue support, see:
pi-foreground-chains - A separate skill that builds on interactive-shell for complex agent workflows.
- macOS tested, Linux experimental
- 60s rate limit between queries (configurable)
- Some TUI apps may have rendering quirks