@counterposition/skill-pi 0.80.3 → 0.84.2
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/package.json
CHANGED
package/skills/pi/SKILL.md
CHANGED
|
@@ -7,7 +7,7 @@ compatibility: "Pi-specific guidance for agents that support Agent Skills"
|
|
|
7
7
|
|
|
8
8
|
# Pi Coding Agent
|
|
9
9
|
|
|
10
|
-
Pi is a minimal terminal coding harness. Default tools: `read`, `write`, `edit`, `bash`, `grep`, `find`, `ls
|
|
10
|
+
Pi is a minimal terminal coding harness. Default tools: `read`, `write`, `edit`, `bash`, `grep`, `find`, `ls` (configurable via the `defaultTools` setting since Pi 0.84.2). Modes: interactive (`pi`), print (`pi -p`), JSON (`--mode json`), RPC (`--mode rpc`), or embedded (`createAgentSession()`). Sub-agents, plan mode, permission flows, and MCP are intentionally left to extensions and Pi packages. Skill synced with Pi 0.84.2.
|
|
11
11
|
|
|
12
12
|
Pi's philosophy: **adapt Pi to your workflows, not the other way around**.
|
|
13
13
|
|
|
@@ -20,8 +20,10 @@ Core packages on npm (source: [github.com/earendil-works/pi](https://github.com/
|
|
|
20
20
|
| `@earendil-works/pi-ai` | Unified LLM API across 20+ providers |
|
|
21
21
|
| `@earendil-works/pi-agent-core` | Agent runtime with tool execution and state |
|
|
22
22
|
| `@earendil-works/pi-tui` | Terminal UI components |
|
|
23
|
-
| `@earendil-works/pi-coding-agent` | CLI, extensions, skills, sessions, settings |
|
|
23
|
+
| `@earendil-works/pi-coding-agent` | CLI, extensions, skills, sessions, settings (also exports `./client` for remote sessions and `./rpc-entry`) |
|
|
24
24
|
| `@earendil-works/pi-web-ui` | Web components for chat interfaces |
|
|
25
|
+
| `@earendil-works/pi-client` / `@earendil-works/pi-protocol` | Experimental remote-session client and wire protocol (Pi 0.84.0) |
|
|
26
|
+
| `@earendil-works/pi-telemetry` | Vendor-neutral telemetry contracts (Pi 0.84.0) |
|
|
25
27
|
|
|
26
28
|
## File System Layout
|
|
27
29
|
|
|
@@ -54,9 +56,9 @@ Core packages on npm (source: [github.com/earendil-works/pi](https://github.com/
|
|
|
54
56
|
- **Settings** — Hierarchical JSON: project `.pi/settings.json` merges over global `~/.pi/agent/settings.json`. → `references/settings.md`
|
|
55
57
|
- **Packages** — Bundles of extensions/skills/prompts/themes via npm, git, or local paths. Installed with `pi install`. → `references/packages.md`
|
|
56
58
|
- **Project trust** — Pi 0.79+ asks before loading project-local settings, resources, and packages; decisions persist in `~/.pi/agent/trust.json`. `--approve`/`--no-approve` override per run; `defaultProjectTrust` sets the non-interactive fallback. → `references/settings.md`
|
|
57
|
-
- **Context files & prompt templates** — Pi loads `AGENTS.md` / `CLAUDE.md` from the agent dir and from `cwd` up through ancestors. `.pi/SYSTEM.md` replaces the system prompt; `APPEND_SYSTEM.md` appends. Prompt templates in `prompts/` become slash commands. → `references/settings.md`
|
|
59
|
+
- **Context files & prompt templates** — Pi loads `AGENTS.md` / `CLAUDE.md` from the agent dir and from `cwd` up through ancestors. Per-directory `AGENTS.override.md` (Pi 0.84.0) replaces same-directory context files while others layer normally. `.pi/SYSTEM.md` replaces the system prompt; `APPEND_SYSTEM.md` appends. Prompt templates in `prompts/` become slash commands. → `references/settings.md`
|
|
58
60
|
- **SDK** — Programmatic embedding via `createAgentSession()`; `createAgentSessionRuntime()` for session replacement. → `references/sdk.md`
|
|
59
|
-
- **Custom providers & models** — `models.json` or extension `pi.registerProvider()` for any OpenAI-/Anthropic-/Google-compatible or custom LLM endpoint. → `references/providers.md`
|
|
61
|
+
- **Custom providers & models** — `models.json` or extension `pi.registerProvider()` (config form or complete pi-ai providers) for any OpenAI-/Anthropic-/Google-compatible or custom LLM endpoint. → `references/providers.md`
|
|
60
62
|
- **Sessions & compaction** — Append-only JSONL with a tree structure; branch with `/tree`, `/fork`, `/clone`, compact with `/compact`. Auto-compaction triggers when `contextTokens > contextWindow - reserveTokens`. Extensions intercept via `session_before_compact`. → `references/extensions.md` and `references/sdk.md`
|
|
61
63
|
|
|
62
64
|
## How to Use This Skill
|
|
@@ -23,7 +23,7 @@ import { StringEnum } from "@earendil-works/pi-ai";
|
|
|
23
23
|
import { Text } from "@earendil-works/pi-tui";
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
- Use `typebox` (1.x) for schemas.
|
|
26
|
+
- Use `typebox` (1.x) for schemas. Pi 0.83.0 bundles TypeBox 1.3.7, which removed deprecated APIs (`Type.Base`, `Type.Awaited`, `Type.Promise`, `Type.AsyncIterator`, `Type.Iterator`, `Type.Options`, `Value.Mutate`) — migrate extension sources off those before typechecking against current Pi.
|
|
27
27
|
- Use `StringEnum` from `@earendil-works/pi-ai` for Google-compatible string enums.
|
|
28
28
|
- Pi 0.80.0 moved pi-ai's old global API (`getModel`, `getModels`, `stream`, `complete`, `registerApiProvider`, ...) off the pi-ai root entrypoint to `@earendil-works/pi-ai/compat`. Extensions keep working unchanged at runtime (the extension loader aliases the root to the compat superset), but extension sources that typecheck against pi-ai's published types must import those APIs from `@earendil-works/pi-ai/compat`. `StringEnum` and the type surface remain on the root. The compat entrypoint and loader alias will be removed in a future release.
|
|
29
29
|
|
|
@@ -90,13 +90,15 @@ Useful agent events:
|
|
|
90
90
|
- `input` — carries `event.streamingBehavior` (`"steer" | "followUp" | undefined`) so handlers can distinguish idle prompts, mid-stream steers, and queued follow-ups; return `{ action: "transform" | "handled" | "continue" }`
|
|
91
91
|
- `before_agent_start` — receives `event.systemPromptOptions` (a `BuildSystemPromptOptions`) so handlers can inspect the structured inputs feeding the system prompt
|
|
92
92
|
- `agent_start`
|
|
93
|
-
- `agent_end`
|
|
93
|
+
- `agent_end` — one low-level run; Pi may still auto-retry, auto-compact and retry, or continue with queued follow-ups
|
|
94
|
+
- `agent_settled` (Pi 0.80.4) — fired when no retry/compaction/follow-up remains; use for status integrations that need to know Pi will not continue automatically (`ctx.isIdle()` is true here unless another extension started a new run)
|
|
94
95
|
- `turn_start`
|
|
95
96
|
- `turn_end`
|
|
96
97
|
- `message_start`
|
|
97
98
|
- `message_update`
|
|
98
99
|
- `message_end` — return a replacement message to override usage/cost or rewrite the finalized assistant message
|
|
99
100
|
- `context`
|
|
101
|
+
- `before_provider_headers` (Pi 0.80.4) — mutate `event.headers` in place after outgoing HTTP headers are assembled: set a key to a string to add/override, `null` to delete. Runs once per provider request; retries reuse the same headers
|
|
100
102
|
- `before_provider_request`
|
|
101
103
|
- `after_provider_response` — inspect the provider HTTP status and headers before stream consumption
|
|
102
104
|
- `model_select`
|
|
@@ -110,7 +112,7 @@ Useful tool events:
|
|
|
110
112
|
- `tool_result`
|
|
111
113
|
- `tool_execution_end`
|
|
112
114
|
|
|
113
|
-
Tool results may include `terminate: true` to end the current tool batch without an automatic follow-up LLM turn — useful for tools that produce a structured final answer (see `examples/extensions/structured-output.ts` in the Pi repo).
|
|
115
|
+
Tool results may include `terminate: true` to end the current tool batch without an automatic follow-up LLM turn — useful for tools that produce a structured final answer (see `examples/extensions/structured-output.ts` in the Pi repo). Since Pi 0.84.1, blocked `tool_call` results may also return `terminate: true`; the agent stops early only when every finalized result in the batch is terminating. Tools that make nested LLM calls can return their combined `Usage` as `usage` on the tool result — Pi persists it and includes it in footer, `/session`, and RPC session totals (Pi 0.81.0), and `tool_result` handlers may inspect or replace that value.
|
|
114
116
|
|
|
115
117
|
`session_shutdown` events carry `event.reason` (`"quit" | "reload" | "new" | "resume" | "fork"`) and, where applicable, `event.targetSessionFile` so cleanup logic can distinguish teardown paths.
|
|
116
118
|
|
|
@@ -121,8 +123,8 @@ Tool results may include `terminate: true` to end the current tool batch without
|
|
|
121
123
|
- `ctx.ui` for interactive UI hooks
|
|
122
124
|
- `ctx.mode` — `"tui" | "rpc" | "json" | "print"`; gate terminal-only features on `ctx.mode === "tui"`
|
|
123
125
|
- `ctx.cwd`
|
|
124
|
-
- `ctx.sessionManager` (read-only)
|
|
125
|
-
- `ctx.modelRegistry` / `ctx.model`
|
|
126
|
+
- `ctx.sessionManager` (read-only; `buildContextEntries()` returns active-branch entries with compaction applied, Pi 0.80.4)
|
|
127
|
+
- `ctx.modelRegistry` / `ctx.model` / `ctx.thinkingLevel` / `ctx.scopedModels` (Pi 0.83.0) — `ctx.modelRegistry` is the synchronous extension-facing facade; its `refresh()` became `Promise<void>` in Pi 0.80.8 (await it before synchronous registry reads). Since Pi 0.84.x it also exposes `getProvider(id)` (effective pi-ai provider) and `getProviderAuth(id)` (API key, headers, base URL, provider-scoped env — no loaded model required). `ctx.scopedModels` is the read-only session model scope resolved from `--models`/`enabledModels` (`{ model, thinkingLevel? }[]`, empty when unscoped); prefer it over enumerating `getAvailable()` for model pickers
|
|
126
128
|
- `ctx.hasUI` — `true` in TUI and RPC modes
|
|
127
129
|
- `ctx.signal` — the active agent abort signal (or `undefined` when idle); pass it to `fetch`/model calls for abort-aware nested work
|
|
128
130
|
- `ctx.isIdle()` / `ctx.hasPendingMessages()`
|
|
@@ -171,6 +173,42 @@ Important rules:
|
|
|
171
173
|
4. Use the file-mutation queue for write/edit style tools.
|
|
172
174
|
5. Put reconstructable state in `details`; it persists in session history.
|
|
173
175
|
|
|
176
|
+
## Dynamic Tool Loading
|
|
177
|
+
|
|
178
|
+
Pi 0.80.7 lets an extension register many tools while keeping only a small initial set active, then add more during execution — cache-friendly on models with native deferred loading. Lifecycle:
|
|
179
|
+
|
|
180
|
+
1. Register every tool with `pi.registerTool()` (all appear in `pi.getAllTools()`).
|
|
181
|
+
2. Keep a loader tool (e.g. `search_tools`) active; leave searchable tools inactive — e.g. on `session_start`, `pi.setActiveTools()` to the filtered set.
|
|
182
|
+
3. During loader execution, call `pi.setActiveTools([...pi.getActiveTools(), ...matches])`. The change must be purely additive; unknown names are ignored.
|
|
183
|
+
4. Pi records the added tools on that tool result and exposes their definitions before the next model response.
|
|
184
|
+
|
|
185
|
+
Native deferred loading preserves the cached prompt prefix on Anthropic Sonnet/Opus/Fable ≥ 4.5 (not Haiku) and OpenAI `gpt-5.4`+; Kimi K3 works via `compat.deferredToolsMode: "kimi"` (Pi 0.80.9). For verified custom models/proxies, enable `compat.supportsToolReferences: true` (`anthropic-messages`) or `compat.supportsToolSearch: true` (`openai-responses`/`openai-codex-responses`). All other models fall back to sending the full active tool list on the next request — activation still works, but may invalidate the provider's cached prefix. Non-additive changes (removals/replacements) always use the fallback.
|
|
186
|
+
|
|
187
|
+
Cache tips: keep the loader active for the whole session; add rather than replace. Activating a tool that has `promptSnippet`/`promptGuidelines` rebuilds the system prompt and can invalidate the prefix even with native support — lazily loaded tools should rely on their `description` alone.
|
|
188
|
+
|
|
189
|
+
## Constrained Tool Sampling
|
|
190
|
+
|
|
191
|
+
`ToolDefinition.constrainedSampling` (Pi 0.82.0) lets a tool prefer or require provider-side output constraints:
|
|
192
|
+
|
|
193
|
+
- `{ type: "json_schema", strict: "prefer" | "require" }` — strict JSON-schema constrained decoding of the tool's own TypeBox parameters
|
|
194
|
+
- `{ type: "grammar", variants: { openai_lark?: string, openai_regex?: string } }` — OpenAI Lark/regex grammar encodings
|
|
195
|
+
- Set `false` to explicitly disable for that tool
|
|
196
|
+
|
|
197
|
+
Model capability metadata gates what is actually sent: `compat.supportsStrictTools` / Anthropic built-ins enable strict JSON-schema tools, and `compat.supportsOpenAIGrammarTools` marks endpoints that accept Lark/regex grammar tools (enabled in generated metadata for GPT-5+ across OpenAI, Codex, Azure, GitHub Copilot, opencode, Cloudflare AI Gateway). Unsupported combinations fall back to normal function tools rather than failing. Independently, Pi 0.84.2 ships experimental strict JSON-schema sampling for its default `read`/`bash`/`edit`/`write` tools under `PI_EXPERIMENTAL=1`.
|
|
198
|
+
|
|
199
|
+
## Display Transformers
|
|
200
|
+
|
|
201
|
+
`pi.registerMarkdownTransformer(transformer)` (Pi 0.84.0) chains display-only Markdown transforms over user text, assistant text, and thinking blocks:
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
pi.registerMarkdownTransformer((markdown, { messageType, isStreaming }) => {
|
|
205
|
+
if (isStreaming || messageType === "assistant-thinking") return markdown;
|
|
206
|
+
return markdown.replaceAll("-->", "→");
|
|
207
|
+
});
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Context carries `messageType` (`"user" | "assistant" | "assistant-thinking"`), `isStreaming`, and `availableWidth` (terminal columns). The hook runs for new messages, restored sessions, and terminal resizes, so keep it synchronous and cheap; a throwing transformer leaves prior output intact and Pi continues the chain. The session and model context are never modified — this is render-only.
|
|
211
|
+
|
|
174
212
|
## UI Methods
|
|
175
213
|
|
|
176
214
|
Check `ctx.hasUI` first. Non-interactive modes may not support UI.
|
|
@@ -240,6 +278,15 @@ Store extension state with custom session entries:
|
|
|
240
278
|
pi.appendEntry("my-extension-state", { key: "value" });
|
|
241
279
|
```
|
|
242
280
|
|
|
281
|
+
Custom entries never participate in LLM context. Since Pi 0.80.4 they can also render in the interactive transcript via `pi.registerEntryRenderer(customType, renderer)` — the TUI-only counterpart to `pi.registerMessageRenderer()` (whose custom messages DO enter LLM context via `pi.sendMessage()`):
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
pi.registerEntryRenderer("status-card", (entry, { expanded }, theme) => {
|
|
285
|
+
return new Text(theme.fg("accent", JSON.stringify(entry.data)));
|
|
286
|
+
});
|
|
287
|
+
pi.appendEntry("status-card", { title: "Indexed files", count: 17 });
|
|
288
|
+
```
|
|
289
|
+
|
|
243
290
|
Use lifecycle hooks to restore it:
|
|
244
291
|
|
|
245
292
|
```typescript
|
|
@@ -280,12 +327,18 @@ pi.registerProvider("anthropic", { baseUrl: "https://proxy.example.com" });
|
|
|
280
327
|
pi.unregisterProvider("my-provider");
|
|
281
328
|
```
|
|
282
329
|
|
|
330
|
+
Dynamic providers can implement `refreshModels(context)` (Pi 0.80.8) for model discovery: Pi calls it during catalog refresh (`/model`, `pi update --models`) and publishes the returned list; its models replace extension-provided `models`. Since Pi 0.84.0 the context is read-snapshot + generation-checked publication: read `context.stored` (the persisted provider snapshot) instead of `context.store`, and persist through `context.publish({ update?, persist? })` — `persist` omitted leaves storage unchanged, a `ModelsStoreEntry` writes it, `persist: null` deletes it. Config-form callbacks that only return models remain unchanged.
|
|
331
|
+
|
|
332
|
+
Since Pi 0.81.0, extensions can also register a complete pi-ai `Provider` via `pi.registerProvider(createProvider({...}))` — native auth (`login`/`resolve`), `getModels`, `refreshModels`, `filterModels`, and custom streaming. The registered provider becomes the composition base; `models.json` overrides still apply above it. Prefer this when you need real authentication or stream behavior rather than just a model list. The legacy config form (`name`, `baseUrl`, `apiKey`, `models`, `oauth`, `streamSimple`) remains supported. OAuth `refreshToken(credentials, signal)` callbacks must accept and honor the abort signal since Pi 0.84.0.
|
|
333
|
+
|
|
283
334
|
If you need auth for a specific model request, use:
|
|
284
335
|
|
|
285
336
|
```typescript
|
|
286
337
|
const auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);
|
|
287
338
|
```
|
|
288
339
|
|
|
340
|
+
(Still supported for extensions in Pi 0.80.8+; SDK code should use `ModelRuntime.getAuth()` — see `references/sdk.md`. `ProviderHeaders` values are `string | null` since Pi 0.84.0, where `null` is a delete marker: handle `null` when inspecting, pass through unchanged when forwarding to pi-ai streams.)
|
|
341
|
+
|
|
289
342
|
Pass `shouldStopAfterTurn` via the SDK to exit the agent loop gracefully after a completed turn. See `references/sdk.md` and `references/providers.md` for the full provider/model schema.
|
|
290
343
|
|
|
291
344
|
## Handy Patterns
|
|
@@ -19,9 +19,11 @@ pi list
|
|
|
19
19
|
pi update # update pi only (changed in Pi 0.79.7)
|
|
20
20
|
pi update --all # update pi + packages, reconcile pinned git refs
|
|
21
21
|
pi update --extensions # update packages only
|
|
22
|
+
pi update --models # refresh model catalogs only (Pi 0.80.8)
|
|
22
23
|
pi update --self # update pi only
|
|
23
24
|
pi update <source> # update one package
|
|
24
|
-
pi config
|
|
25
|
+
pi config # starts in global settings; Tab switches scope
|
|
26
|
+
pi config -l # start in project overrides (.pi/settings.json)
|
|
25
27
|
```
|
|
26
28
|
|
|
27
29
|
By default, `install` and `remove` write to user settings (`~/.pi/agent/settings.json`). Use `-l` to write to project settings (`.pi/settings.json`) instead. `pi update` installs the exact version returned by the update check.
|
|
@@ -99,6 +101,7 @@ If there is no `pi` manifest, Pi auto-discovers:
|
|
|
99
101
|
- `@earendil-works/pi-coding-agent`
|
|
100
102
|
- `@earendil-works/pi-tui`
|
|
101
103
|
- `typebox`
|
|
104
|
+
- Pin dev dependencies to a current Pi line (e.g. `^0.84.2`) so typecheck/tests validate against what users run; keep peers `"*"` so installs stay compatible across Pi versions
|
|
102
105
|
- Other Pi packages must be bundled explicitly
|
|
103
106
|
- Git package installs run `npm install --omit=dev` — runtime needs go in `dependencies`, not `devDependencies`
|
|
104
107
|
|
|
@@ -129,6 +132,6 @@ Rules:
|
|
|
129
132
|
|
|
130
133
|
## Scope and Deduplication
|
|
131
134
|
|
|
132
|
-
- Project settings override global settings for the same package identity
|
|
135
|
+
- Project settings override global settings for the same package identity — unless the project entry has `autoload: false`, in which case it is applied as a delta over the global entry (Pi 0.80.4)
|
|
133
136
|
- Identity is package name for npm, repo URL for git, and resolved absolute path for local sources
|
|
134
|
-
- `pi config` can enable or disable package resources after installation
|
|
137
|
+
- `pi config` can enable or disable package resources after installation; since Pi 0.80.4 it manages global vs project-local scopes (Tab to switch, `pi config -l` to start in project mode with inherited global resources dimmed)
|
|
@@ -9,8 +9,13 @@ Use `/login` in interactive mode, then select a provider. The `/login` selector
|
|
|
9
9
|
- Anthropic Claude Pro / Max — third-party usage draws from extra usage and is billed per token (suppress the warning via `warnings.anthropicExtraUsage`)
|
|
10
10
|
- OpenAI ChatGPT Plus / Pro (Codex) — `/login` defaults to browser auth but can use a device-code flow for headless environments
|
|
11
11
|
- GitHub Copilot
|
|
12
|
+
- OpenRouter (Pi 0.82.0) — `/login openrouter` runs a PKCE flow that mints a user-controlled API key billed from OpenRouter credits; on headless/SSH hosts paste the redirect URL or authorization code into the prompt (Pi 0.83.0). `OPENROUTER_API_KEY` still works via **Use an API key**
|
|
13
|
+
- xAI (Grok/X subscription, Pi 0.80.8) — `/login xai` then **Use a subscription** (device-code OAuth); `XAI_API_KEY` remains available via **Use an API key**
|
|
14
|
+
- Radius (Pi 0.80.8) — a dynamic `pi-messages` gateway; `/login radius` stores OAuth tokens, and custom Radius gateways can be declared in `models.json` with `"oauth": "radius"` plus a gateway `baseUrl`
|
|
12
15
|
|
|
13
|
-
Use `/logout` to clear stored OAuth credentials. Pi 0.71.0 removed built-in Google Gemini CLI and Google Antigravity providers.
|
|
16
|
+
`/login <provider>` with autocomplete works since Pi 0.80.4, and login methods are provider-owned since 0.80.8 (registered pi-ai providers expose their own auth options and status in `/login`). Use `/logout` to clear stored OAuth credentials. Pi 0.71.0 removed built-in Google Gemini CLI and Google Antigravity providers. `pi auth check [provider|model]` (Pi 0.84.1) preflights credential readiness; `pi auth print-api-key` / `pi auth print-bearer-token` (Pi 0.83.0) export resolved credentials to external clients, refreshing OAuth as needed.
|
|
17
|
+
|
|
18
|
+
Since Pi 0.80.8, built-in catalogs are complemented by dynamic ones: `/model` refreshes configured providers in the background, `pi update --models` forces an immediate refresh, and refreshed catalogs are cached in `~/.pi/agent/models-store.json` for offline use. Refreshes revalidate with `If-None-Match` since Pi 0.82.1 so unchanged catalogs answer `304`.
|
|
14
19
|
|
|
15
20
|
## API Key Providers
|
|
16
21
|
|
|
@@ -35,12 +40,17 @@ Use `/logout` to clear stored OAuth credentials. Pi 0.71.0 removed built-in Goog
|
|
|
35
40
|
| ZAI Coding Plan (China) | `ZAI_CODING_CN_API_KEY` | `zai-coding-cn` |
|
|
36
41
|
| OpenCode Zen | `OPENCODE_API_KEY` | `opencode` |
|
|
37
42
|
| OpenCode Go | `OPENCODE_API_KEY` | `opencode-go` |
|
|
43
|
+
| Amazon Bedrock | `AWS_BEARER_TOKEN_BEDROCK` | `amazon-bedrock` |
|
|
44
|
+
| Radius | `RADIUS_API_KEY` | `radius` |
|
|
38
45
|
| Hugging Face | `HF_TOKEN` | `huggingface` |
|
|
39
46
|
| Fireworks | `FIREWORKS_API_KEY` | `fireworks` |
|
|
40
47
|
| Together AI | `TOGETHER_API_KEY` | `together` |
|
|
48
|
+
| Baseten | `BASETEN_API_KEY` | `baseten` |
|
|
41
49
|
| Kimi For Coding | `KIMI_API_KEY` | `kimi-coding` |
|
|
42
50
|
| MiniMax | `MINIMAX_API_KEY` | `minimax` |
|
|
43
51
|
| MiniMax (China) | `MINIMAX_CN_API_KEY` | `minimax-cn` |
|
|
52
|
+
| Qwen Token Plan / Individual | `QWEN_TOKEN_PLAN_API_KEY` | `qwen-token-plan` / `qwen-token-plan-individual` (Pi 0.81.0 / 0.84.1) |
|
|
53
|
+
| Qwen Token Plan (China) | `QWEN_TOKEN_PLAN_CN_API_KEY` | `qwen-token-plan-cn` (Pi 0.81.0) |
|
|
44
54
|
| Xiaomi MiMo | `XIAOMI_API_KEY` | `xiaomi` |
|
|
45
55
|
| Xiaomi MiMo Token Plan (CN/AMS/SGP) | `XIAOMI_TOKEN_PLAN_{CN,AMS,SGP}_API_KEY` | `xiaomi-token-plan-{cn,ams,sgp}` |
|
|
46
56
|
|
|
@@ -99,7 +109,7 @@ export AZURE_OPENAI_DEPLOYMENT_NAME_MAP=gpt-4o=my-gpt4o
|
|
|
99
109
|
|
|
100
110
|
### Amazon Bedrock
|
|
101
111
|
|
|
102
|
-
Pi
|
|
112
|
+
`/login amazon-bedrock` stores a Bedrock API key (Pi 0.80.7). Ambient AWS credential flows also work — these keep using SigV4 authentication:
|
|
103
113
|
|
|
104
114
|
- `AWS_PROFILE`
|
|
105
115
|
- `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`
|
|
@@ -182,15 +192,24 @@ Common `api` values:
|
|
|
182
192
|
|
|
183
193
|
### Model & Compatibility Knobs
|
|
184
194
|
|
|
185
|
-
- `
|
|
195
|
+
- `samplingParams` (Pi 0.84.0) is a free-form object merged verbatim into every request body after pi's own fields (its keys win) — for OpenAI-compatible APIs only (`openai-completions`, `openai-responses`, `azure-openai-responses`). Use it for server-specific knobs like llama.cpp `min_p` or vLLM `top_k`; in `modelOverrides` it merges per key.
|
|
196
|
+
- `thinkingLevelMap` (Pi 0.72) replaces `compat.reasoningEffortMap`. Map pi levels (`off`/`minimal`/`low`/`medium`/`high`/`xhigh`/`max`) to provider values; use `null` to hide a level. Maps may contain holes (Pi 0.80.6) — e.g. expose `high` and `max` without `xhigh`. When a key is omitted, standard levels through `high` use the provider default mapping, but the extended `xhigh`/`max` levels are unsupported.
|
|
197
|
+
- `cost` supports request-wide input pricing tiers (Pi 0.80.6): a `tiers` array where each tier supplies a complete alternate rate set and applies to the whole request when total input usage (`input + cacheRead + cacheWrite`) exceeds `inputTokensAbove`; the highest matching threshold wins. Also usable in `modelOverrides` and extension-registered providers.
|
|
198
|
+
- `modelOverrides` applies to built-in and (since Pi 0.80.4) extension-registered provider models; per-model fields: `name`, `reasoning`, `thinkingLevelMap`, `input`, `cost` (partial), `contextWindow`, `maxTokens`, `samplingParams`, `headers`, `compat`.
|
|
186
199
|
- `openRouterRouting` is forwarded as-is in the OpenRouter `provider` field (fallbacks, ZDR, ignore lists, throughput/latency).
|
|
187
|
-
- `compat.thinkingFormat` supports OpenAI-compatible reasoning variants: `openrouter` sends `reasoning: { effort }`, `together` sends `reasoning: { enabled }` plus `reasoning_effort` when supported, `qwen-chat-template` targets local Qwen-compatible servers that read `chat_template_kwargs.enable_thinking`,
|
|
188
|
-
-
|
|
200
|
+
- `compat.thinkingFormat` supports OpenAI-compatible reasoning variants: `openrouter` sends `reasoning: { effort }`, `together` sends `reasoning: { enabled }` plus `reasoning_effort` when supported, `qwen-chat-template` targets local Qwen-compatible servers that read `chat_template_kwargs.enable_thinking`, `chat-template` (Pi 0.79.9) sends configurable `chat_template_kwargs` via `compat.chatTemplateKwargs` — e.g. `{ "thinking": { "$var": "thinking.enabled" } }` for DeepSeek models behind vLLM/Hugging Face chat templates — and `baseten` (Pi 0.84.0) sends `chat_template_args` via `compat.chatTemplateArgs`.
|
|
201
|
+
- **Breaking (Pi 0.80.7):** `compat.sendSessionIdHeader` was removed. Session affinity is now controlled by `compat.sessionAffinityFormat` (`"openai"` sends `session_id`/`x-client-request-id`, `"openai-nosession"` omits the underscore-containing `session_id` header, `"openrouter"` sends `x-session-id`; default auto-detected). Replace `sendSessionIdHeader: false` with `sessionAffinityFormat: "openai-nosession"`. `sendSessionAffinityHeaders` still gates the behavior for `openai-completions`.
|
|
202
|
+
- `compat.deferredToolsMode: "kimi"` (Pi 0.80.9) enables Kimi's deferred tool serialization; `compat.supportsToolReferences` / `compat.supportsToolSearch` enable native dynamic tool loading on verified custom endpoints, and `compat.supportsStrictTools` / `compat.supportsOpenAIGrammarTools` / per-model `constrainedSampling` gate constrained sampling (see `references/extensions.md`). `compat.supportsFinishReason: false` (Pi 0.84.0) tells pi to infer stop/toolUse for OpenAI-compatible streams that omit `finish_reason`.
|
|
203
|
+
- Advanced `compat` flags exist for proxy quirks (`cacheControlFormat` — now also covering tool-result text content, `supportsReasoningEffort`, `supportsLongCacheRetention`, `supportsEagerToolInputStreaming`, `supportsStrictMode`). See [Pi `docs/models.md`](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/models.md) when a proxy rejects pi's defaults.
|
|
189
204
|
|
|
190
205
|
### Context Overflow Recovery
|
|
191
206
|
|
|
192
207
|
Pi can auto-compact and retry when a provider fails with a recognized context-window overflow. For custom providers whose overflow text Pi does not recognize, use a provider-scoped `message_end` extension handler to rewrite the finalized assistant `errorMessage` so it starts with `context_length_exceeded`.
|
|
193
208
|
|
|
209
|
+
### llama.cpp
|
|
210
|
+
|
|
211
|
+
Pi supports the llama.cpp router server (Pi 0.81.0): configure with `/login llama.cpp`, search/download Hugging Face models and load/unload with live progress via `/llama`, then select loaded models in `/model`. The model catalog persists across restarts (fixed in Pi 0.82.1). See [Pi `docs/llama-cpp.md`](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/llama-cpp.md).
|
|
212
|
+
|
|
194
213
|
## Custom Providers via Extensions
|
|
195
214
|
|
|
196
215
|
Use extensions when you need custom streaming, custom headers, OAuth/device-flow logic, or want to override an existing provider's `baseUrl`/`headers`:
|
|
@@ -219,7 +238,7 @@ pi.registerProvider("anthropic", { baseUrl: "https://proxy.example.com" });
|
|
|
219
238
|
|
|
220
239
|
## SDK / Extension Auth Lookup
|
|
221
240
|
|
|
222
|
-
If extension
|
|
241
|
+
If extension code needs auth for a specific model request, use `getApiKeyAndHeaders(model)` rather than the removed `getApiKey(model)`:
|
|
223
242
|
|
|
224
243
|
```typescript
|
|
225
244
|
const auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);
|
|
@@ -228,4 +247,4 @@ if (!auth.ok) throw new Error(auth.error);
|
|
|
228
247
|
const { apiKey, headers } = auth;
|
|
229
248
|
```
|
|
230
249
|
|
|
231
|
-
This matters for providers whose headers or auth values resolve dynamically on every request.
|
|
250
|
+
This matters for providers whose headers or auth values resolve dynamically on every request. In SDK code, use `ModelRuntime.getAuth(providerOrModel)` instead (Pi 0.80.8) — passing a model also resolves built-in, `models.json`, and extension model headers; see `references/sdk.md`.
|
|
@@ -12,19 +12,16 @@ npm install @earendil-works/pi-coding-agent
|
|
|
12
12
|
|
|
13
13
|
```typescript
|
|
14
14
|
import {
|
|
15
|
-
AuthStorage,
|
|
16
15
|
createAgentSession,
|
|
17
|
-
|
|
16
|
+
ModelRuntime,
|
|
18
17
|
SessionManager,
|
|
19
18
|
} from "@earendil-works/pi-coding-agent";
|
|
20
19
|
|
|
21
|
-
const
|
|
22
|
-
const modelRegistry = ModelRegistry.create(authStorage);
|
|
20
|
+
const modelRuntime = await ModelRuntime.create();
|
|
23
21
|
|
|
24
22
|
const { session } = await createAgentSession({
|
|
25
23
|
sessionManager: SessionManager.inMemory(),
|
|
26
|
-
|
|
27
|
-
modelRegistry,
|
|
24
|
+
modelRuntime,
|
|
28
25
|
});
|
|
29
26
|
|
|
30
27
|
session.subscribe((event) => {
|
|
@@ -38,17 +35,16 @@ await session.prompt("What files are in the current directory?");
|
|
|
38
35
|
|
|
39
36
|
Run with `npx tsx my-script.ts`.
|
|
40
37
|
|
|
41
|
-
**
|
|
38
|
+
**Breaking (Pi 0.80.8):** `ModelRuntime` replaced the old `AuthStorage`/`ModelRegistry` pair as the SDK model/auth facade. `CreateAgentSessionOptions.authStorage` and `modelRegistry` are gone — pass the async `modelRuntime` instead. `AuthStorage` is no longer exported; use `ModelRuntime` (or a custom pi-ai `CredentialStore`), or `readStoredCredential()` for one-off reads of `auth.json`. `ModelRegistry` still exists only as the synchronous extension-facing compatibility facade, and its `refresh()` is now `Promise<void>`.
|
|
42
39
|
|
|
43
40
|
## Key Imports
|
|
44
41
|
|
|
45
42
|
```typescript
|
|
46
43
|
import {
|
|
47
|
-
AuthStorage,
|
|
48
44
|
createAgentSession,
|
|
49
45
|
DefaultResourceLoader,
|
|
50
46
|
defineTool,
|
|
51
|
-
|
|
47
|
+
ModelRuntime,
|
|
52
48
|
SessionManager,
|
|
53
49
|
} from "@earendil-works/pi-coding-agent";
|
|
54
50
|
import { getBuiltinModel } from "@earendil-works/pi-ai/providers/all";
|
|
@@ -60,16 +56,14 @@ import { getBuiltinModel } from "@earendil-works/pi-ai/providers/all";
|
|
|
60
56
|
|
|
61
57
|
```typescript
|
|
62
58
|
const cwd = "/path/to/project";
|
|
63
|
-
const
|
|
64
|
-
const modelRegistry = ModelRegistry.create(authStorage);
|
|
59
|
+
const modelRuntime = await ModelRuntime.create();
|
|
65
60
|
|
|
66
61
|
const { session } = await createAgentSession({
|
|
67
62
|
cwd,
|
|
68
63
|
agentDir: "~/.pi/agent",
|
|
69
|
-
|
|
70
|
-
modelRegistry,
|
|
64
|
+
modelRuntime,
|
|
71
65
|
model: getBuiltinModel("anthropic", "claude-opus-4-8"),
|
|
72
|
-
thinkingLevel: "medium",
|
|
66
|
+
thinkingLevel: "medium", // off | minimal | low | medium | high | xhigh | max
|
|
73
67
|
scopedModels: [
|
|
74
68
|
{ model: getBuiltinModel("anthropic", "claude-opus-4-8"), thinkingLevel: "high" },
|
|
75
69
|
],
|
|
@@ -90,6 +84,52 @@ Notes:
|
|
|
90
84
|
- `DefaultResourceLoader` loads extensions, skills, prompt templates, themes, and context files. Replace it to drive resource discovery from custom sources (and it must implement `loadProjectContextFiles()` if you want `AGENTS.md`/`CLAUDE.md` discovery; that helper is also exported standalone).
|
|
91
85
|
- Pass `shouldStopAfterTurn(state) => boolean` (Pi 0.72.0) to exit the agent loop gracefully after a completed turn.
|
|
92
86
|
|
|
87
|
+
## Models & Auth (`ModelRuntime`)
|
|
88
|
+
|
|
89
|
+
`ModelRuntime` (Pi 0.80.8) implements the pi-ai `Models` interface and owns credential storage. Auth resolution priority: runtime overrides (`setRuntimeApiKey`, not persisted) → stored credentials in `auth.json` → environment variables → fallback resolver for `models.json` keys.
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
import { InMemoryCredentialStore } from "@earendil-works/pi-ai";
|
|
93
|
+
import { ModelRuntime } from "@earendil-works/pi-coding-agent";
|
|
94
|
+
|
|
95
|
+
// Default: ~/.pi/agent/auth.json and ~/.pi/agent/models.json
|
|
96
|
+
const modelRuntime = await ModelRuntime.create();
|
|
97
|
+
|
|
98
|
+
// Model lookup (use pi-ai Models methods directly; the old
|
|
99
|
+
// getAll()/find()/getSnapshot() projections were removed)
|
|
100
|
+
const model = modelRuntime.getModel("my-provider", "my-model");
|
|
101
|
+
const available = await modelRuntime.getAvailable(); // only models with valid auth
|
|
102
|
+
|
|
103
|
+
// Provider-owned auth methods and current status
|
|
104
|
+
for (const provider of modelRuntime.getProviders()) {
|
|
105
|
+
const status = await modelRuntime.checkAuth(provider.id);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
modelRuntime.setRuntimeApiKey("anthropic", "sk-my-temp-key");
|
|
109
|
+
|
|
110
|
+
// Custom locations, or inject any pi-ai CredentialStore
|
|
111
|
+
const custom = await ModelRuntime.create({ authPath: "/my/auth.json", modelsPath: "/my/models.json" });
|
|
112
|
+
const inMemory = await ModelRuntime.create({ credentials: new InMemoryCredentialStore() });
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
`ModelRuntime.getAuth(providerOrModel)` assembles final request auth (replacing `ModelRegistry.getApiKeyAndHeaders()` on the SDK side); passing a model also resolves built-in, `models.json`, and extension model headers. Dynamic provider catalogs refresh via async `ModelRuntime.refresh()` and are cached in `~/.pi/agent/models-store.json`.
|
|
116
|
+
|
|
117
|
+
Pi 0.84.x made catalog refresh cancellation-aware: `refresh(options?)` accepts `{ providers?, allowNetwork?, force?, signal? }` and returns a `ModelsRefreshResult` (`{ errors, aborted }`) instead of discarding provider errors; `create({ signal })`, `login()`, `logout()`, and the now-async `setRuntimeApiKey()/removeRuntimeApiKey()` accept optional abort signals too (unbounded when omitted — applications own deadline policy). Credential mutations resolve once local state is consistent, without waiting for remote freshness; if that synchronization fails they reject with the exported `CredentialSynchronizationError` (inspect `providerId`, `operation`, `credential`, `cause` rather than retrying blindly). A failed refresh never undoes a committed credential change, and each `refresh()` starts a fresh generation so stale refreshes cannot publish afterward.
|
|
118
|
+
|
|
119
|
+
To match CLI model parsing, use the exported resolver helpers (Pi 0.80.4):
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
import { resolveCliModel, resolveModelScopeWithDiagnostics } from "@earendil-works/pi-coding-agent";
|
|
123
|
+
|
|
124
|
+
const cliModel = resolveCliModel({ cliModel: "anthropic/claude-opus-4-8:high", modelRuntime });
|
|
125
|
+
const { scopedModels, diagnostics } = await resolveModelScopeWithDiagnostics(
|
|
126
|
+
["anthropic/*:high", "gpt-5"],
|
|
127
|
+
modelRuntime,
|
|
128
|
+
);
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
`resolveCliModel()` resolves against all registered models (so `--api-key`-style first-time setup works before stored auth exists); `resolveModelScopeWithDiagnostics()` matches `--models`/`enabledModels` semantics and returns warnings instead of printing.
|
|
132
|
+
|
|
93
133
|
## Prompting & Queueing
|
|
94
134
|
|
|
95
135
|
```typescript
|
|
@@ -193,7 +233,8 @@ session.subscribe((event) => {
|
|
|
193
233
|
case "tool_execution_update":
|
|
194
234
|
case "tool_execution_end":
|
|
195
235
|
case "agent_start":
|
|
196
|
-
case "agent_end":
|
|
236
|
+
case "agent_end": // one low-level run; may be followed by retry/compaction/queued follow-ups
|
|
237
|
+
case "agent_settled": // fully settled — no automatic continuation left (Pi 0.80.4)
|
|
197
238
|
case "turn_start":
|
|
198
239
|
case "turn_end":
|
|
199
240
|
case "queue_update":
|
|
@@ -201,18 +242,30 @@ session.subscribe((event) => {
|
|
|
201
242
|
case "compaction_end":
|
|
202
243
|
case "auto_retry_start":
|
|
203
244
|
case "auto_retry_end":
|
|
245
|
+
case "summarization_retry_scheduled": // Pi 0.81.1 — compaction/branch-summary retries
|
|
246
|
+
case "summarization_retry_attempt_start":
|
|
247
|
+
case "summarization_retry_finished":
|
|
204
248
|
break;
|
|
205
249
|
}
|
|
206
250
|
});
|
|
207
251
|
```
|
|
208
252
|
|
|
209
|
-
`compaction_end` results and RPC `compact` responses include estimated post-compaction token counts (Pi 0.79.8) so clients can show the approximate context reduction.
|
|
253
|
+
`compaction_end` results and RPC `compact` responses include estimated post-compaction token counts (Pi 0.79.8) so clients can show the approximate context reduction. Since Pi 0.81.0, summaries persist their LLM `usage`, and session token/cost totals (footer, `/session`, RPC) include assistant messages, tool-reported usage, and summary generation.
|
|
254
|
+
|
|
255
|
+
**Streaming deltas (Pi 0.84.x, JSON/RPC wire only):** `message_update` records are delta-only — the cumulative `message` field and `assistantMessageEvent.partial` were removed to keep stream size linear. A top-level `usage` carries latest cumulative provider usage; assemble partial text from `contentIndex` + `delta` between `message_start` and `message_end`, which remains authoritative. In-process SDK subscribers still receive full events.
|
|
256
|
+
|
|
257
|
+
## Remote Sessions (experimental)
|
|
258
|
+
|
|
259
|
+
Pi 0.84.0 added transport-neutral remote-session client APIs: `@earendil-works/pi-client` (`PiClient`) with a CBOR protocol over Unix sockets, `@earendil-works/pi-protocol` for the wire contract, and `@earendil-works/pi-coding-agent/client` exporting a `RemoteSession` controller with transcript reducers. Sessions list durable `SessionMetadata`; runtime phase/model/lock state lives on acquired `SessionSnapshot` values. Expect these APIs to evolve while experimental.
|
|
210
260
|
|
|
211
261
|
## RPC Mode
|
|
212
262
|
|
|
213
263
|
`pi --mode rpc` speaks newline-delimited JSON over stdio. Additions since Pi 0.79:
|
|
214
264
|
|
|
215
|
-
- `
|
|
265
|
+
- `agent_settled` event (Pi 0.80.4) fires when a run is fully settled — no automatic retry, compaction retry, or queued continuation remains; `agent_end` now carries `willRetry`. `set_thinking_level` accepts `"max"` where the model supports it.
|
|
266
|
+
- `get_entries` / `get_tree` (Pi 0.80.3) read session entries and tree snapshots over RPC; `get_available_thinking_levels` (Pi 0.81.0) lists the current model's supported thinking levels.
|
|
267
|
+
- Direct RPC `bash` commands stream `bash_execution_update` chunks correlated by request `id` (Pi 0.82.0); include an `id` on the command to associate them.
|
|
268
|
+
- `compact` responses include summary `usage`; `get_tokens`/`get_status` totals cover assistant messages, tool-reported usage, and summaries (Pi 0.81.0).
|
|
216
269
|
- `@earendil-works/pi-coding-agent/rpc-entry` (Pi 0.80.3) launches Pi directly in RPC mode from an importing process.
|
|
217
270
|
- RPC extension UI request/response types are exported from the public API (Pi 0.79.0).
|
|
218
271
|
- Package asset path helpers are exported from the public API (Pi 0.79.0).
|
|
@@ -227,6 +280,20 @@ session.subscribe((event) => {
|
|
|
227
280
|
- Add custom skills or prompt templates without touching disk
|
|
228
281
|
- Share an event bus between the host app and loaded extensions
|
|
229
282
|
|
|
283
|
+
To name an inline factory in the startup Extensions list (instead of `<inline:1>`), wrap it in an `InlineExtension` (Pi 0.80.4):
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
import type { InlineExtension } from "@earendil-works/pi-coding-agent";
|
|
287
|
+
|
|
288
|
+
const myProvider: InlineExtension = {
|
|
289
|
+
name: "my-provider",
|
|
290
|
+
factory: (pi) => { /* ... */ },
|
|
291
|
+
};
|
|
292
|
+
const loader = new DefaultResourceLoader({ extensionFactories: [myProvider] });
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
Bare factory functions are still accepted.
|
|
296
|
+
|
|
230
297
|
## Standalone Custom Tools
|
|
231
298
|
|
|
232
299
|
Use `defineTool()` when you want a reusable custom tool definition outside `pi.registerTool(...)`:
|
|
@@ -17,6 +17,7 @@ Edit JSON directly or use `/settings` for common interactive options.
|
|
|
17
17
|
"defaultModel": "claude-sonnet-4-20250514",
|
|
18
18
|
"defaultThinkingLevel": "medium",
|
|
19
19
|
"hideThinkingBlock": false,
|
|
20
|
+
"showCacheMissNotices": false,
|
|
20
21
|
"thinkingBudgets": {
|
|
21
22
|
"minimal": 1024,
|
|
22
23
|
"low": 4096,
|
|
@@ -26,8 +27,9 @@ Edit JSON directly or use `/settings` for common interactive options.
|
|
|
26
27
|
}
|
|
27
28
|
```
|
|
28
29
|
|
|
29
|
-
- Thinking levels: `"off"`, `"minimal"`, `"low"`, `"medium"`, `"high"`, `"xhigh"`
|
|
30
|
+
- Thinking levels: `"off"`, `"minimal"`, `"low"`, `"medium"`, `"high"`, `"xhigh"`, `"max"` — `max` (Pi 0.80.6) is an opt-in level above `xhigh`, exposed only when the selected model supports it (some models, e.g. GPT-5.6, expose both). Custom themes can define `thinkingMax`; existing themes fall back to `thinkingXhigh`.
|
|
30
31
|
- `hideThinkingBlock` hides visible thinking output in the UI
|
|
32
|
+
- `showCacheMissNotices` (Pi 0.80.4) shows transcript notices for significant prompt-cache misses
|
|
31
33
|
|
|
32
34
|
## UI & Display
|
|
33
35
|
|
|
@@ -49,10 +51,28 @@ Edit JSON directly or use `/settings` for common interactive options.
|
|
|
49
51
|
- `doubleEscapeAction`: `"tree"`, `"fork"`, or `"none"`
|
|
50
52
|
- `treeFilterMode`: `"default"`, `"no-tools"`, `"user-only"`, `"labeled-only"`, or `"all"`
|
|
51
53
|
- In `/tree`, `Shift+T` toggles timestamps on entry labels
|
|
52
|
-
- `theme` also accepts `"light-name/dark-name"` (Pi 0.79.7) to switch themes automatically with the terminal color scheme; `/` is reserved in theme names for this. On first run Pi detects the terminal background and defaults to `dark` or `light`.
|
|
53
|
-
- `outputPad` (Pi 0.80.3, `0` or `1`) sets horizontal padding for user messages, assistant messages, and thinking blocks.
|
|
54
|
+
- `theme` also accepts `"light-name/dark-name"` (Pi 0.79.7) to switch themes automatically with the terminal color scheme; `/` is reserved in theme names for this. On first run Pi detects the terminal background and defaults to `dark` or `light`. `--use-theme <name[/name]>` (Pi 0.84.2) sets a per-run initial theme without changing saved settings.
|
|
55
|
+
- `outputPad` (Pi 0.80.3, `0` or `1`) sets horizontal padding for user messages, assistant messages, and thinking blocks; custom message renderers receive it as `options.outputPad` (Pi 0.82.1).
|
|
54
56
|
- `externalEditor` (Pi 0.80.3) sets the `Ctrl+G` external editor command and takes precedence over `$VISUAL`/`$EDITOR`.
|
|
55
57
|
|
|
58
|
+
## Fullscreen TUI Mode
|
|
59
|
+
|
|
60
|
+
Experimental since Pi 0.84.0:
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"tuiMode": "regular",
|
|
65
|
+
"fullscreenExitOutput": "transcript",
|
|
66
|
+
"fullscreenScrollbar": "auto"
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
- `tuiMode`: `"regular"` (default) or `"fullscreen"`; `/settings` switches at runtime, `--tui-mode` overrides per run
|
|
71
|
+
- `fullscreenExitOutput` (Pi 0.84.2): `"transcript"` prints the final transcript on exit; `"resume-hint"` restores the previous screen and prints only a resume hint
|
|
72
|
+
- `fullscreenScrollbar`: `"auto"` shows while scrolling, `"always"` reserves the rightmost column, `"hidden"`
|
|
73
|
+
- Fullscreen keeps editor/status/widgets/footer docked while the transcript scrolls independently; transcript search (`Ctrl+Shift+F`, Pi 0.84.2), page/half-page/line scrolling, and marked-message navigation are configurable via `tui.altScreen.*` keybindings
|
|
74
|
+
- Theme tokens `scrollbarThumb`, `searchMatchBg`, `searchMatchText` are optional additions with fallbacks (`selectedBg`, `selectedBg`, `text`)
|
|
75
|
+
|
|
56
76
|
## Compaction, Branch Summary, Retry
|
|
57
77
|
|
|
58
78
|
```json
|
|
@@ -125,6 +145,7 @@ Notes:
|
|
|
125
145
|
}
|
|
126
146
|
```
|
|
127
147
|
|
|
148
|
+
- `shellPath` supports a leading `~` for the home directory (Pi 0.80.6).
|
|
128
149
|
- `npmCommand` is argv-style and is used for npm lookup/install operations, including git-package installs. User-scoped npm packages install under `~/.pi/agent/npm/`; project-scoped npm packages install under `.pi/npm/`.
|
|
129
150
|
- `terminal.showTerminalProgress` (default `false` since Pi 0.70.0) toggles OSC 9;4 progress reporting in supporting terminals (iTerm2, WezTerm, Windows Terminal, Kitty).
|
|
130
151
|
- `terminal.imageWidthCells` (Pi 0.68.1) caps inline tool-output image width in terminal cells.
|
|
@@ -146,14 +167,19 @@ Notes:
|
|
|
146
167
|
{
|
|
147
168
|
"sessionDir": ".pi/sessions",
|
|
148
169
|
"enabledModels": ["claude-*", "gpt-4o", "gemini-2*"],
|
|
170
|
+
"defaultTools": ["bash", "read", "edit"],
|
|
149
171
|
"markdown": {
|
|
150
|
-
"codeBlockIndent": "
|
|
172
|
+
"codeBlockIndent": " ",
|
|
173
|
+
"mermaid": "streaming"
|
|
151
174
|
}
|
|
152
175
|
}
|
|
153
176
|
```
|
|
154
177
|
|
|
155
178
|
When multiple sources specify a session directory, `--session-dir` takes precedence over `sessionDir` in settings. Pi 0.65.0 removed the old `session_directory` extension/settings hook.
|
|
156
179
|
|
|
180
|
+
- `defaultTools` (Pi 0.84.2) picks the built-in tools enabled at startup (global or per project; project replaces global). An empty array starts with no built-in tools while keeping extension/SDK custom tools. `--tools` remains a strict allowlist for all tools, `--exclude-tools` filters the resulting list.
|
|
181
|
+
- `markdown.mermaid` (Pi 0.84.0): `"off"`, `"final"`, or `"streaming"` — themed Unicode rendering of supported Mermaid diagrams in interactive messages. Pi 0.84.0 also renders terminal-friendly Unicode for LaTeX expressions.
|
|
182
|
+
|
|
157
183
|
## Project Trust
|
|
158
184
|
|
|
159
185
|
Since Pi 0.79.0, project-local settings, resources, and packages (`.pi/` settings/extensions/skills/prompts/themes, project packages) only load after the project is trusted. `AGENTS.md` / `CLAUDE.md` context files load regardless of trust. Trust is a loading gate, not a sandbox.
|
|
@@ -236,7 +262,7 @@ pi [options] [@files...] [messages...]
|
|
|
236
262
|
--provider <name> e.g. anthropic, openai, google
|
|
237
263
|
--model <pattern> supports provider/id and optional :<thinking>
|
|
238
264
|
--api-key <key>
|
|
239
|
-
--thinking off|minimal|low|medium|high|xhigh
|
|
265
|
+
--thinking off|minimal|low|medium|high|xhigh|max
|
|
240
266
|
--models <patterns> Ctrl+P cycling allowlist
|
|
241
267
|
--list-models [search]
|
|
242
268
|
|
|
@@ -270,6 +296,8 @@ pi [options] [@files...] [messages...]
|
|
|
270
296
|
# prompts and misc
|
|
271
297
|
--system-prompt <text> replace default
|
|
272
298
|
--append-system-prompt <text> repeatable; appended with double newlines
|
|
299
|
+
--tui-mode regular|fullscreen experimental fullscreen TUI (Pi 0.84.0)
|
|
300
|
+
--use-theme <name[/name]> per-run initial theme, saved settings untouched (Pi 0.84.2)
|
|
273
301
|
--verbose
|
|
274
302
|
```
|
|
275
303
|
|
|
@@ -281,14 +309,20 @@ pi [options] [@files...] [messages...]
|
|
|
281
309
|
| `PI_CODING_AGENT_SESSION_DIR` | Override session storage; `--session-dir` still wins |
|
|
282
310
|
| `PI_PACKAGE_DIR` | Override package storage directory |
|
|
283
311
|
| `PI_SKIP_VERSION_CHECK` | Skip the `pi.dev` latest-version request at startup |
|
|
284
|
-
| `PI_OFFLINE` | Disable all startup network operations (update checks, telemetry) |
|
|
312
|
+
| `PI_OFFLINE` | Disable all startup network operations (update checks, telemetry, model catalog refresh) |
|
|
285
313
|
| `PI_TELEMETRY` | Override install/update telemetry and provider attribution headers (`1`/`0`); does not gate update checks |
|
|
286
314
|
| `PI_CACHE_RETENTION` | Set to `long` for extended prompt-cache retention where supported |
|
|
287
315
|
| `PI_OAUTH_CALLBACK_HOST` | Bind the OAuth callback server to a custom interface |
|
|
288
|
-
| `
|
|
316
|
+
| `PI_SHARE_VIEWER_URL` | Override the base URL used by `/share` |
|
|
317
|
+
| `PI_HARDWARE_CURSOR` | `1` shows the hardware cursor (see terminal-setup docs) |
|
|
318
|
+
| `PI_TUI_ESC_TIMEOUT` | Ms to wait after a lone ESC before treating it as Escape (default 100 over SSH, 10 otherwise; Pi 0.84.2) — raise it if Alt-key input is misread |
|
|
319
|
+
| `PI_EXPERIMENTAL` | `1` enables experimental features, e.g. strict JSON-schema sampling for built-in tools (Pi 0.84.2) |
|
|
320
|
+
| `AI_AGENT=pi` / `PI_CODING_AGENT=true` | Set automatically by CLI/RPC entry points so child processes can detect Pi (generic vs Pi-specific marker) |
|
|
289
321
|
| `VISUAL`, `EDITOR` | External editor for `Ctrl+G` (the `externalEditor` setting takes precedence) |
|
|
290
322
|
| Provider API key env vars | See `references/providers.md` |
|
|
291
323
|
|
|
324
|
+
Bash-tool commands additionally receive session state since Pi 0.82.0: `PI_SESSION_ID`, `PI_SESSION_FILE`, `PI_PROVIDER`, `PI_MODEL`, and `PI_REASONING_LEVEL` (resolved per command; not injected into user-entered `!`/`!!` commands). When asked which model is running, inspect these instead of inferring from the system prompt.
|
|
325
|
+
|
|
292
326
|
## Practical Notes
|
|
293
327
|
|
|
294
328
|
- Project settings are good for shared package/resource configuration.
|