@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.
Files changed (207) hide show
  1. package/CHANGELOG.md +99 -1
  2. package/README.md +310 -1230
  3. package/dist/cli/args.d.ts +5 -0
  4. package/dist/cli/args.d.ts.map +1 -1
  5. package/dist/cli/args.js +57 -23
  6. package/dist/cli/args.js.map +1 -1
  7. package/dist/cli/config-selector.d.ts +14 -0
  8. package/dist/cli/config-selector.d.ts.map +1 -0
  9. package/dist/cli/config-selector.js +31 -0
  10. package/dist/cli/config-selector.js.map +1 -0
  11. package/dist/cli/session-picker.d.ts.map +1 -1
  12. package/dist/cli/session-picker.js +1 -1
  13. package/dist/cli/session-picker.js.map +1 -1
  14. package/dist/core/agent-session.d.ts +53 -34
  15. package/dist/core/agent-session.d.ts.map +1 -1
  16. package/dist/core/agent-session.js +262 -67
  17. package/dist/core/agent-session.js.map +1 -1
  18. package/dist/core/auth-storage.d.ts +8 -18
  19. package/dist/core/auth-storage.d.ts.map +1 -1
  20. package/dist/core/auth-storage.js +39 -55
  21. package/dist/core/auth-storage.js.map +1 -1
  22. package/dist/core/bash-executor.d.ts.map +1 -1
  23. package/dist/core/bash-executor.js +2 -1
  24. package/dist/core/bash-executor.js.map +1 -1
  25. package/dist/core/diagnostics.d.ts +15 -0
  26. package/dist/core/diagnostics.d.ts.map +1 -0
  27. package/dist/core/diagnostics.js +2 -0
  28. package/dist/core/diagnostics.js.map +1 -0
  29. package/dist/core/export-html/template.css +9 -0
  30. package/dist/core/export-html/template.js +6 -4
  31. package/dist/core/extensions/index.d.ts +1 -1
  32. package/dist/core/extensions/index.d.ts.map +1 -1
  33. package/dist/core/extensions/index.js.map +1 -1
  34. package/dist/core/extensions/loader.d.ts +1 -1
  35. package/dist/core/extensions/loader.d.ts.map +1 -1
  36. package/dist/core/extensions/loader.js +10 -1
  37. package/dist/core/extensions/loader.js.map +1 -1
  38. package/dist/core/extensions/runner.d.ts +9 -3
  39. package/dist/core/extensions/runner.d.ts.map +1 -1
  40. package/dist/core/extensions/runner.js +39 -12
  41. package/dist/core/extensions/runner.js.map +1 -1
  42. package/dist/core/extensions/types.d.ts +112 -1
  43. package/dist/core/extensions/types.d.ts.map +1 -1
  44. package/dist/core/extensions/types.js.map +1 -1
  45. package/dist/core/footer-data-provider.d.ts +9 -2
  46. package/dist/core/footer-data-provider.d.ts.map +1 -1
  47. package/dist/core/footer-data-provider.js +13 -0
  48. package/dist/core/footer-data-provider.js.map +1 -1
  49. package/dist/core/model-registry.d.ts +42 -2
  50. package/dist/core/model-registry.d.ts.map +1 -1
  51. package/dist/core/model-registry.js +154 -44
  52. package/dist/core/model-registry.js.map +1 -1
  53. package/dist/core/model-resolver.d.ts.map +1 -1
  54. package/dist/core/model-resolver.js +3 -2
  55. package/dist/core/model-resolver.js.map +1 -1
  56. package/dist/core/package-manager.d.ts +129 -0
  57. package/dist/core/package-manager.d.ts.map +1 -0
  58. package/dist/core/package-manager.js +1148 -0
  59. package/dist/core/package-manager.js.map +1 -0
  60. package/dist/core/prompt-templates.d.ts +6 -0
  61. package/dist/core/prompt-templates.d.ts.map +1 -1
  62. package/dist/core/prompt-templates.js +114 -54
  63. package/dist/core/prompt-templates.js.map +1 -1
  64. package/dist/core/resource-loader.d.ts +160 -0
  65. package/dist/core/resource-loader.d.ts.map +1 -0
  66. package/dist/core/resource-loader.js +604 -0
  67. package/dist/core/resource-loader.js.map +1 -0
  68. package/dist/core/sdk.d.ts +14 -105
  69. package/dist/core/sdk.d.ts.map +1 -1
  70. package/dist/core/sdk.js +52 -304
  71. package/dist/core/sdk.js.map +1 -1
  72. package/dist/core/session-manager.d.ts.map +1 -1
  73. package/dist/core/session-manager.js +45 -1
  74. package/dist/core/session-manager.js.map +1 -1
  75. package/dist/core/settings-manager.d.ts +34 -16
  76. package/dist/core/settings-manager.d.ts.map +1 -1
  77. package/dist/core/settings-manager.js +104 -25
  78. package/dist/core/settings-manager.js.map +1 -1
  79. package/dist/core/skills.d.ts +18 -10
  80. package/dist/core/skills.d.ts.map +1 -1
  81. package/dist/core/skills.js +126 -93
  82. package/dist/core/skills.js.map +1 -1
  83. package/dist/core/system-prompt.d.ts +3 -27
  84. package/dist/core/system-prompt.d.ts.map +1 -1
  85. package/dist/core/system-prompt.js +16 -103
  86. package/dist/core/system-prompt.js.map +1 -1
  87. package/dist/core/tools/bash.d.ts.map +1 -1
  88. package/dist/core/tools/bash.js +2 -1
  89. package/dist/core/tools/bash.js.map +1 -1
  90. package/dist/core/tools/read.d.ts.map +1 -1
  91. package/dist/core/tools/read.js +4 -4
  92. package/dist/core/tools/read.js.map +1 -1
  93. package/dist/index.d.ts +12 -7
  94. package/dist/index.d.ts.map +1 -1
  95. package/dist/index.js +8 -6
  96. package/dist/index.js.map +1 -1
  97. package/dist/main.d.ts.map +1 -1
  98. package/dist/main.js +209 -97
  99. package/dist/main.js.map +1 -1
  100. package/dist/modes/interactive/components/bordered-loader.d.ts +5 -1
  101. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  102. package/dist/modes/interactive/components/bordered-loader.js +29 -9
  103. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  104. package/dist/modes/interactive/components/config-selector.d.ts +71 -0
  105. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -0
  106. package/dist/modes/interactive/components/config-selector.js +468 -0
  107. package/dist/modes/interactive/components/config-selector.js.map +1 -0
  108. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  109. package/dist/modes/interactive/components/footer.js +4 -0
  110. package/dist/modes/interactive/components/footer.js.map +1 -1
  111. package/dist/modes/interactive/components/index.d.ts +1 -0
  112. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  113. package/dist/modes/interactive/components/index.js +1 -0
  114. package/dist/modes/interactive/components/index.js.map +1 -1
  115. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  116. package/dist/modes/interactive/components/oauth-selector.js +3 -4
  117. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  118. package/dist/modes/interactive/components/session-selector.d.ts +18 -1
  119. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  120. package/dist/modes/interactive/components/session-selector.js +195 -87
  121. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  122. package/dist/modes/interactive/components/skill-invocation-message.d.ts +17 -0
  123. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -0
  124. package/dist/modes/interactive/components/skill-invocation-message.js +47 -0
  125. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -0
  126. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  127. package/dist/modes/interactive/components/tool-execution.js +5 -5
  128. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  129. package/dist/modes/interactive/interactive-mode.d.ts +42 -2
  130. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  131. package/dist/modes/interactive/interactive-mode.js +535 -200
  132. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  133. package/dist/modes/interactive/theme/dark.json +1 -1
  134. package/dist/modes/interactive/theme/light.json +1 -1
  135. package/dist/modes/interactive/theme/theme-schema.json +8 -1
  136. package/dist/modes/interactive/theme/theme.d.ts +8 -1
  137. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  138. package/dist/modes/interactive/theme/theme.js +72 -25
  139. package/dist/modes/interactive/theme/theme.js.map +1 -1
  140. package/dist/modes/print-mode.d.ts.map +1 -1
  141. package/dist/modes/print-mode.js +25 -89
  142. package/dist/modes/print-mode.js.map +1 -1
  143. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  144. package/dist/modes/rpc/rpc-mode.js +32 -92
  145. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  146. package/dist/utils/git.d.ts +2 -0
  147. package/dist/utils/git.d.ts.map +1 -0
  148. package/dist/utils/git.js +6 -0
  149. package/dist/utils/git.js.map +1 -0
  150. package/dist/utils/shell.d.ts +1 -0
  151. package/dist/utils/shell.d.ts.map +1 -1
  152. package/dist/utils/shell.js +14 -1
  153. package/dist/utils/shell.js.map +1 -1
  154. package/dist/utils/sleep.d.ts +5 -0
  155. package/dist/utils/sleep.d.ts.map +1 -0
  156. package/dist/utils/sleep.js +17 -0
  157. package/dist/utils/sleep.js.map +1 -0
  158. package/docs/compaction.md +23 -21
  159. package/docs/custom-provider.md +538 -0
  160. package/docs/development.md +69 -0
  161. package/docs/extensions.md +180 -118
  162. package/docs/images/doom-extension.png +0 -0
  163. package/docs/images/interactive-mode.png +0 -0
  164. package/docs/images/tree-view.png +0 -0
  165. package/docs/json.md +79 -0
  166. package/docs/keybindings.md +162 -0
  167. package/docs/models.md +193 -0
  168. package/docs/packages.md +163 -0
  169. package/docs/prompt-templates.md +67 -0
  170. package/docs/providers.md +147 -0
  171. package/docs/sdk.md +111 -178
  172. package/docs/session.md +167 -16
  173. package/docs/settings.md +216 -0
  174. package/docs/shell-aliases.md +13 -0
  175. package/docs/skills.md +111 -202
  176. package/docs/terminal-setup.md +65 -0
  177. package/docs/themes.md +295 -0
  178. package/docs/tui.md +36 -5
  179. package/docs/windows.md +17 -0
  180. package/examples/README.md +1 -0
  181. package/examples/extensions/README.md +22 -2
  182. package/examples/extensions/bookmark.ts +50 -0
  183. package/examples/extensions/custom-provider-anthropic/index.ts +604 -0
  184. package/examples/extensions/custom-provider-anthropic/package-lock.json +24 -0
  185. package/examples/extensions/custom-provider-anthropic/package.json +19 -0
  186. package/examples/extensions/custom-provider-gitlab-duo/index.ts +349 -0
  187. package/examples/extensions/custom-provider-gitlab-duo/package.json +16 -0
  188. package/examples/extensions/custom-provider-gitlab-duo/test.ts +82 -0
  189. package/examples/extensions/doom-overlay/doom/build.sh +1 -1
  190. package/examples/extensions/event-bus.ts +43 -0
  191. package/examples/extensions/message-renderer.ts +59 -0
  192. package/examples/extensions/session-name.ts +27 -0
  193. package/examples/extensions/with-deps/package-lock.json +2 -2
  194. package/examples/extensions/with-deps/package.json +1 -1
  195. package/examples/sdk/02-custom-model.ts +3 -3
  196. package/examples/sdk/03-custom-prompt.ts +20 -9
  197. package/examples/sdk/04-skills.ts +26 -27
  198. package/examples/sdk/06-extensions.ts +15 -6
  199. package/examples/sdk/07-context-files.ts +22 -18
  200. package/examples/sdk/08-prompt-templates.ts +19 -14
  201. package/examples/sdk/09-api-keys-and-oauth.ts +5 -12
  202. package/examples/sdk/10-settings.ts +3 -3
  203. package/examples/sdk/12-full-control.ts +16 -7
  204. package/examples/sdk/README.md +24 -30
  205. package/package.json +4 -4
  206. package/docs/theme.md +0 -617
  207. package/examples/extensions/chalk-logger.ts +0 -26
package/README.md CHANGED
@@ -9,1449 +9,529 @@
9
9
  <a href="https://github.com/badlogic/pi-mono/actions/workflows/ci.yml"><img alt="Build status" src="https://img.shields.io/github/actions/workflow/status/badlogic/pi-mono/ci.yml?style=flat-square&branch=main" /></a>
