pi-interactive-shell 0.4.3 → 0.4.4
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/README.md +109 -120
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,17 +1,31 @@
|
|
|
1
|
-
# Pi Interactive Shell
|
|
1
|
+
# Pi Interactive Shell
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Pi can run any interactive CLI in a TUI overlay - including other AI agents. Drive Claude, Gemini, Codex, Cursor directly from Pi. Watch it work, take over anytime. Real PTY, full terminal emulation, no tmux needed.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
```typescript
|
|
6
|
+
interactive_shell({ command: 'agent "fix all the bugs"', mode: "hands-free" })
|
|
7
|
+
// Returns immediately with sessionId
|
|
8
|
+
// User watches in overlay, you query for status
|
|
9
|
+
// Session auto-closes when agent finishes
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Why
|
|
13
|
+
|
|
14
|
+
AI agents delegating to other AI agents is powerful but messy:
|
|
15
|
+
|
|
16
|
+
- **Visibility** - What's the subagent doing? Is it stuck?
|
|
17
|
+
- **Control** - User needs to intervene. How?
|
|
18
|
+
- **Integration** - When does the parent agent check in?
|
|
19
|
+
|
|
20
|
+
Interactive Shell solves all three:
|
|
6
21
|
|
|
7
|
-
|
|
22
|
+
**Real-Time Overlay** - User sees the subprocess in a TUI overlay. Full terminal emulation via xterm-headless. ANSI colors, cursor movement, everything.
|
|
8
23
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
| **User control** | Can intervene | None |
|
|
24
|
+
**Seamless Takeover** - Type anything to take control. Scroll with Shift+Up/Down. Double-Escape to detach.
|
|
25
|
+
|
|
26
|
+
**Non-Blocking API** - Start a session, get a sessionId, query for status. Rate-limited to prevent spam. Auto-exits when output stops.
|
|
27
|
+
|
|
28
|
+
**Any CLI** - Not just AI agents. Run `htop`, `vim`, `psql`, `ssh` - anything interactive.
|
|
15
29
|
|
|
16
30
|
## Install
|
|
17
31
|
|
|
@@ -19,153 +33,111 @@ This is distinct from **background subagents** (the `subagent` tool) which run p
|
|
|
19
33
|
npx pi-interactive-shell
|
|
20
34
|
```
|
|
21
35
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
**Requirements:** `node-pty` requires build tools (Xcode Command Line Tools on macOS).
|
|
36
|
+
Installs to `~/.pi/agent/extensions/interactive-shell/`.
|
|
25
37
|
|
|
26
|
-
**
|
|
38
|
+
**Requires:** Node.js, build tools for `node-pty` (Xcode CLI tools on macOS).
|
|
27
39
|
|
|
28
|
-
##
|
|
40
|
+
## Quick Start
|
|
29
41
|
|
|
30
|
-
###
|
|
42
|
+
### Hands-Free (Agent-to-Agent)
|
|
31
43
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
|
44
|
+
```typescript
|
|
45
|
+
// Start - returns immediately
|
|
46
|
+
interactive_shell({
|
|
47
|
+
command: 'pi "Refactor the auth module"',
|
|
48
|
+
mode: "hands-free"
|
|
49
|
+
})
|
|
50
|
+
// → { sessionId: "calm-reef", status: "running" }
|
|
47
51
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
- As string: raw text/keystrokes (e.g., `"/model\n"`)
|
|
52
|
-
- As object: `{ text?, keys?, hex?, paste? }`
|
|
52
|
+
// Query status (rate-limited to 60s)
|
|
53
|
+
interactive_shell({ sessionId: "calm-reef" })
|
|
54
|
+
// → { status: "running", output: "...", runtime: 45000 }
|
|
53
55
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
- `settings` (object): `{ updateInterval?, quietThreshold? }`
|
|
56
|
+
// Get more output
|
|
57
|
+
interactive_shell({ sessionId: "calm-reef", outputLines: 100 })
|
|
57
58
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
- `outputMaxChars` (number): max chars to return (default: 5KB, max: 50KB)
|
|
62
|
-
- `kill` (boolean): kill the session and return final output
|
|
59
|
+
// Kill when done (or let autoExitOnQuiet handle it)
|
|
60
|
+
interactive_shell({ sessionId: "calm-reef", kill: true })
|
|
61
|
+
```
|
|
63
62
|
|
|
64
|
-
###
|
|
63
|
+
### Interactive (User Control)
|
|
65
64
|
|
|
66
|
-
|
|
65
|
+
```typescript
|
|
66
|
+
interactive_shell({ command: 'vim package.json' })
|
|
67
67
|
```
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
|
|
69
|
+
### Send Input
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
interactive_shell({ sessionId: "calm-reef", input: "/help\n" })
|
|
73
|
+
interactive_shell({ sessionId: "calm-reef", input: { keys: ["ctrl+c"] } })
|
|
74
|
+
interactive_shell({ sessionId: "calm-reef", input: { keys: ["down", "down", "enter"] } })
|
|
70
75
|
```
|
|
71
76
|
|
|
72
|
-
##
|
|
77
|
+
## CLI Reference
|
|
73
78
|
|
|
74
|
-
|
|
79
|
+
| Agent | Interactive | With Prompt | Headless (use bash) |
|
|
80
|
+
|-------|-------------|-------------|---------------------|
|
|
81
|
+
| `claude` | `claude` | `claude "prompt"` | `claude -p "prompt"` |
|
|
82
|
+
| `gemini` | `gemini` | `gemini -i "prompt"` | `gemini "prompt"` |
|
|
83
|
+
| `codex` | `codex` | `codex "prompt"` | `codex exec "prompt"` |
|
|
84
|
+
| `agent` | `agent` | `agent "prompt"` | `agent -p "prompt"` |
|
|
85
|
+
| `pi` | `pi` | `pi "prompt"` | `pi -p "prompt"` |
|
|
75
86
|
|
|
76
|
-
|
|
87
|
+
## Features
|
|
77
88
|
|
|
78
|
-
|
|
79
|
-
interactive_shell({ command: 'pi "Review this code"' })
|
|
80
|
-
```
|
|
89
|
+
### Auto-Exit on Quiet
|
|
81
90
|
|
|
82
|
-
|
|
91
|
+
Sessions auto-close after 5s of silence. Disable with `handsFree: { autoExitOnQuiet: false }`.
|
|
83
92
|
|
|
84
|
-
|
|
93
|
+
### Timeout for TUI Capture
|
|
85
94
|
|
|
86
95
|
```typescript
|
|
87
96
|
interactive_shell({
|
|
88
|
-
command:
|
|
97
|
+
command: "pi --help",
|
|
89
98
|
mode: "hands-free",
|
|
90
|
-
|
|
99
|
+
timeout: 5000 // Kill after 5s, return captured output
|
|
91
100
|
})
|
|
92
101
|
```
|
|
93
102
|
|
|
94
|
-
|
|
95
|
-
- `on-quiet` (default): Emit update after 5s of output silence. Perfect for agent-to-agent delegation.
|
|
96
|
-
- `interval`: Emit on fixed schedule (every 60s). Use when continuous output is expected.
|
|
97
|
-
|
|
98
|
-
**Context budget:**
|
|
99
|
-
- Updates include only NEW output since last update (incremental)
|
|
100
|
-
- Default: 1500 chars per update, 100KB total budget
|
|
101
|
-
- When budget exhausted, updates continue but without content
|
|
102
|
-
|
|
103
|
-
**Status updates (all include `sessionId`):**
|
|
104
|
-
- Initial update - sent immediately when session starts
|
|
105
|
-
- `status: "running"` - incremental output
|
|
106
|
-
- `status: "user-takeover"` - user typed something
|
|
107
|
-
- `status: "exited"` - process finished
|
|
108
|
-
|
|
109
|
-
### Sending Input to Active Sessions
|
|
110
|
-
|
|
111
|
-
Use `sessionId` from updates to send input:
|
|
103
|
+
### Configurable Output
|
|
112
104
|
|
|
113
105
|
```typescript
|
|
114
|
-
//
|
|
115
|
-
interactive_shell({ sessionId: "calm-reef"
|
|
106
|
+
// Default: 20 lines, 5KB
|
|
107
|
+
interactive_shell({ sessionId: "calm-reef" })
|
|
116
108
|
|
|
117
|
-
//
|
|
118
|
-
interactive_shell({ sessionId: "calm-reef",
|
|
109
|
+
// More lines (max: 200)
|
|
110
|
+
interactive_shell({ sessionId: "calm-reef", outputLines: 100 })
|
|
119
111
|
|
|
120
|
-
//
|
|
121
|
-
interactive_shell({ sessionId: "calm-reef",
|
|
122
|
-
|
|
123
|
-
// Hex bytes for raw escape sequences
|
|
124
|
-
interactive_shell({ sessionId: "calm-reef", input: { hex: ["0x1b", "0x5b", "0x41"] } })
|
|
125
|
-
|
|
126
|
-
// Bracketed paste (prevents auto-execution)
|
|
127
|
-
interactive_shell({ sessionId: "calm-reef", input: { paste: "multi\nline\ntext" } })
|
|
112
|
+
// More content (max: 50KB)
|
|
113
|
+
interactive_shell({ sessionId: "calm-reef", outputMaxChars: 30000 })
|
|
128
114
|
```
|
|
129
115
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
**Keypad keys:** `kp0`-`kp9`, `kp/`, `kp*`, `kp-`, `kp+`, `kp.`, `kpenter`
|
|
116
|
+
### Input Methods
|
|
133
117
|
|
|
134
|
-
|
|
118
|
+
| Method | Example |
|
|
119
|
+
|--------|---------|
|
|
120
|
+
| Text | `input: "/model\n"` |
|
|
121
|
+
| Keys | `input: { keys: ["enter", "ctrl+c"] }` |
|
|
122
|
+
| Hex | `input: { hex: ["0x1b", "0x5b", "0x41"] }` |
|
|
123
|
+
| Paste | `input: { paste: "multi\nline" }` |
|
|
135
124
|
|
|
136
|
-
|
|
125
|
+
### Background Sessions
|
|
137
126
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
```typescript
|
|
141
|
-
interactive_shell({ sessionId: "calm-reef", settings: { updateInterval: 30000 } })
|
|
142
|
-
interactive_shell({ sessionId: "calm-reef", settings: { quietThreshold: 3000 } })
|
|
143
|
-
```
|
|
127
|
+
1. Double-Escape → "Run in background"
|
|
128
|
+
2. `/attach` or `/attach <id>` to reattach
|
|
144
129
|
|
|
145
130
|
## Config
|
|
146
131
|
|
|
147
|
-
|
|
148
|
-
Project: `<cwd>/.pi/interactive-shell.json`
|
|
132
|
+
`~/.pi/agent/interactive-shell.json`
|
|
149
133
|
|
|
150
134
|
```json
|
|
151
135
|
{
|
|
152
|
-
"doubleEscapeThreshold": 300,
|
|
153
|
-
"exitAutoCloseDelay": 10,
|
|
154
|
-
"overlayWidthPercent": 95,
|
|
155
136
|
"overlayHeightPercent": 45,
|
|
137
|
+
"overlayWidthPercent": 95,
|
|
156
138
|
"scrollbackLines": 5000,
|
|
157
|
-
"
|
|
158
|
-
"
|
|
159
|
-
"handoffPreviewLines": 30,
|
|
160
|
-
"handoffPreviewMaxChars": 2000,
|
|
161
|
-
"handoffSnapshotEnabled": false,
|
|
162
|
-
"handoffSnapshotLines": 200,
|
|
163
|
-
"handoffSnapshotMaxChars": 12000,
|
|
164
|
-
"handsFreeUpdateMode": "on-quiet",
|
|
165
|
-
"handsFreeUpdateInterval": 60000,
|
|
166
|
-
"handsFreeQuietThreshold": 5000,
|
|
167
|
-
"handsFreeUpdateMaxChars": 1500,
|
|
168
|
-
"handsFreeMaxTotalChars": 100000
|
|
139
|
+
"minQueryIntervalSeconds": 60,
|
|
140
|
+
"handsFreeQuietThreshold": 5000
|
|
169
141
|
}
|
|
170
142
|
```
|
|
171
143
|
|
|
@@ -173,7 +145,24 @@ Project: `<cwd>/.pi/interactive-shell.json`
|
|
|
173
145
|
|
|
174
146
|
| Key | Action |
|
|
175
147
|
|-----|--------|
|
|
176
|
-
|
|
|
177
|
-
|
|
|
178
|
-
|
|
|
179
|
-
|
|
148
|
+
| Double-Escape | Detach dialog |
|
|
149
|
+
| Shift+Up/Down | Scroll history |
|
|
150
|
+
| Any key (hands-free) | Take over control |
|
|
151
|
+
|
|
152
|
+
## How It Works
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
interactive_shell → node-pty → subprocess
|
|
156
|
+
↓
|
|
157
|
+
xterm-headless (terminal emulation)
|
|
158
|
+
↓
|
|
159
|
+
TUI overlay (pi rendering)
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Full PTY. The subprocess thinks it's in a real terminal.
|
|
163
|
+
|
|
164
|
+
## Limitations
|
|
165
|
+
|
|
166
|
+
- macOS tested, Linux experimental
|
|
167
|
+
- 60s rate limit between queries (configurable)
|
|
168
|
+
- Some TUI apps may have rendering quirks
|