Skip to main content

interactive-shell

Run interactive CLIs and coding-agent TUIs (pi, Claude Code, Codex, Gemini, Cursor) through the interactive_shell tool, plus long or quiet commands that should wake you when they finish or print a match. Covers background dispatch, stream monitors for CI/PR gates and log watchers, user-visible overlays, sending input to sessions, and cleanup. Use bash for ordinary short commands.

Source facts

Repository
nicobailon/pi-interactive-shell
Last source activity
October 26, 2026 at 15:31
Detected SKILL.md language
English
Stars
602
Forks
57

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
6 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
interactive-shell
description
Run interactive CLIs and coding-agent TUIs (pi, Claude Code, Codex, Gemini, Cursor) through the interactive_shell tool, plus long or quiet commands that should wake you when they finish or print a match. Covers background dispatch, stream monitors for CI/PR gates and log watchers, user-visible overlays, sending input to sessions, and cleanup. Use bash for ordinary short commands.
# Interactive Shell `interactive_shell` runs a command in a PTY that Pi supervises. Every launch returns a `sessionId` at once. Pick the mode by who waits: ``` mode overlay how you hear back use for dispatch yes* one wake-up: tail (+ log if *) delegated agents, test suites, CI watches monitor no one wake-up per trigger match PR/CI gates, log watchers hands-free yes you query; wake-up on exit/takeover an agent you will steer interactive yes the user drives; you can send input user-driven TUIs, auth flows * background: true runs dispatch headless (the wake-up adds a full-output log path); the user can /attach to watch ``` ## If the tool is missing When `interactive_shell` is unavailable, call `enable_interactive_shell` first. The tool becomes callable on the next turn and stays active until Pi reloads or the session changes; reloaded, new, resumed, and forked sessions reset it to inactive. A CLI `--tools` allowlist must include both tools. ## Hot shapes ```js // Finite command, headless; the wake-up brings the tail and the path to the full output interactive_shell({ command: "npm test", cwd: "/abs/repo", mode: "dispatch", background: true, name: "unit-tests", timeout: 1800000, handsFree: { autoExitOnQuiet: false }, reason: "Run unit tests", }) // Gate or watcher: wake on matching lines ("/re/flags" or a plain regex string) interactive_shell({ command: "./scripts/gate --report /tmp/gate.txt", mode: "monitor", name: "pr42-gate", timeout: 2700000, monitor: { strategy: "stream", triggers: [ { id: "verdict", regex: "^(READY|BLOCKED|TIMEOUT|ERROR)\\b" }, { id: "fail", literal: "FAIL" }, ] }, }) // Delegate to a coding agent interactive_shell({ spawn: { agent: "pi", prompt: "Fix the failing tests in src/", worktree: true }, mode: "dispatch" }) interactive_shell({ command: 'claude "Review the diff on this branch"', mode: "dispatch", background: true }) // Live sessions interactive_shell({ sessionId: "calm-reef", outputLines: 50 }) // rendered screen; default 20 lines, 5KB interactive_shell({ sessionId: "calm-reef", input: "/compact", submit: true }) interactive_shell({ sessionId: "calm-reef", inputKeys: ["down", "down", "enter"] }) interactive_shell({ sessionId: "calm-reef", inputPaste: "multi\nline text" }) // bracketed paste interactive_shell({ sessionId: "calm-reef", kill: true }) interactive_shell({ listBackground: true }) interactive_shell({ dismissBackground: "unit-tests" }) // or true for all ``` `inputKeys` takes named keys (`up`, `enter`, `escape`, `tab`, `space`, `backspace`, `delete`, `home`, `end`, `pageup`, `pagedown`, `f1`–`f12`, `kp0`–`kp9`) or single characters, with `ctrl+`/`alt+`/`shift+` (or `c-`/`m-`/`s-`) prefixes. Unknown names are rejected with suggestions. One call can combine `input`, `inputPaste`, and `inputKeys`; they are sent as text, then paste, then keys. `monitor.strategy` is `stream` (match output lines), `poll-diff` (rerun `command` every `poll.intervalMs`, match changes), `file-watch` (watch `fileWatch.path`; omit `command`), or `semantic` (Jev, below). Read events or state with `{ monitorEvents: true, monitorSessionId }` or `monitorStatus: true`. More options: [references/monitors.md](references/monitors.md). ## Rules - **Wait for the wake-up.** After launching dispatch or monitor, end the turn. Don't poll, sleep, or query it. - **Quiet auto-close.** Dispatch stops supervising after ~8s without output (after a 15s grace) and tags the wake-up `completionReason: "auto-close-quiet"`. That is not a verdict: the command may still be running or may have failed. For anything that can go quiet (tests, builds, `gh run watch`), set `handsFree: { autoExitOnQuiet: false }` and a hard `timeout`. Monitor doesn't auto-close on quiet unless you set `autoExitOnQuiet: true`. - **Gate watchers.** For a provider-agnostic external gate watcher, use `mode: "monitor"` with a hard `timeout` and triggers on explicit end lines such as `ready`, `blocked`, and `stale-head`. The watcher must exit only after printing one. - **Prompt goes in the command.** `reason` is only overlay header text. `command: 'claude "Review the codebase"'` starts the agent working; `command: "claude", reason: "Review"` leaves it idle. - **Submitting.** For editor-based TUIs like pi, raw `input` only types text. It does not submit the prompt. Use `submit: true` or `inputKeys: ["enter"]`, not a trailing `\n`. - **No TUIs in bash.** Agent CLIs hang in bash, even for `--help`. Capture one with `interactive_shell({ command: "pi --help", mode: "hands-free", timeout: 5000 })`. Headless one-shots (`claude -p`, `codex exec`, `pi -p`) are fine in bash. - **Isolate unattended agents.** An agent you aren't watching in a repository gets `spawn: { worktree: true }` or its own `cwd`. A raw command runs in its `cwd` and can change that checkout's Git state. - **Pi by default.** Delegate to `pi` unless the user names Claude, Codex, Gemini, Cursor, or another CLI. - **Clean up.** Before finishing, kill or dismiss every session you started for a finite check, including ones the user backgrounded with Ctrl+B. Keep only long-lived work the user wants, such as dev servers or watchers. `kill` and `dismissBackground` cancel locally and attempt termination; subprocess exit is not confirmed. - **Versus `subagent`.** `interactive_shell` runs any CLI where the user can watch and take over. The `subagent` tool runs Pi children for parallel or structured delegation with captured results. - **Jev sends terminal text off the machine.** Semantic supervision is optional and off by default; it never takes the API key in tool args or project config. Read the Jev reference before using `monitor.semantic` or `semanticIncident`. ## Look up the rest Read the matching reference before using any parameter it names; those parameters work even when the tool schema omits them. - Hands-free supervision, takeover (Ctrl+G), transfer (Ctrl+T), snapshots, incremental reads, `attach`, interactive mode → [references/foreground.md](references/foreground.md) - Structured `spawn`, `/spawn`, custom agents, per-agent CLI flags → [references/agents.md](references/agents.md) - Recoverable selected output for a finite headless dispatch (`outputSelection`, `sourceId`) → [references/output-selection.md](references/output-selection.md) - Jev semantic monitoring, actions, diagnostics, incidents, and `launchPolicy` → [references/jev.md](references/jev.md)
View on GitHub