10
10
  </p>
11
11
 
12
- A terminal-based coding agent with multi-model support, mid-session model switching, and a simple CLI for headless coding tasks.
12
+ Pi is a minimal terminal coding harness. Adapt pi to your workflows, not the other way around, without having to fork and modify pi internals. Extend it with TypeScript [Extensions](#extensions), [Skills](#skills), [Prompt Templates](#prompt-templates), and [Themes](#themes). Put your extensions, skills, prompt templates, and themes in [Pi Packages](#pi-packages) and share them with others via npm or git.
13
13
 
14
- Works on Linux, macOS, and Windows (requires bash; see [Windows Setup](#windows-setup)). [Separately maintained port](https://github.com/VaclavSynacek/pi-coding-agent-termux) works on Termux/Android.
14
+ Pi ships with powerful defaults but skips features like sub agents and plan mode. Instead, you can ask pi to build what you want or install a third party pi package that matches your workflow.
15
+
16
+ Pi runs in four modes: interactive, print or JSON, RPC for process integration, and an SDK for embedding in your own apps. See [clawdbot/clawdbot](https://github.com/clawdbot/clawdbot) for a real-world SDK integration.
15
17
 
16
18
  ## Table of Contents
17
19
 
18
- - [Getting Started](#getting-started)
19
- - [Installation](#installation)
20
- - [Windows Setup](#windows-setup)
21
- - [Terminal Setup](#terminal-setup)
22
- - [API Keys & OAuth](#api-keys--oauth)
23
- - [Quick Start](#quick-start)
24
- - [Usage](#usage)
25
- - [Slash Commands](#slash-commands)
26
- - [Editor Features](#editor-features)
20
+ - [Quick Start](#quick-start)
21
+ - [Providers & Models](#providers--models)
22
+ - [Interactive Mode](#interactive-mode)
23
+ - [Editor](#editor)
24
+ - [Commands](#commands)
27
25
  - [Keyboard Shortcuts](#keyboard-shortcuts)
28
- - [Custom Keybindings](#custom-keybindings)
29
- - [Bash Mode](#bash-mode)
30
- - [Image Support](#image-support)
26
+ - [Message Queue](#message-queue)
31
27
  - [Sessions](#sessions)
32
- - [Session Management](#session-management)
33
- - [Context Compaction](#context-compaction)
34
28
  - [Branching](#branching)
35
- - [Configuration](#configuration)
36
- - [Project Context Files](#project-context-files)
37
- - [Custom System Prompt](#custom-system-prompt)
38
- - [Custom Models and Providers](#custom-models-and-providers)
39
- - [Settings File](#settings-file)
29
+ - [Compaction](#compaction)
30
+ - [Settings](#settings)
31
+ - [Context Files](#context-files)
40
32
  - [Customization](#customization)
41
- - [Themes](#themes)
42
33
  - [Prompt Templates](#prompt-templates)
43
34
  - [Skills](#skills)
44
35
  - [Extensions](#extensions)
45
- - [CLI Reference](#cli-reference)
46
- - [Tools](#tools)
36
+ - [Themes](#themes)
37
+ - [Pi Packages](#pi-packages)
47
38
  - [Programmatic Usage](#programmatic-usage)
48
- - [SDK](#sdk)
49
- - [RPC Mode](#rpc-mode)
50
- - [HTML Export](#html-export)
51
39
  - [Philosophy](#philosophy)
52
- - [Development](#development)
53
- - [License](#license)
40
+ - [CLI Reference](#cli-reference)
54
41
 
55
42
  ---
56
43
 
57
- ## Getting Started
58
-
59
- ### Installation
60
-
61
- **npm (recommended):**
44
+ ## Quick Start
62
45
 
63
46
  ```bash
64
47
  npm install -g @mariozechner/pi-coding-agent
65
48
  ```
66
49
 
67
- **Standalone binary:**
68
-
69
- Download from [GitHub Releases](https://github.com/badlogic/pi-mono/releases):
70
-
71
- | Platform | Archive |
72
- |----------|---------|
73
- | macOS Apple Silicon | `pi-darwin-arm64.tar.gz` |
74
- | macOS Intel | `pi-darwin-x64.tar.gz` |
75
- | Linux x64 | `pi-linux-x64.tar.gz` |
76
- | Linux ARM64 | `pi-linux-arm64.tar.gz` |
77
- | Windows x64 | `pi-windows-x64.zip` |
50
+ Authenticate with an API key:
78
51
 
79
52
  ```bash
80
- # macOS/Linux
81
- tar -xzf pi-darwin-arm64.tar.gz
82
- ./pi
83
-
84
- # Windows
85
- unzip pi-windows-x64.zip
86
- pi.exe
87
- ```
88
-
89
- **macOS note:** The binary is unsigned. If blocked, run: `xattr -c ./pi`
90
-
91
- **Build from source** (requires [Bun](https://bun.sh) 1.0+):
92
-
93
- ```bash
94
- git clone https://github.com/badlogic/pi-mono.git
95
- cd pi-mono && npm install && npm run build
96
- cd packages/coding-agent && npm run build:binary
97
- ./dist/pi
98
- ```
99
-
100
- ### Windows Setup
101
-
102
- Pi requires a bash shell on Windows. Checked locations (in order):
103
-
104
- 1. Custom path from `~/.pi/agent/settings.json`
105
- 2. Git Bash (`C:\Program Files\Git\bin\bash.exe`)
106
- 3. `bash.exe` on PATH (Cygwin, MSYS2, WSL)
107
-
108
- For most users, [Git for Windows](https://git-scm.com/download/win) is sufficient.
109
-
110
- **Custom shell path:**
111
-
112
- ```json
113
- // ~/.pi/agent/settings.json
114
- {
115
- "shellPath": "C:\\cygwin64\\bin\\bash.exe"
116
- }
117
- ```
118
-
119
- **Alias expansion:** Pi runs bash in non-interactive mode (`bash -c`), which doesn't expand aliases by default. To enable your shell aliases:
120
-
121
- ```json
122
- // ~/.pi/agent/settings.json
123
- {
124
- "shellCommandPrefix": "shopt -s expand_aliases\neval \"$(grep '^alias ' ~/.zshrc)\""
125
- }
126
- ```
127
-
128
- Adjust the path (`~/.zshrc`, `~/.bashrc`, etc.) to match your shell config.
129
-
130
- ### Terminal Setup
131
-
132
- Pi uses the [Kitty keyboard protocol](https://sw.kovidgoyal.net/kitty/keyboard-protocol/) for reliable modifier key detection. Most modern terminals support this protocol, but some require configuration.
133
-
134
- **Kitty, iTerm2:** Work out of the box.
135
-
136
- **Ghostty:** Add to your Ghostty config (`~/.config/ghostty/config`):
137
-
138
- ```
139
- keybind = alt+backspace=text:\x1b\x7f
140
- keybind = shift+enter=text:\n
141
- ```
142
-
143
- **wezterm:** Create `~/.wezterm.lua`:
144
-
145
- ```lua
146
- local wezterm = require 'wezterm'
147
- local config = wezterm.config_builder()
148
- config.enable_kitty_keyboard = true
149
- return config
150
- ```
151
-
152
- **VS Code (Integrated Terminal):** Add to `keybindings.json` to enable `Shift+Enter` for multi-line input:
153
-
154
- ```json
155
- {
156
- "key": "shift+enter",
157
- "command": "workbench.action.terminal.sendSequence",
158
- "args": { "text": "\u001b[13;2u" },
159
- "when": "terminalFocus"
160
- }
161
- ```
162
-
163
- **Windows Terminal:** Add to `settings.json` (Ctrl+Shift+, or Settings → Open JSON file):
164
-
165
- ```json
166
- {
167
- "actions": [
168
- {
169
- "command": { "action": "sendInput", "input": "\u001b[13;2u" },
170
- "keys": "shift+enter"
171
- }
172
- ]
173
- }
174
- ```
175
-
176
- If you already have an `actions` array, add the object to it.
177
-
178
- **IntelliJ IDEA (Integrated Terminal):** The built-in terminal has limited escape sequence support. Note that Shift+Enter cannot be distinguished from Enter in IntelliJ's terminal. If you want the hardware cursor visible, set `PI_HARDWARE_CURSOR=1` before running pi (disabled by default for compatibility). Consider using a dedicated terminal emulator for the best experience.
179
-
180
- ### API Keys & OAuth
181
-
182
- **Option 1: Auth file** (recommended)
183
-
184
- Add API keys to `~/.pi/agent/auth.json`:
185
-
186
- ```json
187
- {
188
- "anthropic": { "type": "api_key", "key": "sk-ant-..." },
189
- "openai": { "type": "api_key", "key": "sk-..." },
190
- "google": { "type": "api_key", "key": "..." }
191
- }
53
+ export ANTHROPIC_API_KEY=sk-ant-...
54
+ pi
192
55
  ```
193
56
 
194
- **Option 2: Environment variables**
195
-
196
- | Provider | Auth Key | Environment Variable |
197
- |----------|--------------|---------------------|
198
- | Anthropic | `anthropic` | `ANTHROPIC_API_KEY` |
199
- | OpenAI | `openai` | `OPENAI_API_KEY` |
200
- | Google | `google` | `GEMINI_API_KEY` |
201
- | Mistral | `mistral` | `MISTRAL_API_KEY` |
202
- | Groq | `groq` | `GROQ_API_KEY` |
203
- | Cerebras | `cerebras` | `CEREBRAS_API_KEY` |
204
- | xAI | `xai` | `XAI_API_KEY` |
205
- | OpenRouter | `openrouter` | `OPENROUTER_API_KEY` |
206
- | Vercel AI Gateway | `vercel-ai-gateway` | `AI_GATEWAY_API_KEY` |
207
- | ZAI | `zai` | `ZAI_API_KEY` |
208
- | OpenCode Zen | `opencode` | `OPENCODE_API_KEY` |
209
- | MiniMax | `minimax` | `MINIMAX_API_KEY` |
210
- | MiniMax (China) | `minimax-cn` | `MINIMAX_CN_API_KEY` |
211
-
212
- Auth file keys take priority over environment variables.
213
-
214
- **OAuth Providers:**
215
-
216
- Use `/login` to authenticate with subscription-based or free-tier providers:
217
-
218
- | Provider | Models | Cost |
219
- |----------|--------|------|
220
- | Anthropic (Claude Pro/Max) | Claude models via your subscription | Subscription |
221
- | GitHub Copilot | GPT-4o, Claude, Gemini via Copilot subscription | Subscription |
222
- | Google Gemini CLI | Gemini 2.0/2.5 models | Free (Google account) |
223
- | Google Antigravity | Gemini 3, Claude, GPT-OSS | Free (Google account) |
224
- | OpenAI Codex (ChatGPT Plus/Pro) | Codex models via ChatGPT subscription | Subscription |
57
+ Or use your existing subscription:
225
58
 
226
59
  ```bash
227
60
  pi
228
- /login # Select provider, authorize in browser
61
+ /login # Then select provider
229
62
  ```
230
63
 
231
- **Note:** `/login` replaces any existing API key for that provider with OAuth credentials in `auth.json`.
232
-
233
- **GitHub Copilot notes:**
234
- - Press Enter for github.com, or enter your GitHub Enterprise Server domain
235
- - If you get "model not supported" error, enable it in VS Code: Copilot Chat → model selector → select model → "Enable"
236
-
237
- **Google providers notes:**
238
- - Gemini CLI uses the production Cloud Code Assist endpoint (standard Gemini models)
239
- - Antigravity uses a sandbox endpoint with access to Gemini 3, Claude (sonnet/opus thinking), and GPT-OSS models
240
- - Both are free with any Google account, subject to rate limits
241
- - Paid Cloud Code Assist subscriptions: set `GOOGLE_CLOUD_PROJECT` or `GOOGLE_CLOUD_PROJECT_ID` env var to your project ID
64
+ Then just talk to pi. By default, pi gives the model four tools: `read`, `write`, `edit`, and `bash`. The model uses these to fulfill your requests. Add capabilities via [skills](#skills), [prompt templates](#prompt-templates), [extensions](#extensions), or [pi packages](#pi-packages).
242
65
 
243
- **OpenAI Codex notes:**
244
- - Requires ChatGPT Plus/Pro OAuth (`/login openai-codex`)
245
- - Prompt cache stored under `~/.pi/agent/cache/openai-codex/`
246
- - Intended for personal use with your own subscription; not for resale or multi-user services. For production, use the OpenAI Platform API.
247
-
248
- Credentials stored in `~/.pi/agent/auth.json`. Use `/logout` to clear.
249
-
250
- **Troubleshooting (OAuth):**
251
- - **Port 1455 in use:** Close the conflicting process or paste the auth code/URL when prompted.
252
- - **Token expired / refresh failed:** Run `/login` again for the provider to refresh credentials.
253
- - **Usage limits (429):** Wait for the reset window; pi will surface a friendly message with the approximate retry time.
254
-
255
- **Amazon Bedrock:**
256
-
257
- Amazon Bedrock supports multiple authentication methods:
258
-
259
- ```bash
260
- # Option 1: AWS Profile (from ~/.aws/credentials)
261
- export AWS_PROFILE=your-profile-name
66
+ **Platform notes:** [Windows](docs/windows.md) | [Terminal setup](docs/terminal-setup.md) | [Shell aliases](docs/shell-aliases.md)
262
67
 
263
- # Option 2: IAM Access Keys
264
- export AWS_ACCESS_KEY_ID=AKIA...
265
- export AWS_SECRET_ACCESS_KEY=...
68
+ ---
266
69
 
267
- # Option 3: Bedrock API Key (bearer token)
268
- export AWS_BEARER_TOKEN_BEDROCK=...
70
+ ## Providers & Models
71
+
72
+ For each built-in provider, pi maintains a list of tool-capable models, updated with every release. Authenticate via subscription (`/login`) or API key, then select any model from that provider via `/model` (or Ctrl+L).
73
+
74
+ **Subscriptions:**
75
+ - Anthropic Claude Pro/Max
76
+ - OpenAI ChatGPT Plus/Pro (Codex)
77
+ - GitHub Copilot
78
+ - Google Gemini CLI
79
+ - Google Antigravity
80
+
81
+ **API keys:**
82
+ - Anthropic
83
+ - OpenAI
84
+ - Azure OpenAI
85
+ - Google Gemini
86
+ - Google Vertex
87
+ - Amazon Bedrock
88
+ - Mistral
89
+ - Groq
90
+ - Cerebras
91
+ - xAI
92
+ - OpenRouter
93
+ - Vercel AI Gateway
94
+ - ZAI
95
+ - OpenCode Zen
96
+ - MiniMax
97
+
98
+ See [docs/providers.md](docs/providers.md) for detailed setup instructions.
99
+
100
+ **Custom providers & models:** Add providers via `~/.pi/agent/models.json` if they speak a supported API (OpenAI, Anthropic, Google). For custom APIs or OAuth, use extensions. See [docs/models.md](docs/models.md) and [docs/custom-provider.md](docs/custom-provider.md).
269
101
 
270
- # Optional: Set region (defaults to us-east-1)
271
- export AWS_REGION=us-east-1
102
+ ---
272
103
 
273
- pi --provider amazon-bedrock --model global.anthropic.claude-sonnet-4-5-20250929-v1:0
274
- ```
104
+ ## Interactive Mode
275
105
 
276
- See [Supported foundation models in Amazon Bedrock](https://docs.aws.amazon.com/bedrock/latest/userguide/models-supported.html).
106
+ <p align="center"><img src="docs/images/interactive-mode.png" alt="Interactive Mode" width="600"></p>
277
107
 
278
- ### Quick Start
108
+ The interface from top to bottom:
279
109
 
280
- ```bash
281
- export ANTHROPIC_API_KEY=sk-ant-...
282
- pi
283
- ```
110
+ - **Startup header** - Shows shortcuts (`/hotkeys` for all), loaded AGENTS.md files, prompt templates, skills, and extensions
111
+ - **Messages** - Your messages, assistant responses, tool calls and results, notifications, errors, and extension UI
112
+ - **Editor** - Where you type; border color indicates thinking level
113
+ - **Footer** - Working directory, session name, total token/cache usage, cost, context usage, current model
284
114
 
285
- Then chat:
115
+ The editor can be temporarily replaced by other UI, like built-in `/settings` or custom UI from extensions (e.g., a Q&A tool that lets the user answer model questions in a structured format). [Extensions](#extensions) can also replace the editor, add widgets above/below it, a status line, custom footer, or overlays.
286
116
 
287
- ```
288
- You: Create a simple Express server in src/server.ts
289
- ```
117
+ ### Editor
290
118
 
291
- The agent reads, writes, and edits files, and executes commands via bash.
119
+ | Feature | How |
120
+ |---------|-----|
121
+ | File reference | Type `@` to fuzzy-search project files |
122
+ | Path completion | Tab to complete paths |
123
+ | Multi-line | Shift+Enter (or Ctrl+Enter on Windows Terminal) |
124
+ | Images | Ctrl+V to paste, or drag onto terminal |
125
+ | Bash commands | `!command` runs and sends output to LLM, `!!command` runs without sending |
292
126
 
293
- ---
127
+ Standard editing keybindings for delete word, undo, etc. See [docs/keybindings.md](docs/keybindings.md).
294
128
 
295
- ## Usage
129
+ ### Commands
296
130
 
297
- ### Slash Commands
131
+ Type `/` in the editor to trigger commands. [Extensions](#extensions) can register custom commands, [skills](#skills) are available as `/skill:name`, and [prompt templates](#prompt-templates) expand via `/templatename`.
298
132
 
299
133
  | Command | Description |
300
134
  |---------|-------------|
301
- | `/settings` | Open settings menu (thinking, theme, message delivery modes, toggles) |
302
- | `/model` | Switch models mid-session. Use `/model <search>` or `provider/model` to prefilter/disambiguate. |
135
+ | `/login`, `/logout` | OAuth authentication |
136
+ | `/model` | Switch models |
303
137
  | `/scoped-models` | Enable/disable models for Ctrl+P cycling |
304
- | `/export [file]` | Export session to self-contained HTML |
305
- | `/share` | Upload session as secret GitHub gist, get shareable URL (requires `gh` CLI) |
306
- | `/session` | Show session info: path, message counts, token usage, cost |
307
- | `/name <name>` | Set session display name (shown in session selector) |
308
- | `/hotkeys` | Show all keyboard shortcuts |
309
- | `/changelog` | Display full version history |
310
- | `/tree` | Navigate session tree in-place (search, filter, label entries) |
311
- | `/fork` | Create new conversation fork from a previous message |
312
- | `/resume` | Switch to a different session (interactive selector) |
313
- | `/login` | OAuth login for subscription-based models |
314
- | `/logout` | Clear OAuth tokens |
138
+ | `/settings` | Thinking level, theme, message delivery |
139
+ | `/resume` | Pick from previous sessions |
315
140
  | `/new` | Start a new session |
316
- | `/copy` | Copy last agent message to clipboard |
317
- | `/compact [instructions]` | Manually compact conversation context |
318
-
319
- ### Editor Features
320
-
321
- **File reference (`@`):** Type `@` to fuzzy-search project files. Respects `.gitignore`.
322
-
323
- **Path completion (Tab):** Complete relative paths, `../`, `~/`, etc.
324
-
325
- **Drag & drop:** Drag files from your file manager into the terminal.
326
-
327
- **Multi-line paste:** Pasted content is collapsed to `[paste #N <lines> lines]` but sent in full.
328
-
329
- **Message queuing:** Submit messages while the agent is working:
330
- - **Enter** queues a *steering* message, delivered after current tool execution (interrupts remaining tools)
331
- - **Alt+Enter** queues a *follow-up* message, delivered only after the agent finishes all work
332
-
333
- Both modes are configurable via `/settings`: "one-at-a-time" delivers messages one by one waiting for responses, "all" delivers all queued messages at once. Press Escape to abort and restore queued messages to editor.
141
+ | `/name <name>` | Set session display name |
142
+ | `/session` | Show session info (path, tokens, cost) |
143
+ | `/tree` | Jump to any point in the session and continue from there |
144
+ | `/fork` | Create a new session from the current branch |
145
+ | `/compact [prompt]` | Manually compact context, optional custom instructions |
146
+ | `/copy` | Copy last assistant message to clipboard |
147
+ | `/export [file]` | Export session to HTML file |
148
+ | `/share` | Upload as private GitHub gist with shareable HTML link |
149
+ | `/reload` | Reload extensions, skills, prompts, context files (themes hot-reload automatically) |
150
+ | `/hotkeys` | Show all keyboard shortcuts |
151
+ | `/changelog` | Display version history |
152
+ | `/quit`, `/exit` | Quit pi |
334
153
 
335
154
  ### Keyboard Shortcuts
336
155
 
337
- **Navigation:**
338
-
339
- | Key | Action |
340
- |-----|--------|
341
- | Arrow keys | Move cursor / browse history (Up when empty) |
342
- | Option+Left/Right | Move by word |
343
- | Ctrl+A / Home / Cmd+Left | Start of line |
344
- | Ctrl+E / End / Cmd+Right | End of line |
345
-
346
- **Editing:**
156
+ See `/hotkeys` for the full list. Customize via `~/.pi/agent/keybindings.json`. See [docs/keybindings.md](docs/keybindings.md).
347
157
 
348
- | Key | Action |
349
- |-----|--------|
350
- | Enter | Send message |
351
- | Shift+Enter | New line (Ctrl+Enter on Windows Terminal) |
352
- | Ctrl+W / Option+Backspace | Delete word backwards |
353
- | Alt+D / Option+Delete | Delete word forwards |
354
- | Ctrl+U | Delete to start of line |
355
- | Ctrl+K | Delete to end of line |
356
- | Ctrl+Y | Paste most recently deleted text |
357
- | Alt+Y | Cycle through deleted text after pasting |
358
- | Ctrl+- | Undo |
359
-
360
- **Other:**
158
+ **Commonly used:**
361
159
 
362
160
  | Key | Action |
363
161
  |-----|--------|
364
- | Tab | Path completion / accept autocomplete |
365
- | Escape | Cancel autocomplete / abort streaming |
366
- | Ctrl+C | Clear editor (first) / exit (second) |
367
- | Ctrl+D | Exit (when editor is empty) |
368
- | Ctrl+Z | Suspend to background (use `fg` in shell to resume) |
369
- | Shift+Tab | Cycle thinking level |
370
- | Ctrl+P / Shift+Ctrl+P | Cycle models forward/backward (scoped by `--models`) |
162
+ | Ctrl+C | Clear editor |
163
+ | Ctrl+C twice | Quit |
164
+ | Escape | Cancel/abort |
165
+ | Escape twice | Open `/tree` |
371
166
  | Ctrl+L | Open model selector |
372
- | Ctrl+O | Toggle tool output expansion |
373
- | Ctrl+T | Toggle thinking block visibility |
374
- | Ctrl+G | Edit message in external editor (`$VISUAL` or `$EDITOR`) |
375
- | Ctrl+V | Paste image from clipboard |
376
- | Alt+Up | Restore queued messages to editor |
377
-
378
- ### Custom Keybindings
379
-
380
- All keyboard shortcuts can be customized via `~/.pi/agent/keybindings.json`. Each action can be bound to one or more keys.
381
-
382
- **Key format:** `modifier+key` where modifiers are `ctrl`, `shift`, `alt` and keys are:
383
-
384
- - Letters: `a-z`
385
- - Numbers: `0-9`
386
- - Special keys: `escape`, `tab`, `enter`, `space`, `backspace`, `delete`, `home`, `end`, `up`, `down`, `left`, `right`
387
- - Symbol keys: `` ` ``, `-`, `=`, `[`, `]`, `\`, `;`, `'`, `,`, `.`, `/`, `!`, `@`, `#`, `$`, `%`, `^`, `&`, `*`, `(`, `)`, `_`, `+`, `|`, `~`, `{`, `}`, `:`, `<`, `>`, `?`
388
-
389
- **Configurable actions:**
390
-
391
- | Action | Default | Description |
392
- |--------|---------|-------------|
393
- | `cursorUp` | `up` | Move cursor up |
394
- | `cursorDown` | `down` | Move cursor down |
395
- | `cursorLeft` | `left` | Move cursor left |
396
- | `cursorRight` | `right` | Move cursor right |
397
- | `cursorWordLeft` | `alt+left`, `ctrl+left` | Move cursor word left |
398
- | `cursorWordRight` | `alt+right`, `ctrl+right` | Move cursor word right |
399
- | `cursorLineStart` | `home`, `ctrl+a` | Move to line start |
400
- | `cursorLineEnd` | `end`, `ctrl+e` | Move to line end |
401
- | `deleteCharBackward` | `backspace` | Delete char backward |
402
- | `deleteCharForward` | `delete` | Delete char forward |
403
- | `deleteWordBackward` | `ctrl+w`, `alt+backspace` | Delete word backward |
404
- | `deleteWordForward` | `alt+d`, `alt+delete` | Delete word forward |
405
- | `deleteToLineStart` | `ctrl+u` | Delete to line start |
406
- | `deleteToLineEnd` | `ctrl+k` | Delete to line end |
407
- | `yank` | `ctrl+y` | Paste most recently deleted text |
408
- | `yankPop` | `alt+y` | Cycle through deleted text after pasting |
409
- | `undo` | `ctrl+-` | Undo last edit |
410
- | `newLine` | `shift+enter` | Insert new line |
411
- | `submit` | `enter` | Submit input |
412
- | `tab` | `tab` | Tab/autocomplete |
413
- | `interrupt` | `escape` | Interrupt operation |
414
- | `clear` | `ctrl+c` | Clear editor |
415
- | `exit` | `ctrl+d` | Exit (when empty) |
416
- | `suspend` | `ctrl+z` | Suspend process |
417
- | `cycleThinkingLevel` | `shift+tab` | Cycle thinking level |
418
- | `cycleModelForward` | `ctrl+p` | Next model |
419
- | `cycleModelBackward` | `shift+ctrl+p` | Previous model |
420
- | `selectModel` | `ctrl+l` | Open model selector |
421
- | `expandTools` | `ctrl+o` | Expand tool output |
422
- | `toggleThinking` | `ctrl+t` | Toggle thinking |
423
- | `externalEditor` | `ctrl+g` | Open external editor |
424
- | `followUp` | `alt+enter` | Queue follow-up message |
425
- | `dequeue` | `alt+up` | Restore queued messages to editor |
426
- | `selectUp` | `up` | Move selection up in lists (session picker, model selector) |
427
- | `selectDown` | `down` | Move selection down in lists |
428
- | `selectConfirm` | `enter` | Confirm selection |
429
- | `selectCancel` | `escape`, `ctrl+c` | Cancel selection |
430
-
431
- **Example (Emacs-style):**
432
-
433
- ```json
434
- {
435
- "cursorUp": ["up", "ctrl+p"],
436
- "cursorDown": ["down", "ctrl+n"],
437
- "cursorLeft": ["left", "ctrl+b"],
438
- "cursorRight": ["right", "ctrl+f"],
439
- "cursorWordLeft": ["alt+left", "alt+b"],
440
- "cursorWordRight": ["alt+right", "alt+f"],
441
- "deleteCharForward": ["delete", "ctrl+d"],
442
- "deleteCharBackward": ["backspace", "ctrl+h"],
443
- "newLine": ["shift+enter", "ctrl+j"]
444
- }
445
- ```
446
-
447
- **Example (Vim-style):**
448
-
449
- ```json
450
- {
451
- "cursorUp": ["up", "alt+k"],
452
- "cursorDown": ["down", "alt+j"],
453
- "cursorLeft": ["left", "alt+h"],
454
- "cursorRight": ["right", "alt+l"],
455
- "cursorWordLeft": ["alt+left", "alt+b"],
456
- "cursorWordRight": ["alt+right", "alt+w"],
457
- "deleteCharBackward": ["backspace", "ctrl+h"],
458
- "deleteWordBackward": ["ctrl+w", "alt+backspace"]
459
- }
460
- ```
461
-
462
- **Example (symbol keys):**
463
-
464
- ```json
465
- {
466
- "submit": ["enter", "ctrl+j"],
467
- "newLine": ["shift+enter", "ctrl+;"],
468
- "toggleThinking": "ctrl+/",
469
- "cycleModelForward": "ctrl+.",
470
- "cycleModelBackward": "ctrl+,",
471
- "interrupt": ["escape", "ctrl+`"]
472
- }
473
- ```
474
-
475
- > **Note:** Some `ctrl+symbol` combinations overlap with ASCII control characters due to terminal legacy behavior (e.g., `ctrl+[` is the same as Escape, `ctrl+M` is the same as Enter). These can still be used with `ctrl+shift+key` (e.g., `ctrl+shift+]`). See [Kitty keyboard protocol: legacy ctrl mapping of ASCII keys](https://sw.kovidgoyal.net/kitty/keyboard-protocol/#legacy-ctrl-mapping-of-ascii-keys) for all unsupported keys.
476
-
477
- ### Bash Mode
478
-
479
- Prefix commands with `!` to execute them and add output to context:
480
-
481
- ```
482
- !ls -la
483
- !git status
484
- !cat package.json | jq '.dependencies'
485
- ```
486
-
487
- Output streams in real-time. Press Escape to cancel. Large outputs truncate at 2000 lines / 50KB.
488
-
489
- The output becomes part of your next prompt, formatted as:
490
-
491
- ```
492
- Ran `ls -la`
493
-
494
- <output here>
495
- ```
496
-
497
- Run multiple commands before prompting; all outputs are included together.
498
-
499
- ### Image Support
500
-
501
- **Pasting images:** Press `Ctrl+V` to paste an image from your clipboard.
502
-
503
- > **Note:** On macOS, pressing Cmd+C on an image file in Finder copies the file path, not the image contents. Use Preview or another image viewer to copy the actual image, or drag the file onto the terminal instead.
504
-
505
- **Dragging images:** Drag image files onto the terminal to insert their path. On macOS, you can also drag the screenshot thumbnail (after Cmd+Shift+4) directly onto the terminal.
506
-
507
- **Attaching images:** Include image paths in your message:
508
-
509
- ```
510
- You: What's in this screenshot? /path/to/image.png
511
- ```
167
+ | Ctrl+P / Shift+Ctrl+P | Cycle scoped models forward/backward |
168
+ | Shift+Tab | Cycle thinking level |
169
+ | Ctrl+O | Collapse/expand tool output |
170
+ | Ctrl+T | Collapse/expand thinking blocks |
512
171
 
513
- Supported formats: `.jpg`, `.jpeg`, `.png`, `.gif`, `.webp`
172
+ ### Message Queue
514
173
 
515
- **Auto-resize:** Images larger than 2000x2000 pixels are automatically resized to fit within this limit for better compatibility with Anthropic models. The original dimensions are noted in the context so the model can map coordinates back if needed. Disable via `images.autoResize: false` in settings.
174
+ Submit messages while the agent is working:
516
175
 
517
- **Inline rendering:** On terminals that support the Kitty graphics protocol (Kitty, Ghostty, WezTerm) or iTerm2 inline images, images in tool output are rendered inline. On unsupported terminals, a text placeholder is shown instead.
176
+ - **Enter** queues a *steering* message, delivered after current tool execution (interrupts remaining tools)
177
+ - **Alt+Enter** queues a *follow-up* message, delivered only after the agent finishes all work
178
+ - **Escape** aborts and restores queued messages to editor
179
+ - **Alt+Up** retrieves queued messages back to editor
518
180
 
519
- Toggle inline images via `/settings` or set `terminal.showImages: false` in settings.
181
+ Configure delivery in [settings](docs/settings.md): `steeringMode` and `followUpMode` can be `"one-at-a-time"` (default, waits for response) or `"all"` (delivers all queued at once).
520
182
 
521
183
  ---
522
184
 
523
185
  ## Sessions
524
186
 
525
- Sessions are stored as JSONL files with a **tree structure**. Each entry has an `id` and `parentId`, enabling in-place branching: navigate to any previous point with `/tree`, continue from there, and switch between branches while preserving all history in a single file.
526
-
527
- See [docs/session.md](docs/session.md) for the file format and programmatic API.
187
+ Sessions are stored as JSONL files with a tree structure. Each entry has an `id` and `parentId`, enabling in-place branching without creating new files. See [docs/session.md](docs/session.md) for file format.
528
188
 
529
- ### Session Management
189
+ ### Management
530
190
 
531
191
  Sessions auto-save to `~/.pi/agent/sessions/` organized by working directory.
532
192
 
533
193
  ```bash
534
- pi --continue # Continue most recent session
535
- pi -c # Short form
194
+ pi -c # Continue most recent session
195
+ pi -r # Browse and select from past sessions
196
+ pi --no-session # Ephemeral mode (don't save)
197
+ pi --session <path> # Use specific session file or ID
198
+ ```
536
199
 
537
- pi --resume # Browse and select from past sessions (Tab to toggle Current Folder / All)
538
- pi -r # Short form
200
+ ### Branching
539
201
 
540
- pi --no-session # Ephemeral mode (don't save)
202
+ **`/tree`** - Navigate the session tree in-place. Select any previous point, continue from there, and switch between branches. All history preserved in a single file.
541
203
 
542
- pi --session /path/to/file.jsonl # Use specific session file
543
- pi --session a8ec1c2a # Resume by session ID (partial UUID)
544
- ```
204
+ <p align="center"><img src="docs/images/tree-view.png" alt="Tree View" width="600"></p>
545
205
 
546
- In the `/resume` picker:
547
- - `Ctrl+P` toggles display of the session `.jsonl` file path
548
- - `Ctrl+D` deletes the selected session (inline confirmation; uses `trash` if available and cannot delete the active session)
206
+ - Search by typing, page with ←/→
207
+ - Filter modes (Ctrl+O): default no-tools user-only labeled-only → all
208
+ - Press `l` to label entries as bookmarks
549
209
 
550
- **Resuming by session ID:** The `--session` flag accepts a session UUID (or prefix). Session IDs are visible in filenames under `~/.pi/agent/sessions/<project>/` (e.g., `2025-12-13T17-47-46-817Z_a8ec1c2a-5a5f-4699-88cb-03e7d3cb9292.jsonl`). The UUID is the part after the underscore. You can also search by session ID in the `pi -r` picker.
210
+ **`/fork`** - Create a new session file from the current branch. Opens a selector, copies history up to the selected point, and places that message in the editor for modification.
551
211
 
552
- ### Context Compaction
212
+ ### Compaction
553
213
 
554
214
  Long sessions can exhaust context windows. Compaction summarizes older messages while keeping recent ones.
555
215
 
556
- **Manual:** `/compact` or `/compact Focus on the API changes`
216
+ **Manual:** `/compact` or `/compact <custom instructions>`
557
217
 
558
- **Automatic:** Enable via `/settings`. When enabled, triggers in two cases:
559
- - **Overflow recovery**: LLM returns context overflow error. Compacts and auto-retries.
560
- - **Threshold maintenance**: Context exceeds `contextWindow - reserveTokens` after a successful turn. Compacts without retry.
218
+ **Automatic:** Enabled by default. Triggers on context overflow (recovers and retries) or when approaching the limit (proactive). Configure via `/settings` or `settings.json`.
561
219
 
562
- When disabled, neither case triggers automatic compaction (use `/compact` manually if needed).
220
+ Compaction is lossy. The full history remains in the JSONL file; use `/tree` to revisit. Customize compaction behavior via [extensions](#extensions). See [docs/compaction.md](docs/compaction.md) for internals.
563
221
 
564
- **Configuration** (`~/.pi/agent/settings.json`):
222
+ ---
565
223
 
566
- ```json
567
- {
568
- "compaction": {
569
- "enabled": true,
570
- "reserveTokens": 16384,
571
- "keepRecentTokens": 20000
572
- }
573
- }
574
- ```
224
+ ## Settings
575
225
 
576
- > **Note:** Compaction is lossy. The agent loses full conversation access afterward. Size tasks to avoid context limits when possible. For critical context, ask the agent to write a summary to a file, iterate on it until it covers everything, then start a new session with that file. The full session history is preserved in the JSONL file; use `/tree` to revisit any previous point.
226
+ Use `/settings` to modify common options, or edit JSON files directly:
577
227
 
578
- See [docs/compaction.md](docs/compaction.md) for how compaction works internally and how to customize it via extensions.
228
+ | Location | Scope |
229
+ |----------|-------|
230
+ | `~/.pi/agent/settings.json` | Global (all projects) |
231
+ | `.pi/settings.json` | Project (overrides global) |
579
232
 
580
- ### Branching
233
+ See [docs/settings.md](docs/settings.md) for all options.
581
234
 
582
- **In-place navigation (`/tree`):** Navigate the session tree without creating new files. Select any previous point, continue from there, and switch between branches while preserving all history.
235
+ ---
583
236
 
584
- - Search by typing, page with ←/→
585
- - Filter modes (Ctrl+O): default → no-tools → user-only → labeled-only → all
586
- - Press `l` to label entries as bookmarks
587
- - When switching branches, you're prompted whether to generate a summary of the abandoned branch (messages up to the common ancestor)
237
+ ## Context Files
588
238
 
589
- **Create new session (`/fork`):** Fork to a new session file:
239
+ Pi loads `AGENTS.md` (or `CLAUDE.md`) at startup from:
240
+ - `~/.pi/agent/AGENTS.md` (global)
241
+ - Parent directories (walking up from cwd)
242
+ - Current directory
590
243
 
591
- 1. Opens selector showing all your user messages
592
- 2. Select a message to fork from
593
- 3. Creates new session with history up to that point
594
- 4. Selected message placed in editor for modification
244
+ Use for project instructions, conventions, common commands. All matching files are concatenated.
595
245
 
596
- ---
246
+ ### System Prompt
597
247
 
598
- ## Configuration
248
+ Replace the default system prompt with `.pi/SYSTEM.md` (project) or `~/.pi/agent/SYSTEM.md` (global). Append without replacing via `APPEND_SYSTEM.md`.
599
249
 
600
- ### Project Context Files
250
+ ---
601
251
 
602
- Pi loads `AGENTS.md` (or `CLAUDE.md`) files at startup in this order:
252
+ ## Customization
603
253
 
604
- 1. **Global:** `~/.pi/agent/AGENTS.md`
605
- 2. **Parent directories:** Walking up from current directory
606
- 3. **Current directory:** `./AGENTS.md`
254
+ ### Prompt Templates
607
255
 
608
- Use these for:
609
- - Project instructions and guidelines
610
- - Common commands and workflows
611
- - Architecture documentation
612
- - Coding conventions
613
- - Testing instructions
256
+ Reusable prompts as Markdown files. Type `/name` to expand.
614
257
 
615
258
  ```markdown
616
- # Common Commands
617
- - npm run build: Build the project
618
- - npm test: Run tests
619
-
620
- # Code Style
621
- - Use TypeScript strict mode
622
- - Prefer async/await over promises
259
+ <!-- ~/.pi/agent/prompts/review.md -->
260
+ Review this code for bugs, security issues, and performance problems.
261
+ Focus on: {{focus}}
623
262
  ```
624
263
 
625
- ### Custom System Prompt
264
+ Place in `~/.pi/agent/prompts/`, `.pi/prompts/`, or a [pi package](#pi-packages) to share with others. See [docs/prompt-templates.md](docs/prompt-templates.md).
626
265
 
627
- Replace the default system prompt **entirely** by creating a `SYSTEM.md` file:
628
-
629
- 1. **Project-local:** `.pi/SYSTEM.md` (takes precedence)
630
- 2. **Global:** `~/.pi/agent/SYSTEM.md` (fallback)
266
+ ### Skills
631
267
 
632
- This is useful when using pi as different types of agents across repos (coding assistant, personal assistant, domain-specific agent, etc.).
268
+ On-demand capability packages following the [Agent Skills standard](https://agentskills.io). Invoke via `/skill:name` or let the agent load them automatically.
633
269
 
634
270
  ```markdown
635
- You are a technical writing assistant. Help users write clear documentation.
271
+ <!-- ~/.pi/agent/skills/my-skill/SKILL.md -->
272
+ # My Skill
273
+ Use this skill when the user asks about X.
636
274
 
637
- Focus on:
638
- - Concise explanations
639
- - Code examples
640
- - Proper formatting
275
+ ## Steps
276
+ 1. Do this
277
+ 2. Then that
641
278
  ```
642
279
 
643
- The `--system-prompt` CLI flag overrides both files.
644
-
645
- ### Appending to the System Prompt
280
+ Place in `~/.pi/agent/skills/`, `.pi/skills/`, or a [pi package](#pi-packages) to share with others. See [docs/skills.md](docs/skills.md).
646
281
 
647
- To add instructions to the system prompt **without** replacing the default (preserving automatic loading of `AGENTS.md` context files, skills, and tools guidelines), create an `APPEND_SYSTEM.md` file:
648
-
649
- 1. **Project-local:** `.pi/APPEND_SYSTEM.md` (takes precedence)
650
- 2. **Global:** `~/.pi/agent/APPEND_SYSTEM.md` (fallback)
651
-
652
- The `--append-system-prompt` CLI flag overrides both files.
282
+ ### Extensions
653
283
 
654
- ### Custom Models and Providers
284
+ <p align="center"><img src="docs/images/doom-extension.png" alt="Doom Extension" width="600"></p>
655
285
 
656
- Add custom models (Ollama, vLLM, LM Studio, etc.) via `~/.pi/agent/models.json`:
286
+ TypeScript modules that extend pi with custom tools, commands, keyboard shortcuts, event handlers, and UI components.
657
287
 
658
- ```json
659
- {
660
- "providers": {
661
- "ollama": {
662
- "baseUrl": "http://localhost:11434/v1",
663
- "apiKey": "OLLAMA_API_KEY",
664
- "api": "openai-completions",
665
- "models": [
666
- {
667
- "id": "llama-3.1-8b",
668
- "name": "Llama 3.1 8B (Local)",
669
- "reasoning": false,
670
- "input": ["text"],
671
- "cost": {"input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0},
672
- "contextWindow": 128000,
673
- "maxTokens": 32000
674
- }
675
- ]
676
- }
677
- }
288
+ ```typescript
289
+ export default function (pi: ExtensionAPI) {
290
+ pi.registerTool({ name: "deploy", ... });
291
+ pi.registerCommand("stats", { ... });
292
+ pi.on("tool_call", async (event, ctx) => { ... });
678
293
  }
679
294
  ```
680
295
 
681
- **Supported APIs:** `openai-completions`, `openai-responses`, `openai-codex-responses`, `anthropic-messages`, `google-generative-ai`
296
+ **What's possible:**
297
+ - Custom tools (or replace built-in tools entirely)
298
+ - Sub-agents and plan mode
299
+ - Custom compaction and summarization
300
+ - Permission gates and path protection
301
+ - Custom editors and UI components
302
+ - Status lines, headers, footers
303
+ - Git checkpointing and auto-commit
304
+ - SSH and sandbox execution
305
+ - MCP server integration
306
+ - Make pi look like Claude Code
307
+ - Games while waiting (yes, Doom runs)
308
+ - ...anything you can dream up
682
309
 
683
- **API key resolution:** The `apiKey` field supports three formats:
684
- - `"!command"` - Executes the command and uses stdout (e.g., `"!security find-generic-password -ws 'anthropic'"` for macOS Keychain, `"!op read 'op://vault/item/credential'"` for 1Password)
685
- - Environment variable name (e.g., `"MY_API_KEY"`) - Uses the value of the environment variable
686
- - Literal value - Used directly as the API key
310
+ Place in `~/.pi/agent/extensions/`, `.pi/extensions/`, or a [pi package](#pi-packages) to share with others. See [docs/extensions.md](docs/extensions.md) and [examples/extensions/](examples/extensions/).
687
311
 
688
- **API override:** Set `api` at provider level (default for all models) or model level (override per model).
312
+ ### Themes
689
313
 
690
- **Custom headers:**
314
+ Built-in: `dark`, `light`. Themes hot-reload: modify the active theme file and pi immediately applies changes.
691
315
 
692
- ```json
693
- {
694
- "providers": {
695
- "custom-proxy": {
696
- "baseUrl": "https://proxy.example.com/v1",
697
- "apiKey": "YOUR_API_KEY",
698
- "api": "anthropic-messages",
699
- "headers": {
700
- "User-Agent": "Mozilla/5.0 ...",
701
- "X-Custom-Auth": "token"
702
- },
703
- "models": [...]
704
- }
705
- }
706
- }
707
- ```
316
+ Place in `~/.pi/agent/themes/`, `.pi/themes/`, or a [pi package](#pi-packages) to share with others. See [docs/themes.md](docs/themes.md).
708
317
 
709
- **Overriding built-in providers:**
318
+ ### Pi Packages
710
319
 
711
- To route a built-in provider (anthropic, openai, google, etc.) through a proxy without redefining all models, just specify the `baseUrl`:
320
+ Bundle and share extensions, skills, prompts, and themes via npm or git. Find packages on [npmjs.com](https://www.npmjs.com/search?q=keywords%3Api-package) or [Discord](https://discord.com/channels/1456806362351669492/1457744485428629628).
712
321
 
713
- ```json
714
- {
715
- "providers": {
716
- "anthropic": {
717
- "baseUrl": "https://my-proxy.example.com/v1"
718
- }
719
- }
720
- }
322
+ > **Security:** Pi packages run with full system access. Extensions execute arbitrary code, and skills can instruct the model to perform any action including running executables. Review source code before installing third-party packages.
323
+
324
+ ```bash
325
+ pi install npm:@foo/pi-tools
326
+ pi install npm:@foo/pi-tools@1.2.3 # pinned version
327
+ pi install git:github.com/user/repo
328
+ pi install git:github.com/user/repo@v1 # tag or commit
329
+ pi install https://github.com/user/repo
330
+ pi remove npm:@foo/pi-tools
331
+ pi list
332
+ pi update # skips pinned packages
333
+ pi config # enable/disable extensions, skills, prompts, themes
721
334
  ```
722
335
 
723
- All built-in Anthropic models remain available with the new endpoint. Existing OAuth or API key auth continues to work.
336
+ Packages install to `~/.pi/agent/git/` (git) or global npm. Use `-l` for project-local installs (`.pi/git/`, `.pi/npm/`).
724
337
 
725
- To fully replace a built-in provider with custom models, include the `models` array:
338
+ Create a package by adding a `pi` key to `package.json`:
726
339
 
727
340
  ```json
728
341
  {
729
- "providers": {
730
- "anthropic": {
731
- "baseUrl": "https://my-proxy.example.com/v1",
732
- "apiKey": "ANTHROPIC_API_KEY",
733
- "api": "anthropic-messages",
734
- "models": [...]
735
- }
342
+ "name": "my-pi-package",
343
+ "keywords": ["pi-package"],
344
+ "pi": {
345
+ "extensions": ["./extensions"],
346
+ "skills": ["./skills"],
347
+ "prompts": ["./prompts"],
348
+ "themes": ["./themes"]
736
349
  }
737
350
  }
738
351
  ```
739
352
 
740
- **Authorization header:** Set `authHeader: true` to add `Authorization: Bearer <apiKey>` automatically.
741
-
742
- **OpenAI compatibility (`compat` field):**
743
-
744
- **OpenAI Completions (`openai-completions`):**
745
-
746
- | Field | Description |
747
- |-------|-------------|
748
- | `supportsStore` | Whether provider supports `store` field |
749
- | `supportsDeveloperRole` | Use `developer` vs `system` role |
750
- | `supportsReasoningEffort` | Support for `reasoning_effort` parameter |
751
- | `supportsUsageInStreaming` | Whether provider supports `stream_options: { include_usage: true }`. Default: `true` |
752
- | `maxTokensField` | Use `max_completion_tokens` or `max_tokens` |
753
-
754
- **Live reload:** The file reloads each time you open `/model`. Edit during session; no restart needed.
755
-
756
- **Model selection priority:**
757
- 1. CLI args (`--provider`, `--model`)
758
- 2. First from `--models` scope (new sessions only)
759
- 3. Restored from session (`--continue`, `--resume`)
760
- 4. Saved default from settings
761
- 5. First available model with valid API key
762
-
763
- > pi can help you create custom provider and model configurations.
764
-
765
- ### Settings File
353
+ Without a `pi` manifest, pi auto-discovers from conventional directories (`extensions/`, `skills/`, `prompts/`, `themes/`).
766
354
 
767
- Settings are loaded from two locations and merged:
768
-
769
- 1. **Global:** `~/.pi/agent/settings.json` - user preferences
770
- 2. **Project:** `<cwd>/.pi/settings.json` - project-specific overrides (version control friendly)
771
-
772
- Project settings override global settings. For nested objects, individual keys merge. Settings changed via TUI (model, thinking level, etc.) are saved to global preferences only.
773
-
774
- Global `~/.pi/agent/settings.json` stores persistent preferences:
775
-
776
- ```json
777
- {
778
- "theme": "dark",
779
- "defaultProvider": "anthropic",
780
- "defaultModel": "claude-sonnet-4-20250514",
781
- "defaultThinkingLevel": "medium",
782
- "enabledModels": ["anthropic/*", "*gpt*", "gemini-2.5-pro:high"],
783
- "steeringMode": "one-at-a-time",
784
- "followUpMode": "one-at-a-time",
785
- "shellPath": "C:\\path\\to\\bash.exe",
786
- "shellCommandPrefix": "shopt -s expand_aliases",
787
- "hideThinkingBlock": false,
788
- "collapseChangelog": false,
789
- "compaction": {
790
- "enabled": true,
791
- "reserveTokens": 16384,
792
- "keepRecentTokens": 20000
793
- },
794
- "skills": {
795
- "enabled": true
796
- },
797
- "retry": {
798
- "enabled": true,
799
- "maxRetries": 3,
800
- "baseDelayMs": 2000
801
- },
802
- "terminal": {
803
- "showImages": true
804
- },
805
- "images": {
806
- "autoResize": true,
807
- "blockImages": false
808
- },
809
- "showHardwareCursor": false,
810
- "extensions": ["/path/to/extension.ts"]
811
- }
812
- ```
813
-
814
- | Setting | Description | Default |
815
- |---------|-------------|---------|
816
- | `theme` | Color theme name | auto-detected |
817
- | `defaultProvider` | Default model provider | - |
818
- | `defaultModel` | Default model ID | - |
819
- | `defaultThinkingLevel` | Thinking level: `off`, `minimal`, `low`, `medium`, `high`, `xhigh` | - |
820
- | `enabledModels` | Model patterns for cycling. Supports glob patterns (`github-copilot/*`, `*sonnet*`) and fuzzy matching. Same as `--models` CLI flag | - |
821
- | `steeringMode` | Steering message delivery: `all` or `one-at-a-time` | `one-at-a-time` |
822
- | `followUpMode` | Follow-up message delivery: `all` or `one-at-a-time` | `one-at-a-time` |
823
- | `shellPath` | Custom bash path (Windows) | auto-detected |
824
- | `shellCommandPrefix` | Command prefix for bash (e.g., `shopt -s expand_aliases` for alias support) | - |
825
- | `hideThinkingBlock` | Hide thinking blocks in output (Ctrl+T to toggle) | `false` |
826
- | `collapseChangelog` | Show condensed changelog after update | `false` |
827
- | `compaction.enabled` | Enable auto-compaction | `true` |
828
- | `compaction.reserveTokens` | Tokens to reserve before compaction triggers | `16384` |
829
- | `compaction.keepRecentTokens` | Recent tokens to keep after compaction | `20000` |
830
- | `skills.enabled` | Enable skills discovery | `true` |
831
- | `retry.enabled` | Auto-retry on transient errors | `true` |
832
- | `retry.maxRetries` | Maximum retry attempts | `3` |
833
- | `retry.baseDelayMs` | Base delay for exponential backoff | `2000` |
834
- | `terminal.showImages` | Render images inline (supported terminals) | `true` |
835
- | `images.autoResize` | Auto-resize images to 2000x2000 max for better model compatibility | `true` |
836
- | `images.blockImages` | Prevent images from being sent to LLM providers | `false` |
837
- | `showHardwareCursor` | Show terminal cursor while still positioning it for IME support | `false` |
838
- | `doubleEscapeAction` | Action for double-escape with empty editor: `tree` or `branch` | `tree` |
839
- | `editorPaddingX` | Horizontal padding for input editor (0-3) | `0` |
840
- | `markdown.codeBlockIndent` | Prefix for each rendered code block line | `" "` |
841
- | `extensions` | Additional extension file paths | `[]` |
355
+ See [docs/packages.md](docs/packages.md).
842
356
 
843
357
  ---
844
358
 
845
- ## Customization
846
-
847
- ### Themes
359
+ ## Programmatic Usage
848
360
 
849
- Built-in themes: `dark` (default), `light`. Auto-detected on first run.
361
+ ### SDK
850
362
 
851
- Select theme via `/settings` or set in `~/.pi/agent/settings.json`.
363
+ ```typescript
364
+ import { AuthStorage, createAgentSession, ModelRegistry, SessionManager } from "@mariozechner/pi-coding-agent";
852
365
 
853
- **Custom themes:** Create `~/.pi/agent/themes/*.json`. Custom themes support live reload.
366
+ const { session } = await createAgentSession({
367
+ sessionManager: SessionManager.inMemory(),
368
+ authStorage: new AuthStorage(),
369
+ modelRegistry: new ModelRegistry(authStorage),
370
+ });
854
371
 
855
- ```bash
856
- mkdir -p ~/.pi/agent/themes
857
- cp $(npm root -g)/@mariozechner/pi-coding-agent/dist/theme/dark.json ~/.pi/agent/themes/my-theme.json
372
+ await session.prompt("What files are in the current directory?");
858
373
  ```
859
374
 
860
- Select with `/settings`, then edit the file. Changes apply on save.
861
-
862
- > See [Theme Documentation](docs/theme.md) on how to create custom themes in detail. Pi can help you create a new one.
863
-
864
- **VS Code terminal fix:** Set `terminal.integrated.minimumContrastRatio` to `1` for accurate colors.
865
-
866
- ### Prompt Templates
867
-
868
- Define reusable prompts as Markdown files:
375
+ See [docs/sdk.md](docs/sdk.md) and [examples/sdk/](examples/sdk/).
869
376
 
870
- **Locations:**
871
- - Global: `~/.pi/agent/prompts/*.md`
872
- - Project: `.pi/prompts/*.md`
377
+ ### RPC Mode
873
378
 
874
- **Format:**
379
+ For non-Node.js integrations, use RPC mode over stdin/stdout:
875
380
 
876
- ```markdown
877
- ---
878
- description: Review staged git changes
879
- ---
880
- Review the staged changes (`git diff --cached`). Focus on:
881
- - Bugs and logic errors
882
- - Security issues
883
- - Error handling gaps
381
+ ```bash
382
+ pi --mode rpc
884
383
  ```
885
384
 
886
- Filename (without `.md`) becomes the command name. Description shown in autocomplete.
887
-
888
- **Arguments:**
385
+ See [docs/rpc.md](docs/rpc.md) for the protocol.
889
386
 
890
- ```markdown
891
- ---
892
- description: Create a component
893
387
  ---
894
- Create a React component named $1 with features: $@
895
- ```
896
388
 
897
- Usage: `/component Button "onClick handler" "disabled support"`
898
- - `$1` = `Button`
899
- - `$@` or `$ARGUMENTS` = all arguments joined (`Button onClick handler disabled support`)
900
- - `${@:N}` = arguments from the Nth position onwards (1-indexed)
901
- - `${@:N:L}` = `L` arguments starting from the Nth position
389
+ ## Philosophy
902
390
 
903
- **Namespacing:** Subdirectories create prefixes. `.pi/prompts/frontend/component.md` `/component (project:frontend)`
391
+ Pi is aggressively extensible so it doesn't have to dictate your workflow. Features that other tools bake in can be built with [extensions](#extensions), [skills](#skills), or installed from third-party [pi packages](#pi-packages). This keeps the core minimal while letting you shape pi to fit how you work.
904
392
 
393
+ **No MCP.** Build CLI tools with READMEs (see [Skills](#skills)), or build an extension that adds MCP support. [Why?](https://mariozechner.at/posts/2025-11-02-what-if-you-dont-need-mcp/)
905
394
 
906
- ### Skills
395
+ **No sub-agents.** There's many ways to do this. Spawn pi instances via tmux, or build your own with [extensions](#extensions), or install a package that does it your way.
907
396
 
908
- Skills are self-contained capability packages that the agent loads on-demand. Pi implements the [Agent Skills standard](https://agentskills.io/specification), warning about violations but remaining lenient.
397
+ **No permission popups.** Run in a container, or build your own confirmation flow with [extensions](#extensions) inline with your environment and security requirements.
909
398
 
910
- A skill provides specialized workflows, setup instructions, helper scripts, and reference documentation for specific tasks. Skills are loaded when the agent decides a task matches the description, or when you explicitly ask to use one. You can also invoke skills directly via `/skill:name` commands (e.g., `/skill:brave-search`).
399
+ **No plan mode.** Write plans to files, or build it with [extensions](#extensions), or install a package.
911
400
 
912
- **Example use cases:**
913
- - Web search and content extraction (Brave Search API)
914
- - Browser automation via Chrome DevTools Protocol
915
- - Google Calendar, Gmail, Drive integration
916
- - PDF/DOCX processing and creation
917
- - Speech-to-text transcription
918
- - YouTube transcript extraction
401
+ **No built-in to-dos.** They confuse models. Use a TODO.md file, or build your own with [extensions](#extensions).
919
402
 
920
- **Skill locations:**
921
- - Pi user: `~/.pi/agent/skills/**/SKILL.md` (recursive)
922
- - Pi project: `.pi/skills/**/SKILL.md` (recursive)
923
- - Claude Code: `~/.claude/skills/*/SKILL.md` and `.claude/skills/*/SKILL.md`
924
- - Codex CLI: `~/.codex/skills/**/SKILL.md` (recursive)
403
+ **No background bash.** Use tmux. Full observability, direct interaction.
925
404
 
926
- **Format:**
405
+ Read the [blog post](https://mariozechner.at/posts/2025-11-30-pi-coding-agent/) for the full rationale.
927
406
 
928
- ```markdown
929
- ---
930
- name: brave-search
931
- description: Web search via Brave Search API. Use for documentation, facts, or web content.
932
407
  ---
933
408
 
934
- # Brave Search
935
-
936
- ## Setup
937
- \`\`\`bash
938
- cd /path/to/brave-search && npm install
939
- \`\`\`
940
-
941
- ## Usage
942
- \`\`\`bash
943
- ./search.js "query" # Basic search
944
- ./search.js "query" --content # Include page content
945
- \`\`\`
946
- ```
947
-
948
- - `name`: Required. Must match parent directory name. Lowercase, hyphens, max 64 chars.
949
- - `description`: Required. Max 1024 chars. Determines when the skill is loaded.
950
-
951
- **Disable skills:** `pi --no-skills` or set `skills.enabled: false` in settings.
952
-
953
- > See [docs/skills.md](docs/skills.md) for details, examples, and links to skill repositories. pi can help you create new skills.
954
-
955
- ### Extensions
956
-
957
- Extensions are TypeScript modules that extend pi's behavior.
958
-
959
- **Use cases:**
960
- - **Custom tools** - Register tools callable by the LLM with custom UI and rendering
961
- - **Custom commands** - Add `/commands` for users (e.g., `/deploy`, `/stats`)
962
- - **Event interception** - Block tool calls, modify results, customize compaction
963
- - **State persistence** - Store data in session, reconstruct on reload/fork
964
- - **External integrations** - File watchers, webhooks, git checkpointing
965
- - **Custom UI** - Full TUI control from tools, commands, or event handlers
966
-
967
- **Locations:**
968
- - Global: `~/.pi/agent/extensions/*.ts` or `~/.pi/agent/extensions/*/index.ts`
969
- - Project: `.pi/extensions/*.ts` or `.pi/extensions/*/index.ts`
970
- - CLI: `--extension <path>` or `-e <path>`
971
-
972
- **Dependencies:** Extensions can have their own dependencies. Place a `package.json` next to the extension (or in a parent directory), run `npm install`, and imports are resolved via [jiti](https://github.com/unjs/jiti). See [examples/extensions/with-deps/](examples/extensions/with-deps/).
973
-
974
- #### Custom Tools
975
-
976
- Tools are functions the LLM can call. They appear in the system prompt and can have custom rendering.
977
-
978
- ```typescript
979
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
980
- import { Type } from "@sinclair/typebox";
981
- import { Text } from "@mariozechner/pi-tui";
982
-
983
- export default function (pi: ExtensionAPI) {
984
- pi.registerTool({
985
- name: "deploy",
986
- label: "Deploy",
987
- description: "Deploy the application to production",
988
- parameters: Type.Object({
989
- environment: Type.String({ description: "Target environment" }),
990
- }),
991
-
992
- async execute(toolCallId, params, onUpdate, ctx, signal) {
993
- // Show progress via onUpdate
994
- onUpdate({ status: "Deploying..." });
995
-
996
- // Ask user for confirmation
997
- const ok = await ctx.ui.confirm("Deploy?", `Deploy to ${params.environment}?`);
998
- if (!ok) {
999
- return { content: [{ type: "text", text: "Cancelled" }], details: { cancelled: true } };
1000
- }
1001
-
1002
- // Run shell commands
1003
- const result = await ctx.exec("./deploy.sh", [params.environment], { signal });
1004
-
1005
- return {
1006
- content: [{ type: "text", text: result.stdout }],
1007
- details: { environment: params.environment, exitCode: result.exitCode },
1008
- };
1009
- },
1010
-
1011
- // Custom TUI rendering (optional)
1012
- renderCall(args, theme) {
1013
- return new Text(theme.bold("deploy ") + theme.fg("accent", args.environment), 0, 0);
1014
- },
1015
- renderResult(result, options, theme) {
1016
- const ok = result.details?.exitCode === 0;
1017
- return new Text(ok ? theme.fg("success", "✓ Deployed") : theme.fg("error", "✗ Failed"), 0, 0);
1018
- },
1019
- });
1020
- }
1021
- ```
1022
-
1023
- #### Custom Commands
1024
-
1025
- Commands are user-invoked via `/name`. They can show custom UI, modify state, or trigger agent turns.
1026
-
1027
- ```typescript
1028
- export default function (pi: ExtensionAPI) {
1029
- pi.registerCommand("stats", {
1030
- description: "Show session statistics",
1031
- handler: async (args, ctx) => {
1032
- // Simple notification
1033
- ctx.ui.notify(`${ctx.sessionManager.getEntries().length} entries`, "info");
1034
- },
1035
- });
1036
-
1037
- pi.registerCommand("todos", {
1038
- description: "Interactive todo viewer",
1039
- handler: async (args, ctx) => {
1040
- // Full custom UI with keyboard handling
1041
- await ctx.ui.custom((tui, theme, done) => {
1042
- return {
1043
- render(width) {
1044
- return [
1045
- theme.bold("Todos"),
1046
- "- [ ] Item 1",
1047
- "- [x] Item 2",
1048
- "",
1049
- theme.fg("dim", "Press Escape to close"),
1050
- ];
1051
- },
1052
- handleInput(data) {
1053
- if (matchesKey(data, "escape")) done();
1054
- },
1055
- };
1056
- });
1057
- },
1058
- });
1059
- }
1060
- ```
1061
-
1062
- #### Event Interception
1063
-
1064
- Subscribe to lifecycle events to block, modify, or observe agent behavior.
409
+ ## CLI Reference
1065
410
 
1066
- ```typescript
1067
- export default function (pi: ExtensionAPI) {
1068
- // Block dangerous commands
1069
- pi.on("tool_call", async (event, ctx) => {
1070
- if (event.toolName === "bash" && /rm -rf/.test(event.input.command as string)) {
1071
- const ok = await ctx.ui.confirm("Dangerous!", "Allow rm -rf?");
1072
- if (!ok) return { block: true, reason: "Blocked by user" };
1073
- }
1074
- });
1075
-
1076
- // Modify tool results
1077
- pi.on("tool_result", async (event, ctx) => {
1078
- if (event.toolName === "read") {
1079
- // Redact secrets from file contents
1080
- return { modifiedResult: event.result.replace(/API_KEY=\w+/g, "API_KEY=***") };
1081
- }
1082
- });
1083
-
1084
- // Custom compaction
1085
- pi.on("session_before_compact", async (event, ctx) => {
1086
- return { customSummary: "My custom summary of the conversation so far..." };
1087
- });
1088
-
1089
- // Git checkpoint on each turn
1090
- pi.on("turn_end", async (event, ctx) => {
1091
- await ctx.exec("git", ["stash", "push", "-m", `pi-checkpoint-${Date.now()}`]);
1092
- });
1093
- }
411
+ ```bash
412
+ pi [options] [@files...] [messages...]
1094
413
  ```
1095
414
 
1096
- #### State Persistence
1097
-
1098
- Store state in session entries that survive reload and work correctly with branching.
415
+ ### Package Commands
1099
416
 
1100
- ```typescript
1101
- export default function (pi: ExtensionAPI) {
1102
- let counter = 0;
1103
-
1104
- // Reconstruct state from session history
1105
- const reconstruct = (ctx) => {
1106
- counter = 0;
1107
- for (const entry of ctx.sessionManager.getBranch()) {
1108
- if (entry.type === "custom" && entry.customType === "my_counter") {
1109
- counter = entry.data.value;
1110
- }
1111
- }
1112
- };
1113
-
1114
- pi.on("session_start", async (e, ctx) => reconstruct(ctx));
1115
- pi.on("session_fork", async (e, ctx) => reconstruct(ctx));
1116
- pi.on("session_tree", async (e, ctx) => reconstruct(ctx));
1117
-
1118
- pi.registerCommand("increment", {
1119
- handler: async (args, ctx) => {
1120
- counter++;
1121
- ctx.appendEntry("my_counter", { value: counter }); // Persisted in session
1122
- ctx.ui.notify(`Counter: ${counter}`, "info");
1123
- },
1124
- });
1125
- }
417
+ ```bash
418
+ pi install <source> [-l] # Install package, -l for project-local
419
+ pi remove <source> [-l] # Remove package
420
+ pi update [source] # Update packages (skips pinned)
421
+ pi list # List installed packages
422
+ pi config # Enable/disable package resources
1126
423
  ```
1127
424
 
1128
- #### Keyboard Shortcuts
425
+ ### Modes
1129
426
 
1130
- Register custom keyboard shortcuts (shown in `/hotkeys`):
1131
-
1132
- ```typescript
1133
- export default function (pi: ExtensionAPI) {
1134
- pi.registerShortcut("ctrl+shift+d", {
1135
- description: "Deploy to production",
1136
- handler: async (ctx) => {
1137
- ctx.ui.notify("Deploying...", "info");
1138
- await ctx.exec("./deploy.sh", []);
1139
- },
1140
- });
1141
- }
1142
- ```
427
+ | Flag | Description |
428
+ |------|-------------|
429
+ | (default) | Interactive mode |
430
+ | `-p`, `--print` | Print response and exit |
431
+ | `--mode json` | Output all events as JSON lines (see [docs/json.md](docs/json.md)) |
432
+ | `--mode rpc` | RPC mode for process integration (see [docs/rpc.md](docs/rpc.md)) |
433
+ | `--export <in> [out]` | Export session to HTML |
1143
434
 
1144
- #### CLI Flags
435
+ ### Model Options
1145
436
 
1146
- Register custom CLI flags (parsed automatically, shown in `--help`):
437
+ | Option | Description |
438
+ |--------|-------------|
439
+ | `--provider <name>` | Provider (anthropic, openai, google, etc.) |
440
+ | `--model <id>` | Model ID |
441
+ | `--api-key <key>` | API key (overrides env vars) |
442
+ | `--thinking <level>` | `off`, `minimal`, `low`, `medium`, `high`, `xhigh` |
443
+ | `--models <patterns>` | Comma-separated patterns for Ctrl+P cycling |
444
+ | `--list-models [search]` | List available models |
1147
445
 
1148
- ```typescript
1149
- export default function (pi: ExtensionAPI) {
1150
- pi.registerFlag("dry-run", {
1151
- description: "Run without making changes",
1152
- type: "boolean",
1153
- });
1154
-
1155
- pi.on("tool_call", async (event, ctx) => {
1156
- if (pi.getFlag("dry-run") && event.toolName === "write") {
1157
- return { block: true, reason: "Dry run mode" };
1158
- }
1159
- });
1160
- }
1161
- ```
446
+ ### Session Options
1162
447
 
1163
- #### Custom UI
448
+ | Option | Description |
449
+ |--------|-------------|
450
+ | `-c`, `--continue` | Continue most recent session |
451
+ | `-r`, `--resume` | Browse and select session |
452
+ | `--session <path>` | Use specific session file or partial UUID |
453
+ | `--session-dir <dir>` | Custom session storage directory |
454
+ | `--no-session` | Ephemeral mode (don't save) |
1164
455
 
1165
- Extensions have full TUI access via `ctx.ui`:
456
+ ### Tool Options
1166
457
 
1167
- ```typescript
1168
- // Simple prompts
1169
- const confirmed = await ctx.ui.confirm("Title", "Are you sure?");
1170
- const choice = await ctx.ui.select("Pick one", ["Option A", "Option B"]);
1171
- const text = await ctx.ui.input("Enter value");
1172
-
1173
- // Notifications
1174
- ctx.ui.notify("Done!", "success"); // success, info, warning, error
1175
-
1176
- // Status line (persistent in footer, multiple extensions can set their own)
1177
- ctx.ui.setStatus("my-ext", "Processing...");
1178
- ctx.ui.setStatus("my-ext", null); // Clear
1179
-
1180
- // Widgets (above editor by default)
1181
- ctx.ui.setWidget("my-ext", ["Line 1", "Line 2"]);
1182
- ctx.ui.setWidget("my-ext", ["Line 1", "Line 2"], { placement: "belowEditor" });
1183
-
1184
- // Custom footer (replaces built-in footer)
1185
- ctx.ui.setFooter((tui, theme) => ({
1186
- render(width) { return [theme.fg("dim", "Custom footer")]; },
1187
- invalidate() {},
1188
- }));
1189
- ctx.ui.setFooter(undefined); // Restore built-in footer
1190
-
1191
- // Full custom component with keyboard handling
1192
- await ctx.ui.custom((tui, theme, done) => ({
1193
- render(width) {
1194
- return [
1195
- theme.bold("My Component"),
1196
- theme.fg("dim", "Press Escape to close"),
1197
- ];
1198
- },
1199
- handleInput(data) {
1200
- if (matchesKey(data, "escape")) done();
1201
- },
1202
- }));
1203
- ```
458
+ | Option | Description |
459
+ |--------|-------------|
460
+ | `--tools <list>` | Enable specific built-in tools (default: `read,bash,edit,write`) |
461
+ | `--no-tools` | Disable all built-in tools (extension tools still work) |
1204
462
 
1205
- > See [docs/extensions.md](docs/extensions.md) for full API reference.
1206
- > See [docs/tui.md](docs/tui.md) for TUI components and custom rendering.
1207
- > See [examples/extensions/](examples/extensions/) for working examples.
463
+ Available built-in tools: `read`, `bash`, `edit`, `write`, `grep`, `find`, `ls`
1208
464
 
1209
- ---
465
+ ### Resource Options
1210
466
 
1211
- ## CLI Reference
467
+ | Option | Description |
468
+ |--------|-------------|
469
+ | `-e`, `--extension <source>` | Load extension from path, npm, or git (repeatable) |
470
+ | `--no-extensions` | Disable extension discovery |
471
+ | `--skill <path>` | Load skill (repeatable) |
472
+ | `--no-skills` | Disable skill discovery |
473
+ | `--prompt-template <path>` | Load prompt template (repeatable) |
474
+ | `--no-prompt-templates` | Disable prompt template discovery |
475
+ | `--theme <path>` | Load theme (repeatable) |
476
+ | `--no-themes` | Disable theme discovery |
1212
477
 
1213
- ```bash
1214
- pi [options] [@files...] [messages...]
1215
- ```
478
+ Combine `--no-*` with explicit flags to load exactly what you need, ignoring settings.json (e.g., `--no-extensions -e ./my-ext.ts`).
1216
479
 
1217
- ### Options
480
+ ### Other Options
1218
481
 
1219
482
  | Option | Description |
1220
483
  |--------|-------------|
1221
- | `--provider <name>` | Provider: `anthropic`, `openai`, `openai-codex`, `google`, `google-vertex`, `amazon-bedrock`, `mistral`, `xai`, `groq`, `cerebras`, `openrouter`, `vercel-ai-gateway`, `zai`, `opencode`, `minimax`, `minimax-cn`, `github-copilot`, `google-gemini-cli`, `google-antigravity`, or custom |
1222
- | `--model <id>` | Model ID |
1223
- | `--api-key <key>` | API key (overrides environment) |
1224
- | `--system-prompt <text\|file>` | Custom system prompt (text or file path) |
1225
- | `--append-system-prompt <text\|file>` | Append to system prompt |
1226
- | `--mode <mode>` | Output mode: `text`, `json`, `rpc` (implies `--print`) |
1227
- | `--print`, `-p` | Non-interactive: process prompt and exit |
1228
- | `--no-session` | Don't save session |
1229
- | `--session <path>` | Use specific session file |
1230
- | `--session-dir <dir>` | Directory for session storage and lookup |
1231
- | `--continue`, `-c` | Continue most recent session |
1232
- | `--resume`, `-r` | Select session to resume |
1233
- | `--models <patterns>` | Comma-separated patterns for Ctrl+P cycling. Supports glob patterns (e.g., `anthropic/*`, `*sonnet*:high`) and fuzzy matching (e.g., `sonnet,haiku:low`) |
1234
- | `--no-tools` | Disable all built-in tools |
1235
- | `--tools <tools>` | Comma-separated tool list (default: `read,bash,edit,write`) |
1236
- | `--thinking <level>` | Thinking level: `off`, `minimal`, `low`, `medium`, `high` |
1237
- | `--extension <path>`, `-e` | Load an extension file (can be used multiple times) |
1238
- | `--no-extensions` | Disable extension discovery (explicit `-e` paths still work) |
1239
- | `--no-skills` | Disable skills discovery and loading |
1240
- | `--skills <patterns>` | Comma-separated glob patterns to filter skills (e.g., `git-*,docker`) |
1241
- | `--export <file> [output]` | Export session to HTML |
1242
- | `--help`, `-h` | Show help |
1243
- | `--version`, `-v` | Show version |
484
+ | `--system-prompt <text>` | Replace default prompt (context files and skills still appended) |
485
+ | `--append-system-prompt <text>` | Append to system prompt |
486
+ | `--verbose` | Force verbose startup |
487
+ | `-h`, `--help` | Show help |
488
+ | `-v`, `--version` | Show version |
1244
489
 
1245
490
  ### File Arguments
1246
491
 
1247
- Include files with `@` prefix:
492
+ Prefix files with `@` to include in the message:
1248
493
 
1249
494
  ```bash
1250
495
  pi @prompt.md "Answer this"
1251
- pi @screenshot.png "What's in this image?"
1252
- pi @requirements.md @design.png "Implement this"
496
+ pi -p @screenshot.png "What's in this image?"
497
+ pi @code.ts @test.ts "Review these files"
1253
498
  ```
1254
499
 
1255
- Text files wrapped in `<file name="path">content</file>`. Images attached as base64.
1256
-
1257
500
  ### Examples
1258
501
 
1259
502
  ```bash
1260
- # Interactive mode
1261
- pi
1262
-
1263
503
  # Interactive with initial prompt
1264
504
  pi "List all .ts files in src/"
1265
505
 
1266
506
  # Non-interactive
1267
- pi -p "List all .ts files in src/"
1268
-
1269
- # With files
1270
- pi -p @code.ts "Review this code"
507
+ pi -p "Summarize this codebase"
1271
508
 
1272
- # JSON event stream
1273
- pi --mode json "List files"
1274
-
1275
- # RPC mode (headless)
1276
- pi --mode rpc --no-session
1277
-
1278
- # Continue session
1279
- pi -c "What did we discuss?"
1280
-
1281
- # Specific model
509
+ # Different model
1282
510
  pi --provider openai --model gpt-4o "Help me refactor"
1283
511
 
1284
- # Model cycling with thinking levels
1285
- pi --models sonnet:high,haiku:low
1286
-
1287
- # Limit to specific provider with glob pattern
1288
- pi --models "github-copilot/*"
512
+ # Limit model cycling
513
+ pi --models "claude-*,gpt-4o"
1289
514
 
1290
515
  # Read-only mode
1291
- pi --tools read,grep,find,ls -p "Review the architecture"
516
+ pi --tools read,grep,find,ls -p "Review the code"
1292
517
 
1293
- # Export session
1294
- pi --export session.jsonl output.html
518
+ # High thinking level
519
+ pi --thinking high "Solve this complex problem"
1295
520
  ```
1296
521
 
1297
522
  ### Environment Variables
1298
523
 
1299
524
  | Variable | Description |
1300
525
  |----------|-------------|
1301
- | `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, etc. | API keys for providers (see [API Keys & OAuth](#api-keys--oauth)) |
1302
- | `PI_CODING_AGENT_DIR` | Override the agent config directory (default: `~/.pi/agent`) |
1303
- | `PI_SKIP_VERSION_CHECK` | Skip new version check at startup (useful for Nix or other package manager installs) |
1304
- | `VISUAL`, `EDITOR` | External editor for Ctrl+G (e.g., `vim`, `code --wait`) |
1305
-
1306
- ---
1307
-
1308
- ## Tools
1309
-
1310
- ### Default Tools
1311
-
1312
- | Tool | Description |
1313
- |------|-------------|
1314
- | `read` | Read file contents. Images sent as attachments. Text: first 2000 lines, lines truncated at 2000 chars. Use offset/limit for large files. |
1315
- | `write` | Write/overwrite file. Creates parent directories. |
1316
- | `edit` | Replace exact text in file. Must match exactly including whitespace. Fails if text appears multiple times or not found. |
1317
- | `bash` | Execute command. Returns stdout/stderr. Optional `timeout` parameter. |
1318
-
1319
- ### Read-Only Tools
1320
-
1321
- Available via `--tools` flag:
1322
-
1323
- | Tool | Description |
1324
- |------|-------------|
1325
- | `grep` | Search file contents (regex or literal). Respects `.gitignore`. |
1326
- | `find` | Search for files by glob pattern. Respects `.gitignore`. |
1327
- | `ls` | List directory contents. Includes dotfiles. |
1328
-
1329
- Example: `--tools read,grep,find,ls` for code review without modification.
1330
-
1331
- For adding new tools, see [Extensions](#extensions) in the Customization section.
1332
-
1333
- ---
1334
-
1335
- ## Programmatic Usage
1336
-
1337
- ### SDK
1338
-
1339
- For embedding pi in Node.js/TypeScript applications, use the SDK:
1340
-
1341
- ```typescript
1342
- import { createAgentSession, discoverAuthStorage, discoverModels, SessionManager } from "@mariozechner/pi-coding-agent";
1343
-
1344
- const authStorage = discoverAuthStorage();
1345
- const modelRegistry = discoverModels(authStorage);
1346
-
1347
- const { session } = await createAgentSession({
1348
- sessionManager: SessionManager.inMemory(),
1349
- authStorage,
1350
- modelRegistry,
1351
- });
1352
-
1353
- session.subscribe((event) => {
1354
- if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
1355
- process.stdout.write(event.assistantMessageEvent.delta);
1356
- }
1357
- });
1358
-
1359
- await session.prompt("What files are in the current directory?");
1360
- ```
1361
-
1362
- The SDK provides full control over:
1363
- - Model selection and thinking level
1364
- - System prompt (replace or modify)
1365
- - Tools (built-in subsets, custom tools)
1366
- - Extensions (discovered or via paths)
1367
- - Skills, context files, prompt templates
1368
- - Session persistence (`SessionManager`)
1369
- - Settings (`SettingsManager`)
1370
- - API key resolution and OAuth
1371
-
1372
- **Philosophy:** "Omit to discover, provide to override." Omit an option and pi discovers from standard locations. Provide an option and your value is used.
1373
-
1374
- > See [SDK Documentation](docs/sdk.md) for the full API reference. See [examples/sdk/](examples/sdk/) for working examples from minimal to full control.
1375
-
1376
- ### RPC Mode
1377
-
1378
- For embedding pi from other languages or with process isolation:
1379
-
1380
- ```bash
1381
- pi --mode rpc --no-session
1382
- ```
1383
-
1384
- Send JSON commands on stdin:
1385
- ```json
1386
- {"type":"prompt","message":"List all .ts files"}
1387
- {"type":"abort"}
1388
- ```
1389
-
1390
- > See [RPC Documentation](docs/rpc.md) for the full protocol.
1391
-
1392
- ### HTML Export
1393
-
1394
- ```bash
1395
- pi --export session.jsonl # Auto-generated filename
1396
- pi --export session.jsonl output.html # Custom filename
1397
- ```
1398
-
1399
- Works with session files.
526
+ | `PI_CODING_AGENT_DIR` | Override config directory (default: `~/.pi/agent`) |
527
+ | `PI_SKIP_VERSION_CHECK` | Skip version check at startup |
528
+ | `VISUAL`, `EDITOR` | External editor for Ctrl+G |
1400
529
 
1401
530
  ---
1402
531
 
1403
- ## Philosophy
1404
-
1405
- Pi is opinionated about what it won't do. These are intentional design decisions to minimize context bloat and avoid anti-patterns.
1406
-
1407
- **No MCP.** Build CLI tools with READMEs (see [Skills](#skills)). The agent reads them on demand. [Would you like to know more?](https://mariozechner.at/posts/2025-11-02-what-if-you-dont-need-mcp/)
1408
-
1409
- **No sub-agents.** Spawn pi instances via tmux, or [build your own sub-agent tool](examples/extensions/subagent/) with [Extensions](#extensions). Full observability and steerability.
1410
-
1411
- **No permission popups.** Security theater. Run in a container or build your own with [Extensions](#extensions).
1412
-
1413
- **No plan mode.** Gather context in one session, write plans to file, start fresh for implementation.
1414
-
1415
- **No built-in to-dos.** They confuse models. Use a TODO.md file, or [build your own](examples/extensions/todo.ts) with [Extensions](#extensions).
1416
-
1417
- **No background bash.** Use tmux. Full observability, direct interaction.
1418
-
1419
- Read the [blog post](https://mariozechner.at/posts/2025-11-30-pi-coding-agent/) for the full rationale.
1420
-
1421
- ---
1422
-
1423
- ## Development
1424
-
1425
- ### Forking / Rebranding
1426
-
1427
- Configure via `package.json`:
1428
-
1429
- ```json
1430
- {
1431
- "piConfig": {
1432
- "name": "pi",
1433
- "configDir": ".pi"
1434
- }
1435
- }
1436
- ```
1437
-
1438
- Change `name`, `configDir`, and `bin` field for your fork. Affects CLI banner, config paths, and environment variable names.
1439
-
1440
- ### Path Resolution
1441
-
1442
- Three execution modes: npm install, standalone binary, tsx from source.
1443
-
1444
- **Always use `src/paths.ts`** for package assets:
1445
-
1446
- ```typescript
1447
- import { getPackageDir, getThemeDir } from "./paths.js";
1448
- ```
1449
-
1450
- Never use `__dirname` directly for package assets.
1451
-
1452
- ### Debug Command
532
+ ## Contributing & Development
1453
533
 
1454
- `/debug` (hidden) writes rendered lines with ANSI codes to `~/.pi/agent/pi-debug.log` for TUI debugging, as well as the last set of messages that were sent to the LLM.
534
+ See [CONTRIBUTING.md](../../CONTRIBUTING.md) for guidelines and [docs/development.md](docs/development.md) for setup, forking, and debugging.
1455
535
 
1456
536
  ---
1457
537