agent-sh 0.1.0 → 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/README.md +66 -576
- package/dist/acp-client.d.ts +24 -0
- package/dist/acp-client.js +168 -35
- package/dist/context-manager.d.ts +6 -4
- package/dist/context-manager.js +75 -44
- package/dist/event-bus.d.ts +29 -0
- package/dist/extension-loader.js +3 -14
- package/dist/extensions/shell-exec.d.ts +24 -0
- package/dist/extensions/shell-exec.js +188 -0
- package/dist/extensions/tui-renderer.d.ts +1 -1
- package/dist/extensions/tui-renderer.js +133 -28
- package/dist/index.js +195 -6
- package/dist/input-handler.d.ts +13 -3
- package/dist/input-handler.js +259 -127
- package/dist/mcp-server.d.ts +13 -0
- package/dist/mcp-server.js +234 -0
- package/dist/output-parser.d.ts +5 -26
- package/dist/output-parser.js +16 -78
- package/dist/settings.d.ts +33 -0
- package/dist/settings.js +43 -0
- package/dist/shell.d.ts +9 -4
- package/dist/shell.js +88 -10
- package/dist/types.d.ts +4 -0
- package/dist/utils/ansi.d.ts +4 -1
- package/dist/utils/ansi.js +60 -2
- package/dist/utils/line-editor.d.ts +59 -0
- package/dist/utils/line-editor.js +381 -0
- package/dist/utils/markdown.js +4 -4
- package/dist/utils/tool-display.d.ts +11 -0
- package/dist/utils/tool-display.js +92 -9
- package/examples/pi-agent-sh.ts +166 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# agent-sh
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/agent-sh)
|
|
4
|
+
[](https://github.com/guanyilun/agent-sh/blob/main/LICENSE)
|
|
5
|
+
|
|
3
6
|
Not a shell that lives in an agent — an agent that lives in a shell.
|
|
4
7
|
|
|
5
8
|
agent-sh is a real terminal first. Every keystroke goes to a real PTY. `cd`, pipes, vim, job control — they all just work. But type `>` at the start of a line, and you're talking to an AI agent that has full context of what you've been doing: your working directory, recent commands, their output.
|
|
@@ -31,222 +34,38 @@ The [Agent Client Protocol](https://agentclientprotocol.com/) decouples the shel
|
|
|
31
34
|
|
|
32
35
|
## Key Features
|
|
33
36
|
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
-
|
|
37
|
-
-
|
|
38
|
-
-
|
|
39
|
-
-
|
|
40
|
-
-
|
|
41
|
-
-
|
|
42
|
-
-
|
|
43
|
-
-
|
|
44
|
-
- **🎨 Themeable** — Semantic color palette, swappable via extensions
|
|
45
|
-
|
|
46
|
-
## Install
|
|
47
|
-
|
|
48
|
-
```bash
|
|
49
|
-
git clone https://github.com/guanyilun/agent-sh.git
|
|
50
|
-
cd agent-sh
|
|
51
|
-
npm install
|
|
52
|
-
npm run build
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
Requires Node.js 18+ and an ACP-compatible agent installed on your system.
|
|
56
|
-
|
|
57
|
-
## Running agent-sh
|
|
58
|
-
|
|
59
|
-
After building, you can run agent-sh in several ways:
|
|
60
|
-
|
|
61
|
-
```bash
|
|
62
|
-
# Start with the default agent (pi-acp) - RECOMMENDED
|
|
63
|
-
npm start
|
|
64
|
-
|
|
65
|
-
# Quick shortcuts
|
|
66
|
-
npm run pi # Start with pi-acp
|
|
67
|
-
npm run claude # Start with claude-agent-acp (Anthropic's official Claude agent)
|
|
68
|
-
|
|
69
|
-
# Using the built binary directly
|
|
70
|
-
node dist/index.js --agent <agent-name>
|
|
71
|
-
|
|
72
|
-
# Using npm script with custom agent
|
|
73
|
-
npm start -- --agent <agent-name>
|
|
74
|
-
|
|
75
|
-
# Using npx (if published to npm)
|
|
76
|
-
npx agent-sh --agent <agent-name>
|
|
77
|
-
|
|
78
|
-
# Make the built file executable and run directly
|
|
79
|
-
chmod +x dist/index.js
|
|
80
|
-
./dist/index.js --agent <agent-name>
|
|
81
|
-
|
|
82
|
-
# Using environment variable to set default agent
|
|
83
|
-
AGENT_SH_AGENT=claude-agent-acp npm start
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
### Install ACP-compatible agents
|
|
87
|
-
|
|
88
|
-
agent-sh requires an ACP-compatible agent. Here are some popular options:
|
|
89
|
-
|
|
90
|
-
| Agent | Install Command | Notes |
|
|
91
|
-
|-------|----------------|-------|
|
|
92
|
-
| **pi-acp** | `npm install -g pi-acp` | **Recommended default** - ACP adapter for pi coding agent |
|
|
93
|
-
| **claude-agent-acp** | `npm install -g @agentclientprotocol/claude-agent-acp` | Anthropic's official ACP Claude agent |
|
|
94
|
-
|
|
95
|
-
**⚠️ Important**: The `claude` CLI tool (Claude Code) does **not** support the ACP protocol. You must use `claude-agent-acp` or `pi-acp` with Anthropic models.
|
|
96
|
-
|
|
97
|
-
**Example: Installing pi-acp**
|
|
98
|
-
```bash
|
|
99
|
-
npm install -g pi-acp
|
|
100
|
-
pi-acp --help # Verify installation
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
## Usage
|
|
104
|
-
|
|
105
|
-
### Quick Start
|
|
106
|
-
|
|
107
|
-
```bash
|
|
108
|
-
# 1. Install required agents (if not already installed)
|
|
109
|
-
npm install -g pi-acp
|
|
110
|
-
npm install -g @agentclientprotocol/claude-agent-acp
|
|
111
|
-
|
|
112
|
-
# 2. Set required API keys
|
|
113
|
-
export ANTHROPIC_API_KEY="your-anthropic-api-key"
|
|
114
|
-
# Or for OpenAI models with pi-acp:
|
|
115
|
-
# export OPENAI_API_KEY="your-openai-api-key"
|
|
116
|
-
|
|
117
|
-
# 3. Start agent-sh
|
|
118
|
-
npm start
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
### Common Usage Patterns
|
|
122
|
-
|
|
123
|
-
```bash
|
|
124
|
-
# Start with the default agent (pi-acp)
|
|
125
|
-
npm start
|
|
126
|
-
# Shows: pi ● ❯ when entering agent mode
|
|
127
|
-
|
|
128
|
-
# Quick shortcuts
|
|
129
|
-
npm run pi # pi-acp
|
|
130
|
-
npm run claude # claude-agent-acp (Anthropic's official Claude agent)
|
|
131
|
-
|
|
132
|
-
# Start with a specific agent
|
|
133
|
-
npm start -- --agent pi-acp
|
|
134
|
-
|
|
135
|
-
# Pass arguments to the agent (including model)
|
|
136
|
-
npm start -- --agent claude-agent-acp --agent-args "--model claude-3-5-sonnet-20241022"
|
|
137
|
-
# Shows: claude-agent-acp (claude-3-5-sonnet-20241022) ● ❯ when entering agent mode
|
|
138
|
-
|
|
139
|
-
# Use pi-acp with Claude
|
|
140
|
-
npm start -- --agent pi-acp --agent-args "--provider anthropic --model claude-3-5-sonnet-20241022"
|
|
141
|
-
# Shows: pi (claude-3-5-sonnet-20241022) ● ❯
|
|
142
|
-
|
|
143
|
-
# Use pi-acp with OpenAI GPT-4
|
|
144
|
-
export OPENAI_API_KEY="your-openai-key"
|
|
145
|
-
npm start -- --agent pi-acp --agent-args "--provider openai --model gpt-4o"
|
|
146
|
-
# Shows: pi (gpt-4o) ● ❯
|
|
147
|
-
|
|
148
|
-
# Use a different shell
|
|
149
|
-
npm start -- --shell /bin/zsh
|
|
150
|
-
|
|
151
|
-
# Set default agent via environment variable
|
|
152
|
-
AGENT_SH_AGENT=claude-agent-acp npm start
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
### Common Claude Models
|
|
37
|
+
- **Instant Start** — Shell starts immediately, no waiting for agent connection
|
|
38
|
+
- **Smart Connection** — Agent connects asynchronously in the background
|
|
39
|
+
- **Auto-Wait** — Queries automatically wait for agent to finish connecting
|
|
40
|
+
- **Real-time Streaming** — Agent responses stream live with syntax highlighting
|
|
41
|
+
- **Zero Latency** — Direct PTY access, full terminal compatibility
|
|
42
|
+
- **Context Aware** — Agent sees your cwd, recent commands, and their output
|
|
43
|
+
- **Multiple Agents** — Easy switching between pi-acp, claude, and other ACP agents
|
|
44
|
+
- **Inline Diff Preview** — File writes show syntax-highlighted diffs inline (Ctrl+O to expand)
|
|
45
|
+
- **Thinking Display** — Toggle agent thinking/reasoning text with Ctrl+T
|
|
46
|
+
- **Themeable** — Semantic color palette, swappable via [extensions](docs/extensions.md)
|
|
156
47
|
|
|
157
|
-
|
|
158
|
-
- `claude-3-5-sonnet-20241022` (latest Sonnet)
|
|
159
|
-
- `claude-3-5-haiku-20241022` (latest Haiku)
|
|
160
|
-
- `claude-3-opus-20240229` (older Opus)
|
|
161
|
-
- `claude-3-sonnet-20240229` (older Sonnet)
|
|
48
|
+
## Quick Start
|
|
162
49
|
|
|
163
|
-
**Example with claude-agent-acp**:
|
|
164
50
|
```bash
|
|
165
|
-
|
|
166
|
-
npm
|
|
167
|
-
```
|
|
51
|
+
# 1. Install agent-sh and an ACP-compatible agent
|
|
52
|
+
npm install -g agent-sh pi-acp
|
|
168
53
|
|
|
169
|
-
|
|
170
|
-
```bash
|
|
54
|
+
# 2. Set API keys
|
|
171
55
|
export ANTHROPIC_API_KEY="your-key"
|
|
172
|
-
npm start -- --agent pi-acp --agent-args "--provider anthropic --model claude-3-5-sonnet-20241022"
|
|
173
|
-
```
|
|
174
56
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
agent-sh
|
|
178
|
-
|
|
179
|
-
```bash
|
|
180
|
-
# Set the default agent to use
|
|
181
|
-
export AGENT_SH_AGENT=pi-acp # Default is pi-acp
|
|
57
|
+
# 3. Start
|
|
58
|
+
agent-sh # default agent (pi-acp)
|
|
59
|
+
agent-sh --agent claude-agent-acp # use a different agent
|
|
182
60
|
```
|
|
183
61
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
Many ACP agents also require API keys. Set these before starting agent-sh:
|
|
187
|
-
|
|
188
|
-
#### pi-acp configuration
|
|
62
|
+
Requires Node.js 18+. Other ACP agents: `npm install -g @agentclientprotocol/claude-agent-acp`
|
|
189
63
|
|
|
190
|
-
|
|
64
|
+
> **Note**: The `claude` CLI tool (Claude Code) does **not** support ACP. Use `claude-agent-acp` or `pi-acp` with Anthropic models.
|
|
191
65
|
|
|
192
|
-
|
|
193
|
-
# Anthropic Claude
|
|
194
|
-
export ANTHROPIC_API_KEY="your-anthropic-key"
|
|
195
|
-
|
|
196
|
-
# OpenAI
|
|
197
|
-
export OPENAI_API_KEY="your-openai-key"
|
|
198
|
-
|
|
199
|
-
# Google Gemini
|
|
200
|
-
export GEMINI_API_KEY="your-gemini-key"
|
|
201
|
-
|
|
202
|
-
# Groq
|
|
203
|
-
export GROQ_API_KEY="your-groq-key"
|
|
204
|
-
|
|
205
|
-
# xAI (Grok)
|
|
206
|
-
export XAI_API_KEY="your-xai-key"
|
|
207
|
-
|
|
208
|
-
# OpenRouter
|
|
209
|
-
export OPENROUTER_API_KEY="your-openrouter-key"
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
You can also configure pi-acp by passing arguments:
|
|
213
|
-
|
|
214
|
-
```bash
|
|
215
|
-
# Use Claude 3.5 Sonnet with pi-acp
|
|
216
|
-
npm start -- --agent pi-acp --agent-args "--provider anthropic --model claude-3-5-sonnet-20241022"
|
|
217
|
-
# Shows: pi (claude-3-5-sonnet-20241022) ● ❯
|
|
66
|
+
See the [Usage Guide](docs/usage.md) for all options, model configuration, and environment variables.
|
|
218
67
|
|
|
219
|
-
|
|
220
|
-
export OPENAI_API_KEY="your-openai-key"
|
|
221
|
-
npm start -- --agent pi-acp --agent-args "--provider openai --model gpt-4o"
|
|
222
|
-
# Shows: pi (gpt-4o) ● ❯
|
|
223
|
-
|
|
224
|
-
# Enable thinking mode
|
|
225
|
-
npm start -- --agent pi-acp --agent-args "--thinking high"
|
|
226
|
-
|
|
227
|
-
# Limit to read-only tools
|
|
228
|
-
npm start -- --agent pi-acp --agent-args "--tools read,grep,find,ls"
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
**Model Display**: When you specify a model using `--model`, it will be displayed in parentheses next to the agent name when you enter agent mode. This helps you quickly identify which model you're using.
|
|
232
|
-
|
|
233
|
-
For more pi-acp options, run `pi --help` (pi-acp accepts the same arguments).
|
|
234
|
-
|
|
235
|
-
#### Other agent configurations
|
|
236
|
-
|
|
237
|
-
Refer to each agent's documentation for their specific environment variable requirements. Common patterns:
|
|
238
|
-
|
|
239
|
-
```bash
|
|
240
|
-
# claude-agent-acp (Anthropic's official Claude agent)
|
|
241
|
-
export ANTHROPIC_API_KEY="your-key"
|
|
242
|
-
|
|
243
|
-
# gemini-cli
|
|
244
|
-
export GOOGLE_API_KEY="your-key"
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
**Tip:** Add these to your `~/.zshrc` or `~/.bashrc` for persistent configuration.
|
|
248
|
-
|
|
249
|
-
### Input modes
|
|
68
|
+
## Input Modes
|
|
250
69
|
|
|
251
70
|
| Input | Behavior |
|
|
252
71
|
|---|---|
|
|
@@ -258,401 +77,72 @@ export GOOGLE_API_KEY="your-key"
|
|
|
258
77
|
| `Ctrl-C` | Standard signal to shell, or cancels active agent response |
|
|
259
78
|
| `Ctrl-O` | Expand/collapse truncated diff preview |
|
|
260
79
|
| `Ctrl-T` | Toggle thinking/reasoning text display |
|
|
80
|
+
| `Shift-Tab` | Cycle thinking level (off → minimal → low → medium → high → xhigh) |
|
|
261
81
|
| `Escape` | Exit agent input mode (when typing after `>`) |
|
|
262
82
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
**Agent Info Display**: When entering agent mode, you'll see the current agent name and model (if specified) next to the prompt, followed by a green dot (●) indicating the connection status. For example:
|
|
266
|
-
- `pi ● ❯` — pi agent without model specified
|
|
267
|
-
- `pi (gpt-4o) ● ❯` — pi agent with gpt-4o model
|
|
268
|
-
- `pi (claude-3-5-sonnet-20241022) ● ❯` — pi agent with Claude Sonnet model
|
|
269
|
-
- `claude-agent-acp (claude-3-5-sonnet-20241022) ● ❯` — Claude agent with Sonnet model
|
|
83
|
+
### Agent Input Keybindings
|
|
270
84
|
|
|
271
|
-
|
|
85
|
+
When typing after `>`, full readline-style keybindings are available:
|
|
272
86
|
|
|
273
|
-
|
|
|
87
|
+
| Key | Action |
|
|
274
88
|
|---|---|
|
|
275
|
-
|
|
|
276
|
-
|
|
|
277
|
-
|
|
|
278
|
-
|
|
|
279
|
-
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
-
|
|
288
|
-
-
|
|
289
|
-
- **Recall tool** — the agent can run `__shell_recall --search "query"` or `__shell_recall --expand 42` to retrieve full output of any past exchange
|
|
290
|
-
|
|
291
|
-
This means you can run a failing command, then type `> fix this` and the agent knows exactly what happened. For long outputs, the agent sees a truncated summary and can recall the full content on demand.
|
|
89
|
+
| `↑` / `↓` | Browse query history (persisted across sessions) |
|
|
90
|
+
| `Shift-Enter` | Insert newline (multiline input) |
|
|
91
|
+
| `Shift-Tab` | Cycle thinking level |
|
|
92
|
+
| `Ctrl-D` | Exit agent input mode (on empty line) |
|
|
93
|
+
| `Ctrl-A` / `Home` | Move to start of line |
|
|
94
|
+
| `Ctrl-E` / `End` | Move to end of line |
|
|
95
|
+
| `Ctrl-B` / `←` | Move back one character |
|
|
96
|
+
| `Ctrl-F` / `→` | Move forward one character |
|
|
97
|
+
| `Option-B` / `Option-←` | Move back one word |
|
|
98
|
+
| `Option-F` / `Option-→` | Move forward one word |
|
|
99
|
+
| `Ctrl-U` | Delete to start of line |
|
|
100
|
+
| `Ctrl-K` | Delete to end of line |
|
|
101
|
+
| `Ctrl-W` / `Option-Backspace` | Delete word backward |
|
|
102
|
+
| `Option-D` | Delete word forward |
|
|
292
103
|
|
|
293
|
-
|
|
104
|
+
### Thinking Level
|
|
294
105
|
|
|
295
|
-
agent
|
|
296
|
-
|
|
297
|
-
### Design philosophy: headless core + pluggable frontends
|
|
298
|
-
|
|
299
|
-
The core (`createCore()`) is a frontend-agnostic kernel — it wires up the EventBus, ContextManager, and AcpClient with zero knowledge of terminals, PTYs, or rendering. The interactive terminal (Shell + TUI + extensions) is one frontend built on top.
|
|
106
|
+
The agent prompt shows the current thinking level next to the model name:
|
|
300
107
|
|
|
301
108
|
```
|
|
302
|
-
|
|
303
|
-
│ EventBus — typed pub/sub + transform pipelines
|
|
304
|
-
│ ContextManager — exchange recording, context assembly
|
|
305
|
-
│ AcpClient — ACP protocol, terminal execution (yolo by default)
|
|
306
|
-
│
|
|
307
|
-
index.ts — interactive terminal frontend:
|
|
308
|
-
│ Shell — PTY lifecycle (delegates to InputHandler + OutputParser)
|
|
309
|
-
│
|
|
310
|
-
├── Built-in extensions:
|
|
311
|
-
│ tuiRenderer — markdown rendering, inline diffs, thinking display, spinner
|
|
312
|
-
│ slashCommands — /help, /clear, /copy, /compact, /quit
|
|
313
|
-
│ fileAutocomplete — @ file path completion
|
|
314
|
-
│ shellRecall — __shell_recall terminal interception
|
|
315
|
-
│
|
|
316
|
-
├── Shared utilities:
|
|
317
|
-
│ palette — semantic color system (accent, success, warning, error, muted)
|
|
318
|
-
│ diff-renderer — syntax-highlighted diffs (split/unified/summary)
|
|
319
|
-
│ box-frame — bordered TUI panels
|
|
320
|
-
│ tool-display — width-adaptive tool call rendering
|
|
321
|
-
│
|
|
322
|
-
└── User extensions (opt-in, loaded from -e flag / settings.json / extensions dir):
|
|
323
|
-
e.g. interactive-prompts, solarized-theme
|
|
109
|
+
pi (claude-3.5-sonnet) [medium] ● ❯
|
|
324
110
|
```
|
|
325
111
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
**The core works without any frontend.** This enables:
|
|
112
|
+
Press **Shift-Tab** in agent input mode to cycle through levels. The levels are advertised by the agent via ACP session modes — different agents may offer different options. The spinner label reflects the mode: "Thinking" when thinking is enabled, "Working" when it's off.
|
|
329
113
|
|
|
330
|
-
|
|
331
|
-
- **Headless mode** — CI, scripting, embedding — no terminal needed
|
|
332
|
-
- **Alternative renderers** — web UI, logging backend, minimal TUI
|
|
333
|
-
- **Custom features** — add commands, autocomplete providers, tool interceptors by writing an extension
|
|
114
|
+
### Slash Commands
|
|
334
115
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
| Method | When |
|
|
116
|
+
| Command | Description |
|
|
338
117
|
|---|---|
|
|
339
|
-
| `
|
|
340
|
-
| `
|
|
341
|
-
| `
|
|
342
|
-
| `
|
|
343
|
-
|
|
344
|
-
### We handle from the agent
|
|
118
|
+
| `/help` | Show available commands |
|
|
119
|
+
| `/clear` | Start a new agent session |
|
|
120
|
+
| `/copy` | Copy last agent response to clipboard |
|
|
121
|
+
| `/compact` | Ask agent to summarize the conversation |
|
|
122
|
+
| `/quit` | Exit agent-sh |
|
|
345
123
|
|
|
346
|
-
|
|
347
|
-
|---|---|
|
|
348
|
-
| `terminal/create` | Execute command in an isolated child process |
|
|
349
|
-
| `terminal/output` | Return captured output for a terminal ID |
|
|
350
|
-
| `terminal/wait_for_exit` | Await command completion, return exit code |
|
|
351
|
-
| `terminal/kill` | Send signal to running command |
|
|
352
|
-
| `terminal/release` | Cleanup terminal session |
|
|
353
|
-
| `fs/read_text_file` | Read file from disk, return content |
|
|
354
|
-
| `fs/write_text_file` | Write file to disk |
|
|
355
|
-
| `session/request_permission` | Prompt user for y/n/allow-all confirmation |
|
|
356
|
-
|
|
357
|
-
### We render from the agent
|
|
358
|
-
|
|
359
|
-
| Update type | What we render |
|
|
360
|
-
|---|---|
|
|
361
|
-
| `agent_message_chunk` | Real-time streaming markdown with syntax highlighting in a bordered box |
|
|
362
|
-
| `agent_thought_chunk` | Thinking spinner (default), or streaming text when toggled on with Ctrl+T |
|
|
363
|
-
| `tool_call` | Yellow header showing what the agent is invoking |
|
|
364
|
-
| `tool_call_update` | Status indicator (✓ or ✗ with exit code) |
|
|
365
|
-
| `file_write` | Inline diff preview in bordered box (Ctrl+O to expand/collapse) |
|
|
124
|
+
## Configuration
|
|
366
125
|
|
|
367
|
-
|
|
126
|
+
agent-sh stores settings and history in `~/.agent-sh/`. Behavior is configurable via `~/.agent-sh/settings.json` — context window size, truncation thresholds, display limits, and more. All fields are optional with sensible defaults.
|
|
368
127
|
|
|
369
|
-
|
|
370
|
-
agent-sh/
|
|
371
|
-
├── src/
|
|
372
|
-
│ ├── index.ts # Interactive terminal entry point (CLI args, Shell, extensions)
|
|
373
|
-
│ ├── core.ts # createCore() — frontend-agnostic kernel, library entry point
|
|
374
|
-
│ ├── event-bus.ts # Typed EventBus: emit/on, emitPipe, emitPipeAsync
|
|
375
|
-
│ ├── shell.ts # PTY lifecycle + wiring (InputHandler + OutputParser)
|
|
376
|
-
│ ├── input-handler.ts # Keyboard input, agent mode, bus-driven autocomplete
|
|
377
|
-
│ ├── output-parser.ts # OSC parsing, command boundary detection
|
|
378
|
-
│ ├── acp-client.ts # ACP protocol, terminal execution, session management
|
|
379
|
-
│ ├── context-manager.ts # Exchange log, context assembly, recall API
|
|
380
|
-
│ ├── extension-loader.ts # Extension loading (-e, settings.json, extensions dir)
|
|
381
|
-
│ ├── executor.ts # Isolated child process execution
|
|
382
|
-
│ ├── types.ts # Shared type definitions
|
|
383
|
-
│ ├── utils/
|
|
384
|
-
│ │ ├── palette.ts # Semantic color palette (accent/success/warning/error/muted)
|
|
385
|
-
│ │ ├── ansi.ts # ANSI utility functions (visibleLen, stripAnsi)
|
|
386
|
-
│ │ ├── diff.ts # Line-level LCS diff for file change previews
|
|
387
|
-
│ │ ├── diff-renderer.ts# Syntax-highlighted diff display (split/unified/summary)
|
|
388
|
-
│ │ ├── box-frame.ts # Bordered TUI panels (rounded/square/double/heavy)
|
|
389
|
-
│ │ ├── tool-display.ts # Width-adaptive tool call/result rendering
|
|
390
|
-
│ │ ├── file-watcher.ts # File change detection for agent tool writes
|
|
391
|
-
│ │ └── markdown.ts # Streaming markdown → ANSI renderer
|
|
392
|
-
│ └── extensions/
|
|
393
|
-
│ ├── tui-renderer.ts # Terminal rendering (markdown, spinner, tools)
|
|
394
|
-
│ ├── slash-commands.ts # /help, /clear, /copy, /compact, /quit
|
|
395
|
-
│ ├── file-autocomplete.ts # @ file path completion
|
|
396
|
-
│ └── shell-recall.ts # __shell_recall terminal interception
|
|
397
|
-
├── examples/
|
|
398
|
-
│ └── extensions/
|
|
399
|
-
│ ├── interactive-prompts.ts # Example: permission gates (opt-in)
|
|
400
|
-
│ └── solarized-theme.ts # Example: color theme via setPalette()
|
|
401
|
-
├── package.json
|
|
402
|
-
└── tsconfig.json
|
|
403
|
-
```
|
|
128
|
+
See the [Usage Guide](docs/usage.md#configuration) for the full settings reference.
|
|
404
129
|
|
|
405
130
|
## Development
|
|
406
131
|
|
|
407
132
|
```bash
|
|
408
|
-
|
|
409
|
-
npm run
|
|
410
|
-
|
|
411
|
-
#
|
|
412
|
-
npm run build
|
|
413
|
-
|
|
414
|
-
# Run the built version (uses default agent pi-acp)
|
|
415
|
-
npm start
|
|
416
|
-
|
|
417
|
-
# Quick shortcuts for different agents
|
|
418
|
-
npm run pi # Start with pi-acp
|
|
419
|
-
npm run claude # Start with claude-agent-acp (Anthropic's official Claude agent)
|
|
420
|
-
|
|
421
|
-
# Debug mode — logs ACP protocol details to stderr
|
|
422
|
-
DEBUG=1 npm start
|
|
423
|
-
|
|
424
|
-
# Test with specific agent
|
|
425
|
-
npm run dev -- --agent pi-acp
|
|
426
|
-
```
|
|
427
|
-
|
|
428
|
-
## How it works
|
|
429
|
-
|
|
430
|
-
1. agent-sh spawns a real PTY running your shell (zsh or bash, with your full rc config — oh-my-zsh, p10k, aliases, plugins, PATH) and sets up raw stdin passthrough
|
|
431
|
-
2. It launches the specified ACP agent as a subprocess with stdio transport
|
|
432
|
-
3. All keyboard input goes directly to the PTY — zero latency, full terminal compatibility
|
|
433
|
-
4. **Smart connection**: The agent connects asynchronously in the background while the shell starts immediately
|
|
434
|
-
5. **Auto-wait**: If you send a query before the agent is fully connected, the system automatically waits for connection completion
|
|
435
|
-
6. When you type `>` at the start of a line, agent-sh intercepts and enters agent input mode
|
|
436
|
-
7. On Enter, the query (plus shell context) is sent to the agent via `session/prompt`
|
|
437
|
-
8. The agent's streaming response renders inline in a bordered markdown box with real-time output
|
|
438
|
-
9. If the agent needs to run commands, it calls `terminal/create` and agent-sh executes them in isolated child processes, streaming output back
|
|
439
|
-
10. When the agent finishes, normal shell operation resumes
|
|
440
|
-
|
|
441
|
-
### EventBus
|
|
442
|
-
|
|
443
|
-
All communication between components flows through a typed EventBus. Components emit events (shell commands, agent responses, tool calls) and extensions subscribe to events they care about. The bus supports three modes:
|
|
444
|
-
|
|
445
|
-
- **emit/on** — fire-and-forget notifications (e.g., `agent:response-chunk`)
|
|
446
|
-
- **emitPipe/onPipe** — synchronous transform chains (e.g., `autocomplete:request` where extensions append completion items)
|
|
447
|
-
- **emitPipeAsync/onPipeAsync** — async transform chains (e.g., `permission:request` where extensions prompt the user and return a decision)
|
|
448
|
-
|
|
449
|
-
### Writing extensions
|
|
450
|
-
|
|
451
|
-
An extension is a module that exports a default (or named `activate`) function. It receives an `ExtensionContext` with access to all core services:
|
|
452
|
-
|
|
453
|
-
```typescript
|
|
454
|
-
// my-extension.js
|
|
455
|
-
export default function activate(ctx) {
|
|
456
|
-
// Listen to agent events
|
|
457
|
-
ctx.bus.on("agent:response-done", (e) => {
|
|
458
|
-
console.log(`Agent responded with ${e.response.length} chars`);
|
|
459
|
-
});
|
|
460
|
-
|
|
461
|
-
// Add a slash command
|
|
462
|
-
ctx.bus.on("command:execute", (e) => {
|
|
463
|
-
if (e.name === "/greet") {
|
|
464
|
-
ctx.bus.emit("ui:info", { message: "Hello from my extension!" });
|
|
465
|
-
}
|
|
466
|
-
});
|
|
467
|
-
ctx.bus.onPipe("autocomplete:request", (payload) => {
|
|
468
|
-
if (!payload.buffer.startsWith("/g")) return payload;
|
|
469
|
-
return { ...payload, items: [...payload.items, { name: "/greet", description: "Say hello" }] };
|
|
470
|
-
});
|
|
471
|
-
|
|
472
|
-
// Intercept terminal commands
|
|
473
|
-
ctx.bus.onPipe("agent:terminal-intercept", (payload) => {
|
|
474
|
-
if (payload.command !== "my-tool") return payload;
|
|
475
|
-
return { ...payload, intercepted: true, output: "custom output" };
|
|
476
|
-
});
|
|
477
|
-
}
|
|
478
|
-
```
|
|
479
|
-
|
|
480
|
-
The `ExtensionContext` provides:
|
|
481
|
-
|
|
482
|
-
| Property | Type | Description |
|
|
483
|
-
|---|---|---|
|
|
484
|
-
| `bus` | `EventBus` | Subscribe to events, emit events, register pipe handlers |
|
|
485
|
-
| `contextManager` | `ContextManager` | Access exchange history, cwd, search, expand |
|
|
486
|
-
| `getAcpClient` | `() => AcpClient` | Lazy getter for the agent client |
|
|
487
|
-
| `quit` | `() => void` | Exit agent-sh |
|
|
488
|
-
| `setPalette` | `(overrides: Partial<ColorPalette>) => void` | Override color palette slots for theming |
|
|
489
|
-
|
|
490
|
-
### Yolo mode
|
|
491
|
-
|
|
492
|
-
By default, agent-sh runs in **yolo mode** — all tool calls and file writes are auto-approved. This matches pi's design philosophy where the agent operates freely unless you explicitly add permission gates.
|
|
493
|
-
|
|
494
|
-
To add permission prompts, load the example extension:
|
|
495
|
-
```bash
|
|
496
|
-
# One-off
|
|
497
|
-
npm start -- -e ./examples/extensions/interactive-prompts.ts
|
|
498
|
-
|
|
499
|
-
# Permanent: copy to your extensions dir
|
|
500
|
-
cp examples/extensions/interactive-prompts.ts ~/.agent-sh/extensions/
|
|
501
|
-
|
|
502
|
-
# Or add to settings.json
|
|
503
|
-
echo '{ "extensions": ["./examples/extensions/interactive-prompts.ts"] }' > ~/.agent-sh/settings.json
|
|
504
|
-
```
|
|
505
|
-
|
|
506
|
-
### Theming
|
|
507
|
-
|
|
508
|
-
agent-sh uses a semantic color palette with ~10 base roles (`accent`, `success`, `warning`, `error`, `muted`, plus background variants and style modifiers). Extensions can override any slot via `setPalette()`:
|
|
509
|
-
|
|
510
|
-
```typescript
|
|
511
|
-
// solarized-theme.ts
|
|
512
|
-
export default function activate({ setPalette }) {
|
|
513
|
-
setPalette({
|
|
514
|
-
accent: "\x1b[38;2;38;139;210m", // solarized blue
|
|
515
|
-
success: "\x1b[38;2;133;153;0m", // solarized green
|
|
516
|
-
warning: "\x1b[38;2;181;137;0m", // solarized yellow
|
|
517
|
-
error: "\x1b[38;2;220;50;47m", // solarized red
|
|
518
|
-
muted: "\x1b[38;2;88;110;117m", // solarized base01
|
|
519
|
-
});
|
|
520
|
-
}
|
|
521
|
-
```
|
|
522
|
-
|
|
523
|
-
Load a theme like any other extension:
|
|
524
|
-
```bash
|
|
525
|
-
npm start -- -e ./examples/extensions/solarized-theme.ts
|
|
526
|
-
```
|
|
527
|
-
|
|
528
|
-
A complete example is included at `examples/extensions/solarized-theme.ts`.
|
|
529
|
-
|
|
530
|
-
### Loading extensions
|
|
531
|
-
|
|
532
|
-
Extensions are loaded from three sources (in order, deduplicated):
|
|
533
|
-
|
|
534
|
-
**1. CLI flag (`-e` / `--extensions`)** — npm packages or file paths, repeatable:
|
|
535
|
-
```bash
|
|
536
|
-
npm start -- -e my-ext-package -e ./local-ext.ts
|
|
537
|
-
npm start -- -e my-ext-package,another-package # comma-separated also works
|
|
538
|
-
```
|
|
539
|
-
|
|
540
|
-
**2. Settings file** — `~/.agent-sh/settings.json`:
|
|
541
|
-
```json
|
|
542
|
-
{
|
|
543
|
-
"extensions": [
|
|
544
|
-
"my-published-extension",
|
|
545
|
-
"/absolute/path/to/ext.ts",
|
|
546
|
-
"./relative/path/to/ext.js"
|
|
547
|
-
]
|
|
548
|
-
}
|
|
549
|
-
```
|
|
550
|
-
|
|
551
|
-
**3. Extensions directory** — files and directories in `~/.agent-sh/extensions/`:
|
|
552
|
-
```bash
|
|
553
|
-
~/.agent-sh/extensions/
|
|
554
|
-
├── my-extension.ts # loaded directly
|
|
555
|
-
├── another.js # JS works too
|
|
556
|
-
└── complex-extension/ # directory with index file
|
|
557
|
-
├── index.ts # entry point (auto-detected)
|
|
558
|
-
└── helpers.ts # supporting modules
|
|
559
|
-
```
|
|
560
|
-
|
|
561
|
-
Extensions can be written in **TypeScript or JavaScript** — `.ts`, `.tsx`, `.mts`, `.js`, `.mjs` are all supported. TS extensions are transpiled at runtime via tsx.
|
|
562
|
-
|
|
563
|
-
Bare names (e.g. `my-ext-package`) resolve as **npm packages** via Node's standard module resolution. Install them globally or locally and reference by name.
|
|
564
|
-
|
|
565
|
-
Errors in extension loading are non-fatal — a `ui:error` is emitted and the next extension continues loading.
|
|
566
|
-
|
|
567
|
-
### Using as a library
|
|
568
|
-
|
|
569
|
-
The core can be imported directly for building custom frontends — no terminal required:
|
|
570
|
-
|
|
571
|
-
```typescript
|
|
572
|
-
import { createCore } from "agent-sh";
|
|
573
|
-
|
|
574
|
-
const core = createCore({ agentCommand: "pi-acp" });
|
|
575
|
-
|
|
576
|
-
// Subscribe to events
|
|
577
|
-
core.bus.on("agent:response-chunk", ({ text }) => process.stdout.write(text));
|
|
578
|
-
core.bus.on("agent:processing-done", () => console.log("\n[done]"));
|
|
579
|
-
|
|
580
|
-
// Handle permissions (auto-approve, or wire to your own UI)
|
|
581
|
-
core.bus.onPipeAsync("permission:request", async (p) => {
|
|
582
|
-
return { ...p, decision: { approved: true } };
|
|
583
|
-
});
|
|
584
|
-
|
|
585
|
-
// Connect and send a query
|
|
586
|
-
await core.start();
|
|
587
|
-
core.bus.emit("agent:submit", { query: "explain this codebase" });
|
|
588
|
-
```
|
|
589
|
-
|
|
590
|
-
This works for WebSocket servers, REST APIs, Electron apps, test harnesses, or any environment where you want agent-sh's context management and ACP integration without the interactive terminal.
|
|
591
|
-
|
|
592
|
-
## Troubleshooting
|
|
593
|
-
|
|
594
|
-
### Agent connection issues
|
|
595
|
-
|
|
596
|
-
**Problem**: "Agent not connected. Please wait a moment and try again."
|
|
597
|
-
|
|
598
|
-
**Solutions**:
|
|
599
|
-
1. **Check agent installation**:
|
|
600
|
-
```bash
|
|
601
|
-
which pi-acp
|
|
602
|
-
which claude-agent-acp
|
|
603
|
-
```
|
|
604
|
-
|
|
605
|
-
2. **Verify ACP compatibility**:
|
|
606
|
-
```bash
|
|
607
|
-
# Test if agent supports ACP protocol
|
|
608
|
-
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":1,"clientInfo":{"name":"test","version":"1.0.0"},"clientCapabilities":{"terminal":true,"fs":{"readTextFile":true,"writeTextFile":true}}}}' | pi-acp
|
|
609
|
-
```
|
|
610
|
-
|
|
611
|
-
3. **Install missing agents**:
|
|
612
|
-
```bash
|
|
613
|
-
npm install -g pi-acp
|
|
614
|
-
npm install -g @agentclientprotocol/claude-agent-acp
|
|
615
|
-
```
|
|
616
|
-
|
|
617
|
-
4. **Check environment variables**:
|
|
618
|
-
```bash
|
|
619
|
-
echo $ANTHROPIC_API_KEY
|
|
620
|
-
echo $OPENAI_API_KEY
|
|
621
|
-
echo $GEMINI_API_KEY
|
|
622
|
-
```
|
|
623
|
-
|
|
624
|
-
### Common errors
|
|
625
|
-
|
|
626
|
-
**Error**: "claude: command not found"
|
|
627
|
-
- **Cause**: Trying to use `claude` CLI tool which doesn't support ACP
|
|
628
|
-
- **Solution**: Use `claude-agent-acp` or `pi-acp` instead
|
|
629
|
-
|
|
630
|
-
**Error**: "API key not found"
|
|
631
|
-
- **Cause**: Missing required API key environment variable
|
|
632
|
-
- **Solution**: Set the appropriate API key (e.g., `export ANTHROPIC_API_KEY="your-key"`)
|
|
633
|
-
|
|
634
|
-
**Error**: "Invalid model name"
|
|
635
|
-
- **Cause**: Using incorrect model name
|
|
636
|
-
- **Solution**: Use valid model names like `claude-3-5-sonnet-20241022` or `gpt-4o`
|
|
637
|
-
|
|
638
|
-
**Error**: "Agent process exited with code X"
|
|
639
|
-
- **Cause**: Agent crashed or failed to start
|
|
640
|
-
- **Solution**: Check agent installation and API key validity
|
|
641
|
-
|
|
642
|
-
### Debug mode
|
|
643
|
-
|
|
644
|
-
Enable debug mode to see detailed ACP protocol information:
|
|
645
|
-
```bash
|
|
646
|
-
DEBUG=1 npm start -- --agent pi-acp
|
|
133
|
+
npm run dev # development mode (no build step)
|
|
134
|
+
npm run build # build
|
|
135
|
+
npm start # run built version
|
|
136
|
+
DEBUG=1 npm start # debug mode (logs ACP protocol details)
|
|
647
137
|
```
|
|
648
138
|
|
|
649
|
-
|
|
139
|
+
## Documentation
|
|
650
140
|
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
141
|
+
- [Usage Guide](docs/usage.md) — models, providers, API keys, environment config
|
|
142
|
+
- [Architecture](docs/architecture.md) — design philosophy, protocol details, project structure
|
|
143
|
+
- [Extensions](docs/extensions.md) — writing extensions, theming, yolo mode
|
|
144
|
+
- [Library Usage](docs/library.md) — using agent-sh as a Node.js library
|
|
145
|
+
- [Troubleshooting](docs/troubleshooting.md) — common errors and debug mode
|
|
656
146
|
|
|
657
147
|
## License
|
|
658
148
|
|