@mariozechner/pi-coding-agent 0.49.3 → 0.50.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 +99 -1
- package/README.md +310 -1230
- package/dist/cli/args.d.ts +5 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +57 -23
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/config-selector.d.ts +14 -0
- package/dist/cli/config-selector.d.ts.map +1 -0
- package/dist/cli/config-selector.js +31 -0
- package/dist/cli/config-selector.js.map +1 -0
- package/dist/cli/session-picker.d.ts.map +1 -1
- package/dist/cli/session-picker.js +1 -1
- package/dist/cli/session-picker.js.map +1 -1
- package/dist/core/agent-session.d.ts +53 -34
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +262 -67
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts +8 -18
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +39 -55
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +2 -1
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/diagnostics.d.ts +15 -0
- package/dist/core/diagnostics.d.ts.map +1 -0
- package/dist/core/diagnostics.js +2 -0
- package/dist/core/diagnostics.js.map +1 -0
- package/dist/core/export-html/template.css +9 -0
- package/dist/core/export-html/template.js +6 -4
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +10 -1
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +9 -3
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +39 -12
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +112 -1
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +9 -2
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +13 -0
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/model-registry.d.ts +42 -2
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +154 -44
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +3 -2
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/package-manager.d.ts +129 -0
- package/dist/core/package-manager.d.ts.map +1 -0
- package/dist/core/package-manager.js +1148 -0
- package/dist/core/package-manager.js.map +1 -0
- package/dist/core/prompt-templates.d.ts +6 -0
- package/dist/core/prompt-templates.d.ts.map +1 -1
- package/dist/core/prompt-templates.js +114 -54
- package/dist/core/prompt-templates.js.map +1 -1
- package/dist/core/resource-loader.d.ts +160 -0
- package/dist/core/resource-loader.d.ts.map +1 -0
- package/dist/core/resource-loader.js +604 -0
- package/dist/core/resource-loader.js.map +1 -0
- package/dist/core/sdk.d.ts +14 -105
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +52 -304
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +45 -1
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +34 -16
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +104 -25
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.d.ts +18 -10
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +126 -93
- package/dist/core/skills.js.map +1 -1
- package/dist/core/system-prompt.d.ts +3 -27
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +16 -103
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +2 -1
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +4 -4
- package/dist/core/tools/read.js.map +1 -1
- package/dist/index.d.ts +12 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -6
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +209 -97
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.d.ts +5 -1
- package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.js +29 -9
- package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
- package/dist/modes/interactive/components/config-selector.d.ts +71 -0
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/config-selector.js +468 -0
- package/dist/modes/interactive/components/config-selector.js.map +1 -0
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +4 -0
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -0
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +1 -0
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js +3 -4
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts +18 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +195 -87
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts +17 -0
- package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/skill-invocation-message.js +47 -0
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -0
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +5 -5
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +42 -2
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +535 -200
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/dark.json +1 -1
- package/dist/modes/interactive/theme/light.json +1 -1
- package/dist/modes/interactive/theme/theme-schema.json +8 -1
- package/dist/modes/interactive/theme/theme.d.ts +8 -1
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +72 -25
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +25 -89
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +32 -92
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/utils/git.d.ts +2 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +6 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/shell.d.ts +1 -0
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +14 -1
- package/dist/utils/shell.js.map +1 -1
- package/dist/utils/sleep.d.ts +5 -0
- package/dist/utils/sleep.d.ts.map +1 -0
- package/dist/utils/sleep.js +17 -0
- package/dist/utils/sleep.js.map +1 -0
- package/docs/compaction.md +23 -21
- package/docs/custom-provider.md +538 -0
- package/docs/development.md +69 -0
- package/docs/extensions.md +180 -118
- package/docs/images/doom-extension.png +0 -0
- package/docs/images/interactive-mode.png +0 -0
- package/docs/images/tree-view.png +0 -0
- package/docs/json.md +79 -0
- package/docs/keybindings.md +162 -0
- package/docs/models.md +193 -0
- package/docs/packages.md +163 -0
- package/docs/prompt-templates.md +67 -0
- package/docs/providers.md +147 -0
- package/docs/sdk.md +111 -178
- package/docs/session.md +167 -16
- package/docs/settings.md +216 -0
- package/docs/shell-aliases.md +13 -0
- package/docs/skills.md +111 -202
- package/docs/terminal-setup.md +65 -0
- package/docs/themes.md +295 -0
- package/docs/tui.md +36 -5
- package/docs/windows.md +17 -0
- package/examples/README.md +1 -0
- package/examples/extensions/README.md +22 -2
- package/examples/extensions/bookmark.ts +50 -0
- package/examples/extensions/custom-provider-anthropic/index.ts +604 -0
- package/examples/extensions/custom-provider-anthropic/package-lock.json +24 -0
- package/examples/extensions/custom-provider-anthropic/package.json +19 -0
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +349 -0
- package/examples/extensions/custom-provider-gitlab-duo/package.json +16 -0
- package/examples/extensions/custom-provider-gitlab-duo/test.ts +82 -0
- package/examples/extensions/doom-overlay/doom/build.sh +1 -1
- package/examples/extensions/event-bus.ts +43 -0
- package/examples/extensions/message-renderer.ts +59 -0
- package/examples/extensions/session-name.ts +27 -0
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/sdk/02-custom-model.ts +3 -3
- package/examples/sdk/03-custom-prompt.ts +20 -9
- package/examples/sdk/04-skills.ts +26 -27
- package/examples/sdk/06-extensions.ts +15 -6
- package/examples/sdk/07-context-files.ts +22 -18
- package/examples/sdk/08-prompt-templates.ts +19 -14
- package/examples/sdk/09-api-keys-and-oauth.ts +5 -12
- package/examples/sdk/10-settings.ts +3 -3
- package/examples/sdk/12-full-control.ts +16 -7
- package/examples/sdk/README.md +24 -30
- package/package.json +4 -4
- package/docs/theme.md +0 -617
- package/examples/extensions/chalk-logger.ts +0 -26
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Development
|
|
2
|
+
|
|
3
|
+
See [AGENTS.md](../../../AGENTS.md) for additional guidelines.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
git clone https://github.com/badlogic/pi-mono
|
|
9
|
+
cd pi-mono
|
|
10
|
+
npm install
|
|
11
|
+
npm run build
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Run from source:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
./pi-test.sh
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Forking / Rebranding
|
|
21
|
+
|
|
22
|
+
Configure via `package.json`:
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
{
|
|
26
|
+
"piConfig": {
|
|
27
|
+
"name": "pi",
|
|
28
|
+
"configDir": ".pi"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Change `name`, `configDir`, and `bin` field for your fork. Affects CLI banner, config paths, and environment variable names.
|
|
34
|
+
|
|
35
|
+
## Path Resolution
|
|
36
|
+
|
|
37
|
+
Three execution modes: npm install, standalone binary, tsx from source.
|
|
38
|
+
|
|
39
|
+
**Always use `src/config.ts`** for package assets:
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import { getPackageDir, getThemeDir } from "./config.js";
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Never use `__dirname` directly for package assets.
|
|
46
|
+
|
|
47
|
+
## Debug Command
|
|
48
|
+
|
|
49
|
+
`/debug` (hidden) writes to `~/.pi/agent/pi-debug.log`:
|
|
50
|
+
- Rendered TUI lines with ANSI codes
|
|
51
|
+
- Last messages sent to the LLM
|
|
52
|
+
|
|
53
|
+
## Testing
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
./test.sh # Run non-LLM tests (no API keys needed)
|
|
57
|
+
npm test # Run all tests
|
|
58
|
+
npm test -- test/specific.test.ts # Run specific test
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Project Structure
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
packages/
|
|
65
|
+
ai/ # LLM provider abstraction
|
|
66
|
+
agent/ # Agent loop and message types
|
|
67
|
+
tui/ # Terminal UI components
|
|
68
|
+
coding-agent/ # CLI and interactive mode
|
|
69
|
+
```
|
package/docs/extensions.md
CHANGED
|
@@ -46,6 +46,7 @@ See [examples/extensions/](../examples/extensions/) for working implementations.
|
|
|
46
46
|
- [Custom UI](#custom-ui)
|
|
47
47
|
- [Error Handling](#error-handling)
|
|
48
48
|
- [Mode Behavior](#mode-behavior)
|
|
49
|
+
- [Examples Reference](#examples-reference)
|
|
49
50
|
|
|
50
51
|
## Quick Start
|
|
51
52
|
|
|
@@ -102,6 +103,8 @@ pi -e ./my-extension.ts
|
|
|
102
103
|
|
|
103
104
|
## Extension Locations
|
|
104
105
|
|
|
106
|
+
> **Security:** Extensions run with your full system permissions and can execute arbitrary code. Only install from sources you trust.
|
|
107
|
+
|
|
105
108
|
Extensions are auto-discovered from:
|
|
106
109
|
|
|
107
110
|
| Location | Scope |
|
|
@@ -115,47 +118,18 @@ Additional paths via `settings.json`:
|
|
|
115
118
|
|
|
116
119
|
```json
|
|
117
120
|
{
|
|
118
|
-
"
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
3. **Subdirectory with package.json:** `extensions/myext/package.json` with `"pi"` field → loads declared paths
|
|
127
|
-
|
|
128
|
-
```
|
|
129
|
-
~/.pi/agent/extensions/
|
|
130
|
-
├── simple.ts # Direct file (auto-discovered)
|
|
131
|
-
├── my-tool/
|
|
132
|
-
│ └── index.ts # Subdirectory with index (auto-discovered)
|
|
133
|
-
└── my-extension-pack/
|
|
134
|
-
├── package.json # Declares multiple extensions
|
|
135
|
-
├── node_modules/ # Dependencies installed here
|
|
136
|
-
└── src/
|
|
137
|
-
├── safety-gates.ts # First extension
|
|
138
|
-
└── custom-tools.ts # Second extension
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
```json
|
|
142
|
-
// my-extension-pack/package.json
|
|
143
|
-
{
|
|
144
|
-
"name": "my-extension-pack",
|
|
145
|
-
"dependencies": {
|
|
146
|
-
"zod": "^3.0.0"
|
|
147
|
-
},
|
|
148
|
-
"pi": {
|
|
149
|
-
"extensions": ["./src/safety-gates.ts", "./src/custom-tools.ts"]
|
|
150
|
-
}
|
|
121
|
+
"packages": [
|
|
122
|
+
"npm:@foo/bar@1.0.0",
|
|
123
|
+
"git:github.com/user/repo@v1"
|
|
124
|
+
],
|
|
125
|
+
"extensions": [
|
|
126
|
+
"/path/to/local/extension.ts",
|
|
127
|
+
"/path/to/local/extension/dir"
|
|
128
|
+
]
|
|
151
129
|
}
|
|
152
130
|
```
|
|
153
131
|
|
|
154
|
-
|
|
155
|
-
- Multiple extensions from one package
|
|
156
|
-
- Third-party npm dependencies (resolved via jiti)
|
|
157
|
-
- Nested source structure (no depth limit within the package)
|
|
158
|
-
- Deployment to and installation from npm
|
|
132
|
+
To share extensions via npm or git as pi packages, see [packages.md](packages.md).
|
|
159
133
|
|
|
160
134
|
## Available Imports
|
|
161
135
|
|
|
@@ -303,6 +277,8 @@ exit (Ctrl+C, Ctrl+D)
|
|
|
303
277
|
|
|
304
278
|
### Session Events
|
|
305
279
|
|
|
280
|
+
See [session.md](session.md) for session storage internals and the SessionManager API.
|
|
281
|
+
|
|
306
282
|
#### session_start
|
|
307
283
|
|
|
308
284
|
Fired on initial session load.
|
|
@@ -313,8 +289,6 @@ pi.on("session_start", async (_event, ctx) => {
|
|
|
313
289
|
});
|
|
314
290
|
```
|
|
315
291
|
|
|
316
|
-
**Examples:** [claude-rules.ts](../examples/extensions/claude-rules.ts), [custom-header.ts](../examples/extensions/custom-header.ts), [file-trigger.ts](../examples/extensions/file-trigger.ts), [status-line.ts](../examples/extensions/status-line.ts), [todo.ts](../examples/extensions/todo.ts), [tools.ts](../examples/extensions/tools.ts)
|
|
317
|
-
|
|
318
292
|
#### session_before_switch / session_switch
|
|
319
293
|
|
|
320
294
|
Fired when starting a new session (`/new`) or switching sessions (`/resume`).
|
|
@@ -336,8 +310,6 @@ pi.on("session_switch", async (event, ctx) => {
|
|
|
336
310
|
});
|
|
337
311
|
```
|
|
338
312
|
|
|
339
|
-
**Examples:** [confirm-destructive.ts](../examples/extensions/confirm-destructive.ts), [dirty-repo-guard.ts](../examples/extensions/dirty-repo-guard.ts), [status-line.ts](../examples/extensions/status-line.ts), [todo.ts](../examples/extensions/todo.ts)
|
|
340
|
-
|
|
341
313
|
#### session_before_fork / session_fork
|
|
342
314
|
|
|
343
315
|
Fired when forking via `/fork`.
|
|
@@ -355,8 +327,6 @@ pi.on("session_fork", async (event, ctx) => {
|
|
|
355
327
|
});
|
|
356
328
|
```
|
|
357
329
|
|
|
358
|
-
**Examples:** [confirm-destructive.ts](../examples/extensions/confirm-destructive.ts), [dirty-repo-guard.ts](../examples/extensions/dirty-repo-guard.ts), [git-checkpoint.ts](../examples/extensions/git-checkpoint.ts), [todo.ts](../examples/extensions/todo.ts), [tools.ts](../examples/extensions/tools.ts)
|
|
359
|
-
|
|
360
330
|
#### session_before_compact / session_compact
|
|
361
331
|
|
|
362
332
|
Fired on compaction. See [compaction.md](compaction.md) for details.
|
|
@@ -384,11 +354,9 @@ pi.on("session_compact", async (event, ctx) => {
|
|
|
384
354
|
});
|
|
385
355
|
```
|
|
386
356
|
|
|
387
|
-
**Examples:** [custom-compaction.ts](../examples/extensions/custom-compaction.ts), [trigger-compact.ts](../examples/extensions/trigger-compact.ts)
|
|
388
|
-
|
|
389
357
|
#### session_before_tree / session_tree
|
|
390
358
|
|
|
391
|
-
Fired on `/tree` navigation.
|
|
359
|
+
Fired on `/tree` navigation. See [tree.md](tree.md) for tree navigation concepts.
|
|
392
360
|
|
|
393
361
|
```typescript
|
|
394
362
|
pi.on("session_before_tree", async (event, ctx) => {
|
|
@@ -403,8 +371,6 @@ pi.on("session_tree", async (event, ctx) => {
|
|
|
403
371
|
});
|
|
404
372
|
```
|
|
405
373
|
|
|
406
|
-
**Examples:** [todo.ts](../examples/extensions/todo.ts), [tools.ts](../examples/extensions/tools.ts)
|
|
407
|
-
|
|
408
374
|
#### session_shutdown
|
|
409
375
|
|
|
410
376
|
Fired on exit (Ctrl+C, Ctrl+D, SIGTERM).
|
|
@@ -415,8 +381,6 @@ pi.on("session_shutdown", async (_event, ctx) => {
|
|
|
415
381
|
});
|
|
416
382
|
```
|
|
417
383
|
|
|
418
|
-
**Examples:** [auto-commit-on-exit.ts](../examples/extensions/auto-commit-on-exit.ts)
|
|
419
|
-
|
|
420
384
|
### Agent Events
|
|
421
385
|
|
|
422
386
|
#### before_agent_start
|
|
@@ -442,8 +406,6 @@ pi.on("before_agent_start", async (event, ctx) => {
|
|
|
442
406
|
});
|
|
443
407
|
```
|
|
444
408
|
|
|
445
|
-
**Examples:** [claude-rules.ts](../examples/extensions/claude-rules.ts), [pirate.ts](../examples/extensions/pirate.ts), [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [preset.ts](../examples/extensions/preset.ts), [ssh.ts](../examples/extensions/ssh.ts)
|
|
446
|
-
|
|
447
409
|
#### agent_start / agent_end
|
|
448
410
|
|
|
449
411
|
Fired once per user prompt.
|
|
@@ -456,8 +418,6 @@ pi.on("agent_end", async (event, ctx) => {
|
|
|
456
418
|
});
|
|
457
419
|
```
|
|
458
420
|
|
|
459
|
-
**Examples:** [chalk-logger.ts](../examples/extensions/chalk-logger.ts), [git-checkpoint.ts](../examples/extensions/git-checkpoint.ts), [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts)
|
|
460
|
-
|
|
461
421
|
#### turn_start / turn_end
|
|
462
422
|
|
|
463
423
|
Fired for each turn (one LLM response + tool calls).
|
|
@@ -472,11 +432,9 @@ pi.on("turn_end", async (event, ctx) => {
|
|
|
472
432
|
});
|
|
473
433
|
```
|
|
474
434
|
|
|
475
|
-
**Examples:** [git-checkpoint.ts](../examples/extensions/git-checkpoint.ts), [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [status-line.ts](../examples/extensions/status-line.ts)
|
|
476
|
-
|
|
477
435
|
#### context
|
|
478
436
|
|
|
479
|
-
Fired before each LLM call. Modify messages non-destructively.
|
|
437
|
+
Fired before each LLM call. Modify messages non-destructively. See [session.md](session.md) for message types.
|
|
480
438
|
|
|
481
439
|
```typescript
|
|
482
440
|
pi.on("context", async (event, ctx) => {
|
|
@@ -486,8 +444,6 @@ pi.on("context", async (event, ctx) => {
|
|
|
486
444
|
});
|
|
487
445
|
```
|
|
488
446
|
|
|
489
|
-
**Examples:** [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts)
|
|
490
|
-
|
|
491
447
|
### Model Events
|
|
492
448
|
|
|
493
449
|
#### model_select
|
|
@@ -499,20 +455,18 @@ pi.on("model_select", async (event, ctx) => {
|
|
|
499
455
|
// event.model - newly selected model
|
|
500
456
|
// event.previousModel - previous model (undefined if first selection)
|
|
501
457
|
// event.source - "set" | "cycle" | "restore"
|
|
502
|
-
|
|
503
|
-
const prev = event.previousModel
|
|
504
|
-
? `${event.previousModel.provider}/${event.previousModel.id}`
|
|
458
|
+
|
|
459
|
+
const prev = event.previousModel
|
|
460
|
+
? `${event.previousModel.provider}/${event.previousModel.id}`
|
|
505
461
|
: "none";
|
|
506
462
|
const next = `${event.model.provider}/${event.model.id}`;
|
|
507
|
-
|
|
463
|
+
|
|
508
464
|
ctx.ui.notify(`Model changed (${event.source}): ${prev} -> ${next}`, "info");
|
|
509
465
|
});
|
|
510
466
|
```
|
|
511
467
|
|
|
512
468
|
Use this to update UI elements (status bars, footers) or perform model-specific initialization when the active model changes.
|
|
513
469
|
|
|
514
|
-
**Examples:** [model-status.ts](../examples/extensions/model-status.ts)
|
|
515
|
-
|
|
516
470
|
### Tool Events
|
|
517
471
|
|
|
518
472
|
#### tool_call
|
|
@@ -531,8 +485,6 @@ pi.on("tool_call", async (event, ctx) => {
|
|
|
531
485
|
});
|
|
532
486
|
```
|
|
533
487
|
|
|
534
|
-
**Examples:** [chalk-logger.ts](../examples/extensions/chalk-logger.ts), [permission-gate.ts](../examples/extensions/permission-gate.ts), [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [protected-paths.ts](../examples/extensions/protected-paths.ts)
|
|
535
|
-
|
|
536
488
|
#### tool_result
|
|
537
489
|
|
|
538
490
|
Fired after tool executes. **Can modify result.**
|
|
@@ -553,8 +505,6 @@ pi.on("tool_result", async (event, ctx) => {
|
|
|
553
505
|
});
|
|
554
506
|
```
|
|
555
507
|
|
|
556
|
-
**Examples:** [git-checkpoint.ts](../examples/extensions/git-checkpoint.ts), [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts)
|
|
557
|
-
|
|
558
508
|
### User Bash Events
|
|
559
509
|
|
|
560
510
|
#### user_bash
|
|
@@ -575,8 +525,6 @@ pi.on("user_bash", (event, ctx) => {
|
|
|
575
525
|
});
|
|
576
526
|
```
|
|
577
527
|
|
|
578
|
-
**Examples:** [ssh.ts](../examples/extensions/ssh.ts), [interactive-shell.ts](../examples/extensions/interactive-shell.ts)
|
|
579
|
-
|
|
580
528
|
### Input Events
|
|
581
529
|
|
|
582
530
|
#### input
|
|
@@ -643,7 +591,7 @@ Current working directory.
|
|
|
643
591
|
|
|
644
592
|
### ctx.sessionManager
|
|
645
593
|
|
|
646
|
-
Read-only access to session state
|
|
594
|
+
Read-only access to session state. See [session.md](session.md) for the full SessionManager API and entry types.
|
|
647
595
|
|
|
648
596
|
```typescript
|
|
649
597
|
ctx.sessionManager.getEntries() // All entries
|
|
@@ -811,8 +759,6 @@ pi.registerTool({
|
|
|
811
759
|
});
|
|
812
760
|
```
|
|
813
761
|
|
|
814
|
-
**Examples:** [hello.ts](../examples/extensions/hello.ts), [question.ts](../examples/extensions/question.ts), [questionnaire.ts](../examples/extensions/questionnaire.ts), [todo.ts](../examples/extensions/todo.ts), [truncated-tool.ts](../examples/extensions/truncated-tool.ts)
|
|
815
|
-
|
|
816
762
|
### pi.sendMessage(message, options?)
|
|
817
763
|
|
|
818
764
|
Inject a custom message into the session.
|
|
@@ -836,8 +782,6 @@ pi.sendMessage({
|
|
|
836
782
|
- `"nextTurn"` - Queued for next user prompt. Does not interrupt or trigger anything.
|
|
837
783
|
- `triggerTurn: true` - If agent is idle, trigger an LLM response immediately. Only applies to `"steer"` and `"followUp"` modes (ignored for `"nextTurn"`).
|
|
838
784
|
|
|
839
|
-
**Examples:** [file-trigger.ts](../examples/extensions/file-trigger.ts), [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts)
|
|
840
|
-
|
|
841
785
|
### pi.sendUserMessage(content, options?)
|
|
842
786
|
|
|
843
787
|
Send a user message to the agent. Unlike `sendMessage()` which sends custom messages, this sends an actual user message that appears as if typed by the user. Always triggers a turn.
|
|
@@ -883,8 +827,6 @@ pi.on("session_start", async (_event, ctx) => {
|
|
|
883
827
|
});
|
|
884
828
|
```
|
|
885
829
|
|
|
886
|
-
**Examples:** [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [preset.ts](../examples/extensions/preset.ts), [snake.ts](../examples/extensions/snake.ts), [tools.ts](../examples/extensions/tools.ts)
|
|
887
|
-
|
|
888
830
|
### pi.setSessionName(name)
|
|
889
831
|
|
|
890
832
|
Set the session display name (shown in session selector instead of first message).
|
|
@@ -954,15 +896,13 @@ pi.registerCommand("deploy", {
|
|
|
954
896
|
});
|
|
955
897
|
```
|
|
956
898
|
|
|
957
|
-
**Examples:** [custom-footer.ts](../examples/extensions/custom-footer.ts), [custom-header.ts](../examples/extensions/custom-header.ts), [handoff.ts](../examples/extensions/handoff.ts), [pirate.ts](../examples/extensions/pirate.ts), [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [preset.ts](../examples/extensions/preset.ts), [qna.ts](../examples/extensions/qna.ts), [send-user-message.ts](../examples/extensions/send-user-message.ts), [snake.ts](../examples/extensions/snake.ts), [summarize.ts](../examples/extensions/summarize.ts), [todo.ts](../examples/extensions/todo.ts), [tools.ts](../examples/extensions/tools.ts)
|
|
958
|
-
|
|
959
899
|
### pi.registerMessageRenderer(customType, renderer)
|
|
960
900
|
|
|
961
901
|
Register a custom TUI renderer for messages with your `customType`. See [Custom UI](#custom-ui).
|
|
962
902
|
|
|
963
903
|
### pi.registerShortcut(shortcut, options)
|
|
964
904
|
|
|
965
|
-
Register a keyboard shortcut.
|
|
905
|
+
Register a keyboard shortcut. See [keybindings.md](keybindings.md) for the shortcut format and built-in keybindings.
|
|
966
906
|
|
|
967
907
|
```typescript
|
|
968
908
|
pi.registerShortcut("ctrl+shift+p", {
|
|
@@ -973,8 +913,6 @@ pi.registerShortcut("ctrl+shift+p", {
|
|
|
973
913
|
});
|
|
974
914
|
```
|
|
975
915
|
|
|
976
|
-
**Examples:** [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [preset.ts](../examples/extensions/preset.ts)
|
|
977
|
-
|
|
978
916
|
### pi.registerFlag(name, options)
|
|
979
917
|
|
|
980
918
|
Register a CLI flag.
|
|
@@ -992,8 +930,6 @@ if (pi.getFlag("--plan")) {
|
|
|
992
930
|
}
|
|
993
931
|
```
|
|
994
932
|
|
|
995
|
-
**Examples:** [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [preset.ts](../examples/extensions/preset.ts)
|
|
996
|
-
|
|
997
933
|
### pi.exec(command, args, options?)
|
|
998
934
|
|
|
999
935
|
Execute a shell command.
|
|
@@ -1003,8 +939,6 @@ const result = await pi.exec("git", ["status"], { signal, timeout: 5000 });
|
|
|
1003
939
|
// result.stdout, result.stderr, result.code, result.killed
|
|
1004
940
|
```
|
|
1005
941
|
|
|
1006
|
-
**Examples:** [auto-commit-on-exit.ts](../examples/extensions/auto-commit-on-exit.ts), [dirty-repo-guard.ts](../examples/extensions/dirty-repo-guard.ts), [git-checkpoint.ts](../examples/extensions/git-checkpoint.ts)
|
|
1007
|
-
|
|
1008
942
|
### pi.getActiveTools() / pi.getAllTools() / pi.setActiveTools(names)
|
|
1009
943
|
|
|
1010
944
|
Manage active tools.
|
|
@@ -1016,11 +950,9 @@ const names = all.map(t => t.name); // Just names if needed
|
|
|
1016
950
|
pi.setActiveTools(["read", "bash"]); // Switch to read-only
|
|
1017
951
|
```
|
|
1018
952
|
|
|
1019
|
-
**Examples:** [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [preset.ts](../examples/extensions/preset.ts), [tools.ts](../examples/extensions/tools.ts)
|
|
1020
|
-
|
|
1021
953
|
### pi.setModel(model)
|
|
1022
954
|
|
|
1023
|
-
Set the current model. Returns `false` if no API key is available for the model.
|
|
955
|
+
Set the current model. Returns `false` if no API key is available for the model. See [models.md](models.md) for configuring custom models.
|
|
1024
956
|
|
|
1025
957
|
```typescript
|
|
1026
958
|
const model = ctx.modelRegistry.find("anthropic", "claude-sonnet-4-5");
|
|
@@ -1032,8 +964,6 @@ if (model) {
|
|
|
1032
964
|
}
|
|
1033
965
|
```
|
|
1034
966
|
|
|
1035
|
-
**Examples:** [preset.ts](../examples/extensions/preset.ts)
|
|
1036
|
-
|
|
1037
967
|
### pi.getThinkingLevel() / pi.setThinkingLevel(level)
|
|
1038
968
|
|
|
1039
969
|
Get or set the thinking level. Level is clamped to model capabilities (non-reasoning models always use "off").
|
|
@@ -1043,8 +973,6 @@ const current = pi.getThinkingLevel(); // "off" | "minimal" | "low" | "medium"
|
|
|
1043
973
|
pi.setThinkingLevel("high");
|
|
1044
974
|
```
|
|
1045
975
|
|
|
1046
|
-
**Examples:** [preset.ts](../examples/extensions/preset.ts)
|
|
1047
|
-
|
|
1048
976
|
### pi.events
|
|
1049
977
|
|
|
1050
978
|
Shared event bus for communication between extensions:
|
|
@@ -1054,6 +982,70 @@ pi.events.on("my:event", (data) => { ... });
|
|
|
1054
982
|
pi.events.emit("my:event", { ... });
|
|
1055
983
|
```
|
|
1056
984
|
|
|
985
|
+
### pi.registerProvider(name, config)
|
|
986
|
+
|
|
987
|
+
Register or override a model provider dynamically. Useful for proxies, custom endpoints, or team-wide model configurations.
|
|
988
|
+
|
|
989
|
+
```typescript
|
|
990
|
+
// Register a new provider with custom models
|
|
991
|
+
pi.registerProvider("my-proxy", {
|
|
992
|
+
baseUrl: "https://proxy.example.com",
|
|
993
|
+
apiKey: "PROXY_API_KEY", // env var name or literal
|
|
994
|
+
api: "anthropic-messages",
|
|
995
|
+
models: [
|
|
996
|
+
{
|
|
997
|
+
id: "claude-sonnet-4-20250514",
|
|
998
|
+
name: "Claude 4 Sonnet (proxy)",
|
|
999
|
+
reasoning: false,
|
|
1000
|
+
input: ["text", "image"],
|
|
1001
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
1002
|
+
contextWindow: 200000,
|
|
1003
|
+
maxTokens: 16384
|
|
1004
|
+
}
|
|
1005
|
+
]
|
|
1006
|
+
});
|
|
1007
|
+
|
|
1008
|
+
// Override baseUrl for an existing provider (keeps all models)
|
|
1009
|
+
pi.registerProvider("anthropic", {
|
|
1010
|
+
baseUrl: "https://proxy.example.com"
|
|
1011
|
+
});
|
|
1012
|
+
|
|
1013
|
+
// Register provider with OAuth support for /login
|
|
1014
|
+
pi.registerProvider("corporate-ai", {
|
|
1015
|
+
baseUrl: "https://ai.corp.com",
|
|
1016
|
+
api: "openai-responses",
|
|
1017
|
+
models: [...],
|
|
1018
|
+
oauth: {
|
|
1019
|
+
name: "Corporate AI (SSO)",
|
|
1020
|
+
async login(callbacks) {
|
|
1021
|
+
// Custom OAuth flow
|
|
1022
|
+
callbacks.onAuth({ url: "https://sso.corp.com/..." });
|
|
1023
|
+
const code = await callbacks.onPrompt({ message: "Enter code:" });
|
|
1024
|
+
return { refresh: code, access: code, expires: Date.now() + 3600000 };
|
|
1025
|
+
},
|
|
1026
|
+
async refreshToken(credentials) {
|
|
1027
|
+
// Refresh logic
|
|
1028
|
+
return credentials;
|
|
1029
|
+
},
|
|
1030
|
+
getApiKey(credentials) {
|
|
1031
|
+
return credentials.access;
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
});
|
|
1035
|
+
```
|
|
1036
|
+
|
|
1037
|
+
**Config options:**
|
|
1038
|
+
- `baseUrl` - API endpoint URL. Required when defining models.
|
|
1039
|
+
- `apiKey` - API key or environment variable name. Required when defining models (unless `oauth` provided).
|
|
1040
|
+
- `api` - API type: `"anthropic-messages"`, `"openai-completions"`, `"openai-responses"`, etc.
|
|
1041
|
+
- `headers` - Custom headers to include in requests.
|
|
1042
|
+
- `authHeader` - If true, adds `Authorization: Bearer` header automatically.
|
|
1043
|
+
- `models` - Array of model definitions. If provided, replaces all existing models for this provider.
|
|
1044
|
+
- `oauth` - OAuth provider config for `/login` support. When provided, the provider appears in the login menu.
|
|
1045
|
+
- `streamSimple` - Custom streaming implementation for non-standard APIs.
|
|
1046
|
+
|
|
1047
|
+
See [custom-provider.md](custom-provider.md) for advanced topics: custom streaming APIs, OAuth details, model definition reference.
|
|
1048
|
+
|
|
1057
1049
|
## State Management
|
|
1058
1050
|
|
|
1059
1051
|
Extensions with state should store it in tool result `details` for proper branching support:
|
|
@@ -1214,6 +1206,7 @@ The built-in limit is **50KB** (~10k tokens) and **2000 lines**, whichever is hi
|
|
|
1214
1206
|
import {
|
|
1215
1207
|
truncateHead, // Keep first N lines/bytes (good for file reads, search results)
|
|
1216
1208
|
truncateTail, // Keep last N lines/bytes (good for logs, command output)
|
|
1209
|
+
truncateLine, // Truncate a single line to maxBytes with ellipsis
|
|
1217
1210
|
formatSize, // Human-readable size (e.g., "50KB", "1.5MB")
|
|
1218
1211
|
DEFAULT_MAX_BYTES, // 50KB
|
|
1219
1212
|
DEFAULT_MAX_LINES, // 2000
|
|
@@ -1272,7 +1265,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
1272
1265
|
|
|
1273
1266
|
### Custom Rendering
|
|
1274
1267
|
|
|
1275
|
-
Tools can provide `renderCall` and `renderResult` for custom TUI display. See [tui.md](tui.md) for the full component API.
|
|
1268
|
+
Tools can provide `renderCall` and `renderResult` for custom TUI display. See [tui.md](tui.md) for the full component API and [tool-execution.ts](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/src/modes/interactive/components/tool-execution.ts) for how built-in tools render.
|
|
1276
1269
|
|
|
1277
1270
|
Tool output is wrapped in a `Box` that handles padding and background. Your render methods return `Component` instances (typically `Text`).
|
|
1278
1271
|
|
|
@@ -1388,12 +1381,6 @@ const text = await ctx.ui.editor("Edit:", "prefilled text");
|
|
|
1388
1381
|
ctx.ui.notify("Done!", "info"); // "info" | "warning" | "error"
|
|
1389
1382
|
```
|
|
1390
1383
|
|
|
1391
|
-
**Examples:**
|
|
1392
|
-
- `ctx.ui.select()`: [confirm-destructive.ts](../examples/extensions/confirm-destructive.ts), [dirty-repo-guard.ts](../examples/extensions/dirty-repo-guard.ts), [git-checkpoint.ts](../examples/extensions/git-checkpoint.ts), [permission-gate.ts](../examples/extensions/permission-gate.ts), [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [question.ts](../examples/extensions/question.ts), [questionnaire.ts](../examples/extensions/questionnaire.ts)
|
|
1393
|
-
- `ctx.ui.confirm()`: [confirm-destructive.ts](../examples/extensions/confirm-destructive.ts)
|
|
1394
|
-
- `ctx.ui.editor()`: [handoff.ts](../examples/extensions/handoff.ts)
|
|
1395
|
-
- `ctx.ui.setEditorText()`: [handoff.ts](../examples/extensions/handoff.ts), [qna.ts](../examples/extensions/qna.ts)
|
|
1396
|
-
|
|
1397
1384
|
#### Timed Dialogs with Countdown
|
|
1398
1385
|
|
|
1399
1386
|
Dialogs support a `timeout` option that auto-dismisses with a live countdown display:
|
|
@@ -1481,7 +1468,7 @@ const current = ctx.ui.getEditorText();
|
|
|
1481
1468
|
ctx.ui.setEditorComponent((tui, theme, keybindings) => new VimEditor(tui, theme, keybindings));
|
|
1482
1469
|
ctx.ui.setEditorComponent(undefined); // Restore default editor
|
|
1483
1470
|
|
|
1484
|
-
// Theme management
|
|
1471
|
+
// Theme management (see themes.md for creating themes)
|
|
1485
1472
|
const themes = ctx.ui.getAllThemes(); // [{ name: "dark", path: "/..." | undefined }, ...]
|
|
1486
1473
|
const lightTheme = ctx.ui.getTheme("light"); // Load without switching
|
|
1487
1474
|
const result = ctx.ui.setTheme("light"); // Switch by name
|
|
@@ -1492,14 +1479,6 @@ ctx.ui.setTheme(lightTheme!); // Or switch by Theme object
|
|
|
1492
1479
|
ctx.ui.theme.fg("accent", "styled text"); // Access current theme
|
|
1493
1480
|
```
|
|
1494
1481
|
|
|
1495
|
-
**Examples:**
|
|
1496
|
-
- `ctx.ui.setStatus()`: [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [preset.ts](../examples/extensions/preset.ts), [status-line.ts](../examples/extensions/status-line.ts)
|
|
1497
|
-
- `ctx.ui.setWidget()`: [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts)
|
|
1498
|
-
- `ctx.ui.setFooter()`: [custom-footer.ts](../examples/extensions/custom-footer.ts)
|
|
1499
|
-
- `ctx.ui.setHeader()`: [custom-header.ts](../examples/extensions/custom-header.ts)
|
|
1500
|
-
- `ctx.ui.setEditorComponent()`: [modal-editor.ts](../examples/extensions/modal-editor.ts)
|
|
1501
|
-
- `ctx.ui.setTheme()`: [mac-system-theme.ts](../examples/extensions/mac-system-theme.ts)
|
|
1502
|
-
|
|
1503
1482
|
### Custom Components
|
|
1504
1483
|
|
|
1505
1484
|
For complex UI, use `ctx.ui.custom()`. This temporarily replaces the editor with your component until `done()` is called:
|
|
@@ -1558,8 +1537,6 @@ const result = await ctx.ui.custom<string | null>(
|
|
|
1558
1537
|
|
|
1559
1538
|
See [tui.md](tui.md) for the full `OverlayOptions` API and [overlay-qa-tests.ts](../examples/extensions/overlay-qa-tests.ts) for examples.
|
|
1560
1539
|
|
|
1561
|
-
**Examples:** [handoff.ts](../examples/extensions/handoff.ts), [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [preset.ts](../examples/extensions/preset.ts), [qna.ts](../examples/extensions/qna.ts), [snake.ts](../examples/extensions/snake.ts), [summarize.ts](../examples/extensions/summarize.ts), [todo.ts](../examples/extensions/todo.ts), [tools.ts](../examples/extensions/tools.ts), [overlay-test.ts](../examples/extensions/overlay-test.ts)
|
|
1562
|
-
|
|
1563
1540
|
### Custom Editor
|
|
1564
1541
|
|
|
1565
1542
|
Replace the main input editor with a custom implementation (vim mode, emacs mode, etc.):
|
|
@@ -1601,8 +1578,6 @@ export default function (pi: ExtensionAPI) {
|
|
|
1601
1578
|
|
|
1602
1579
|
See [tui.md](tui.md) Pattern 7 for a complete example with mode indicator.
|
|
1603
1580
|
|
|
1604
|
-
**Examples:** [modal-editor.ts](../examples/extensions/modal-editor.ts)
|
|
1605
|
-
|
|
1606
1581
|
### Message Rendering
|
|
1607
1582
|
|
|
1608
1583
|
Register a custom renderer for messages with your `customType`:
|
|
@@ -1636,7 +1611,7 @@ pi.sendMessage({
|
|
|
1636
1611
|
|
|
1637
1612
|
### Theme Colors
|
|
1638
1613
|
|
|
1639
|
-
All render functions receive a `theme` object
|
|
1614
|
+
All render functions receive a `theme` object. See [themes.md](themes.md) for creating custom themes and the full color palette.
|
|
1640
1615
|
|
|
1641
1616
|
```typescript
|
|
1642
1617
|
// Foreground colors
|
|
@@ -1654,6 +1629,19 @@ theme.italic(text)
|
|
|
1654
1629
|
theme.strikethrough(text)
|
|
1655
1630
|
```
|
|
1656
1631
|
|
|
1632
|
+
For syntax highlighting in custom tool renderers:
|
|
1633
|
+
|
|
1634
|
+
```typescript
|
|
1635
|
+
import { highlightCode, getLanguageFromPath } from "@mariozechner/pi-coding-agent";
|
|
1636
|
+
|
|
1637
|
+
// Highlight code with explicit language
|
|
1638
|
+
const highlighted = highlightCode("const x = 1;", "typescript", theme);
|
|
1639
|
+
|
|
1640
|
+
// Auto-detect language from file path
|
|
1641
|
+
const lang = getLanguageFromPath("/path/to/file.rs"); // "rust"
|
|
1642
|
+
const highlighted = highlightCode(code, lang, theme);
|
|
1643
|
+
```
|
|
1644
|
+
|
|
1657
1645
|
## Error Handling
|
|
1658
1646
|
|
|
1659
1647
|
- Extension errors are logged, agent continues
|
|
@@ -1665,7 +1653,81 @@ theme.strikethrough(text)
|
|
|
1665
1653
|
| Mode | UI Methods | Notes |
|
|
1666
1654
|
|------|-----------|-------|
|
|
1667
1655
|
| Interactive | Full TUI | Normal operation |
|
|
1668
|
-
| RPC | JSON protocol | Host handles UI |
|
|
1656
|
+
| RPC (`--mode rpc`) | JSON protocol | Host handles UI, see [rpc.md](rpc.md) |
|
|
1657
|
+
| JSON (`--mode json`) | No-op | Event stream to stdout, see [json.md](json.md) |
|
|
1669
1658
|
| Print (`-p`) | No-op | Extensions run but can't prompt |
|
|
1670
1659
|
|
|
1671
|
-
In
|
|
1660
|
+
In non-interactive modes, check `ctx.hasUI` before using UI methods.
|
|
1661
|
+
|
|
1662
|
+
## Examples Reference
|
|
1663
|
+
|
|
1664
|
+
All examples in [examples/extensions/](../examples/extensions/).
|
|
1665
|
+
|
|
1666
|
+
| Example | Description | Key APIs |
|
|
1667
|
+
|---------|-------------|----------|
|
|
1668
|
+
| **Tools** |||
|
|
1669
|
+
| `hello.ts` | Minimal tool registration | `registerTool` |
|
|
1670
|
+
| `question.ts` | Tool with user interaction | `registerTool`, `ui.select` |
|
|
1671
|
+
| `questionnaire.ts` | Multi-step wizard tool | `registerTool`, `ui.custom` |
|
|
1672
|
+
| `todo.ts` | Stateful tool with persistence | `registerTool`, `appendEntry`, `renderResult`, session events |
|
|
1673
|
+
| `truncated-tool.ts` | Output truncation example | `registerTool`, `truncateHead` |
|
|
1674
|
+
| `tool-override.ts` | Override built-in read tool | `registerTool` (same name as built-in) |
|
|
1675
|
+
| **Commands** |||
|
|
1676
|
+
| `pirate.ts` | Modify system prompt per-turn | `registerCommand`, `before_agent_start` |
|
|
1677
|
+
| `summarize.ts` | Conversation summary command | `registerCommand`, `ui.custom` |
|
|
1678
|
+
| `handoff.ts` | Cross-provider model handoff | `registerCommand`, `ui.editor`, `ui.custom` |
|
|
1679
|
+
| `qna.ts` | Q&A with custom UI | `registerCommand`, `ui.custom`, `setEditorText` |
|
|
1680
|
+
| `send-user-message.ts` | Inject user messages | `registerCommand`, `sendUserMessage` |
|
|
1681
|
+
| `shutdown-command.ts` | Graceful shutdown command | `registerCommand`, `shutdown()` |
|
|
1682
|
+
| **Events & Gates** |||
|
|
1683
|
+
| `permission-gate.ts` | Block dangerous commands | `on("tool_call")`, `ui.confirm` |
|
|
1684
|
+
| `protected-paths.ts` | Block writes to specific paths | `on("tool_call")` |
|
|
1685
|
+
| `confirm-destructive.ts` | Confirm session changes | `on("session_before_switch")`, `on("session_before_fork")` |
|
|
1686
|
+
| `dirty-repo-guard.ts` | Warn on dirty git repo | `on("session_before_*")`, `exec` |
|
|
1687
|
+
| `input-transform.ts` | Transform user input | `on("input")` |
|
|
1688
|
+
| `model-status.ts` | React to model changes | `on("model_select")`, `setStatus` |
|
|
1689
|
+
| `claude-rules.ts` | Load rules from files | `on("session_start")`, `on("before_agent_start")` |
|
|
1690
|
+
| `file-trigger.ts` | File watcher triggers messages | `sendMessage` |
|
|
1691
|
+
| **Compaction & Sessions** |||
|
|
1692
|
+
| `custom-compaction.ts` | Custom compaction summary | `on("session_before_compact")` |
|
|
1693
|
+
| `trigger-compact.ts` | Trigger compaction manually | `compact()` |
|
|
1694
|
+
| `git-checkpoint.ts` | Git stash on turns | `on("turn_end")`, `on("session_fork")`, `exec` |
|
|
1695
|
+
| `auto-commit-on-exit.ts` | Commit on shutdown | `on("session_shutdown")`, `exec` |
|
|
1696
|
+
| **UI Components** |||
|
|
1697
|
+
| `status-line.ts` | Footer status indicator | `setStatus`, session events |
|
|
1698
|
+
| `custom-footer.ts` | Replace footer entirely | `registerCommand`, `setFooter` |
|
|
1699
|
+
| `custom-header.ts` | Replace startup header | `on("session_start")`, `setHeader` |
|
|
1700
|
+
| `modal-editor.ts` | Vim-style modal editor | `setEditorComponent`, `CustomEditor` |
|
|
1701
|
+
| `rainbow-editor.ts` | Custom editor styling | `setEditorComponent` |
|
|
1702
|
+
| `widget-placement.ts` | Widget above/below editor | `setWidget` |
|
|
1703
|
+
| `overlay-test.ts` | Overlay components | `ui.custom` with overlay options |
|
|
1704
|
+
| `overlay-qa-tests.ts` | Comprehensive overlay tests | `ui.custom`, all overlay options |
|
|
1705
|
+
| `notify.ts` | Simple notifications | `ui.notify` |
|
|
1706
|
+
| `timed-confirm.ts` | Dialogs with timeout | `ui.confirm` with timeout/signal |
|
|
1707
|
+
| `mac-system-theme.ts` | Auto-switch theme | `setTheme`, `exec` |
|
|
1708
|
+
| **Complex Extensions** |||
|
|
1709
|
+
| `plan-mode/` | Full plan mode implementation | All event types, `registerCommand`, `registerShortcut`, `registerFlag`, `setStatus`, `setWidget`, `sendMessage`, `setActiveTools` |
|
|
1710
|
+
| `preset.ts` | Saveable presets (model, tools, thinking) | `registerCommand`, `registerShortcut`, `registerFlag`, `setModel`, `setActiveTools`, `setThinkingLevel`, `appendEntry` |
|
|
1711
|
+
| `tools.ts` | Toggle tools on/off UI | `registerCommand`, `setActiveTools`, `SettingsList`, session events |
|
|
1712
|
+
| **Remote & Sandbox** |||
|
|
1713
|
+
| `ssh.ts` | SSH remote execution | `registerFlag`, `on("user_bash")`, `on("before_agent_start")`, tool operations |
|
|
1714
|
+
| `interactive-shell.ts` | Persistent shell session | `on("user_bash")` |
|
|
1715
|
+
| `sandbox/` | Sandboxed tool execution | Tool operations |
|
|
1716
|
+
| `subagent/` | Spawn sub-agents | `registerTool`, `exec` |
|
|
1717
|
+
| **Games** |||
|
|
1718
|
+
| `snake.ts` | Snake game | `registerCommand`, `ui.custom`, keyboard handling |
|
|
1719
|
+
| `space-invaders.ts` | Space Invaders game | `registerCommand`, `ui.custom` |
|
|
1720
|
+
| `doom-overlay/` | Doom in overlay | `ui.custom` with overlay |
|
|
1721
|
+
| **Providers** |||
|
|
1722
|
+
| `custom-provider-anthropic/` | Custom Anthropic proxy | `registerProvider` |
|
|
1723
|
+
| `custom-provider-gitlab-duo/` | GitLab Duo integration | `registerProvider` with OAuth |
|
|
1724
|
+
| **Messages & Communication** |||
|
|
1725
|
+
| `message-renderer.ts` | Custom message rendering | `registerMessageRenderer`, `sendMessage` |
|
|
1726
|
+
| `event-bus.ts` | Inter-extension events | `pi.events` |
|
|
1727
|
+
| **Session Metadata** |||
|
|
1728
|
+
| `session-name.ts` | Name sessions for selector | `setSessionName`, `getSessionName` |
|
|
1729
|
+
| `bookmark.ts` | Bookmark entries for /tree | `setLabel` |
|
|
1730
|
+
| **Misc** |||
|
|
1731
|
+
| `antigravity-image-gen.ts` | Image generation tool | `registerTool`, Google Antigravity |
|
|
1732
|
+
| `inline-bash.ts` | Inline bash in tool calls | `on("tool_call")` |
|
|
1733
|
+
| `with-deps/` | Extension with npm dependencies | Package structure with `package.json` |
|
|
Binary file
|
|
Binary file
|
|
Binary file
|