@counterposition/skill-pi 0.80.9 → 0.87.1
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 +1 -1
- package/skills/pi/SKILL.md +7 -5
- package/skills/pi/references/extensions.md +52 -14
- package/skills/pi/references/packages.md +1 -0
- package/skills/pi/references/patterns.md +3 -2
- package/skills/pi/references/providers.md +27 -8
- package/skills/pi/references/sdk.md +21 -6
- package/skills/pi/references/settings.md +56 -9
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`, `
|
|
10
|
+
Pi is a minimal terminal coding harness. Default tools: `read`, `bash`, `edit`, `write`; `grep`, `find`, `ls`, and the Windows `powershell` tool (Pi 0.84.3) are opt-in via the `defaultTools` setting or `--tools`. 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.87.1.
|
|
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,10 +56,10 @@ 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`
|
|
60
|
-
- **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
|
+
- **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`
|
|
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`. Since Pi 0.87.0 `SessionManager` is canonical for model context: append-only `context_edit` entries omit or replace messages in future requests without rewriting history. → `references/extensions.md` and `references/sdk.md`
|
|
61
63
|
|
|
62
64
|
## How to Use This Skill
|
|
63
65
|
|
|
@@ -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
|
|
|
@@ -81,28 +81,37 @@ Useful session events:
|
|
|
81
81
|
- `resources_discover`
|
|
82
82
|
- `project_trust` — user/global and CLI extensions only, fired before project resources load; return `{ trusted: "yes" | "no" | "undecided" }` (optionally `remember: true` to persist). The first yes/no decision wins and suppresses the built-in trust prompt.
|
|
83
83
|
|
|
84
|
-
`session_before_compact` and `session_compact` carry `reason` and `willRetry` (Pi 0.79.10) so handlers can distinguish manual `/compact`, threshold auto-compaction, and overflow-retry compaction.
|
|
84
|
+
`session_before_compact` and `session_compact` carry `reason` and `willRetry` (Pi 0.79.10) so handlers can distinguish manual `/compact`, threshold auto-compaction, and overflow-retry compaction. `session_compact_failed` (Pi 0.84.3) reports failed or aborted compactions with `reason`, `aborted`, `willRetry`, `fromExtension`, and `errorMessage`.
|
|
85
85
|
|
|
86
86
|
`session_start` carries `event.reason` — `"startup" | "reload" | "new" | "resume" | "fork"` — and `event.previousSessionFile` for `"new"`/`"resume"`/`"fork"`. The old post-transition `session_switch` / `session_fork` events were removed; route all of those flows through `session_start`.
|
|
87
87
|
|
|
88
88
|
Useful agent events:
|
|
89
89
|
|
|
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
|
-
- `before_agent_start` —
|
|
91
|
+
- `before_agent_start` — `event.systemPrompt` is read-only; mutate `event.systemPromptOptions` (sections, selected tools, guidelines) so Pi appends a transcript delta that survives resume/branching and keeps the cached prefix (Pi 0.86.0). Returning `{ systemPrompt }` replaces the whole prompt for that run and is sent as the provider's leading system prompt
|
|
92
92
|
- `agent_start`
|
|
93
93
|
- `agent_end` — one low-level run; Pi may still auto-retry, auto-compact and retry, or continue with queued follow-ups
|
|
94
|
-
- `
|
|
94
|
+
- `agent_before_settle` (Pi 0.87.0) — the final actionable boundary before settlement (see below)
|
|
95
|
+
- `agent_settled` (Pi 0.80.4) — notification-only; fired when no retry/compaction/follow-up remains, for status integrations that need to know Pi will not continue automatically. Since Pi 0.87.0, runs requested from `agent_settled` handlers are deferred until every settled handler finishes (`ctx.isIdle()` stays true, no reentrant `agent_start`)
|
|
95
96
|
- `turn_start`
|
|
96
|
-
- `turn_end`
|
|
97
|
+
- `turn_end` — actionable since Pi 0.87.0; carries `turnIndex`, `message`, `toolResults`, and their session entry IDs
|
|
97
98
|
- `message_start`
|
|
98
99
|
- `message_update`
|
|
99
100
|
- `message_end` — return a replacement message to override usage/cost or rewrite the finalized assistant message
|
|
100
|
-
- `context`
|
|
101
|
+
- `context` — transforms conversation messages; since Pi 0.87.0 handlers no longer see prompt/tool system messages, and Pi restores that state afterward (filtering or slicing messages is safe)
|
|
102
|
+
- `context_with_system` (Pi 0.87.0) — runs after `context` on the full transcript including system messages and is sent verbatim; use only when a request-local transform must own the whole transcript, and keep a system message at index 0
|
|
101
103
|
- `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
|
|
102
104
|
- `before_provider_request`
|
|
103
105
|
- `after_provider_response` — inspect the provider HTTP status and headers before stream consumption
|
|
104
106
|
- `model_select`
|
|
105
107
|
- `thinking_level_select` — observe interactive thinking-level changes
|
|
108
|
+
- `ui_prompt_start` / `ui_prompt_end` (Pi 0.84.4) — distinguish active agent work from time spent waiting on blocking `ctx.ui` prompts (`kind`: `select`/`confirm`/`input`/`editor`/`custom`)
|
|
109
|
+
- `cache_warming_decision` (Pi 0.86.0) — override an idle prompt-cache refresh with `{ action: "warm" }` or `{ action: "stop" }`; the last handler returning an action wins
|
|
110
|
+
- `user_bash` — user `!`/`!!` commands. Fails closed since Pi 0.86.0: return `undefined` to pass to the next handler (then local execution), `{ operations }` or `{ result }` to handle it; a throwing handler or invalid result aborts the command
|
|
111
|
+
|
|
112
|
+
`turn_end` and `agent_before_settle` are actionable boundaries (Pi 0.87.0). Handlers receive the proposed `event.entries`, `event.continue`, a `context` preview, and the run `outcome`, and may return `{ entries: [...event.entries, draft], continue: true }` to persist `custom`, `custom_message`, `context_edit`, or `compaction` entries in order and ensure exactly one next provider request without disturbing steering/follow-up queues. Guard the condition — an unconditional `continue: true` loops.
|
|
113
|
+
|
|
114
|
+
`pi.on()` returns an unsubscribe function (Pi 0.86.0); handlers added or removed during a dispatch apply from the next dispatch.
|
|
106
115
|
|
|
107
116
|
Useful tool events:
|
|
108
117
|
|
|
@@ -112,7 +121,9 @@ Useful tool events:
|
|
|
112
121
|
- `tool_result`
|
|
113
122
|
- `tool_execution_end`
|
|
114
123
|
|
|
115
|
-
|
|
124
|
+
Since Pi 0.86.0, tool-call `arguments` and result `details` must be JSON-compatible values (no `Date`, `Map`, class instances, `undefined` array slots); use `details: undefined` when there is nothing structured to keep. Tools registered without a parameter schema are rejected at registration.
|
|
125
|
+
|
|
126
|
+
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.
|
|
116
127
|
|
|
117
128
|
`session_shutdown` events carry `event.reason` (`"quit" | "reload" | "new" | "resume" | "fork"`) and, where applicable, `event.targetSessionFile` so cleanup logic can distinguish teardown paths.
|
|
118
129
|
|
|
@@ -124,7 +135,8 @@ Tool results may include `terminate: true` to end the current tool batch without
|
|
|
124
135
|
- `ctx.mode` — `"tui" | "rpc" | "json" | "print"`; gate terminal-only features on `ctx.mode === "tui"`
|
|
125
136
|
- `ctx.cwd`
|
|
126
137
|
- `ctx.sessionManager` (read-only; `buildContextEntries()` returns active-branch entries with compaction applied, Pi 0.80.4)
|
|
127
|
-
- `ctx.modelRegistry` / `ctx.model` — `ctx.modelRegistry` is the synchronous extension-facing facade; its `refresh()` became `Promise<void>` in Pi 0.80.8 (await it before synchronous registry reads)
|
|
138
|
+
- `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
|
|
139
|
+
- `ctx.modelRegistry.stream()` / `streamSimple()` / `complete()` (Pi 0.86.0) — nested model calls through configured providers with request-time auth; prefer `streamSimple()` for provider-neutral calls, pass `ctx.signal`, and report the combined `usage` on the tool result
|
|
128
140
|
- `ctx.hasUI` — `true` in TUI and RPC modes
|
|
129
141
|
- `ctx.signal` — the active agent abort signal (or `undefined` when idle); pass it to `fetch`/model calls for abort-aware nested work
|
|
130
142
|
- `ctx.isIdle()` / `ctx.hasPendingMessages()`
|
|
@@ -180,12 +192,35 @@ Pi 0.80.7 lets an extension register many tools while keeping only a small initi
|
|
|
180
192
|
1. Register every tool with `pi.registerTool()` (all appear in `pi.getAllTools()`).
|
|
181
193
|
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
194
|
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.
|
|
195
|
+
4. Pi records the added tools on that tool result and exposes their definitions before the next model response. Since Pi 0.86.0 prompt and tool changes are transcript-backed system messages, so they survive resume and branch navigation.
|
|
184
196
|
|
|
185
|
-
Native deferred loading preserves the cached prompt prefix on Anthropic Sonnet/Opus/Fable ≥ 4.5 (not Haiku)
|
|
197
|
+
Native deferred loading preserves the cached prompt prefix on Anthropic Sonnet/Opus/Fable ≥ 4.5 (not Haiku), OpenAI `gpt-5.4`+, and Fireworks Messages models (Pi 0.86.0; name the loader `ToolSearch` or `tool_search`); 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
198
|
|
|
187
199
|
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
200
|
|
|
201
|
+
## Constrained Tool Sampling
|
|
202
|
+
|
|
203
|
+
`ToolDefinition.constrainedSampling` (Pi 0.82.0) lets a tool prefer or require provider-side output constraints:
|
|
204
|
+
|
|
205
|
+
- `{ type: "json_schema", strict: "prefer" | "require" }` — strict JSON-schema constrained decoding of the tool's own TypeBox parameters
|
|
206
|
+
- `{ type: "grammar", variants: { openai_lark?: string, openai_regex?: string } }` — OpenAI Lark/regex grammar encodings
|
|
207
|
+
- Set `false` to explicitly disable for that tool
|
|
208
|
+
|
|
209
|
+
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. Since Pi 0.86.0, strict-prefer JSON-schema sampling is on by default for the built-in `read`, `bash`, `powershell`, `edit`, and `write` tools (no `PI_EXPERIMENTAL` needed); re-register a definition with `constrainedSampling: false` to opt out.
|
|
210
|
+
|
|
211
|
+
## Display Transformers
|
|
212
|
+
|
|
213
|
+
`pi.registerMarkdownTransformer(transformer)` (Pi 0.84.0) chains display-only Markdown transforms over user text, assistant text, and thinking blocks:
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
pi.registerMarkdownTransformer((markdown, { messageType, isStreaming }) => {
|
|
217
|
+
if (isStreaming || messageType === "assistant-thinking") return markdown;
|
|
218
|
+
return markdown.replaceAll("-->", "→");
|
|
219
|
+
});
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
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.
|
|
223
|
+
|
|
189
224
|
## UI Methods
|
|
190
225
|
|
|
191
226
|
Check `ctx.hasUI` first. Non-interactive modes may not support UI.
|
|
@@ -304,7 +339,9 @@ pi.registerProvider("anthropic", { baseUrl: "https://proxy.example.com" });
|
|
|
304
339
|
pi.unregisterProvider("my-provider");
|
|
305
340
|
```
|
|
306
341
|
|
|
307
|
-
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`.
|
|
342
|
+
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.
|
|
343
|
+
|
|
344
|
+
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.
|
|
308
345
|
|
|
309
346
|
If you need auth for a specific model request, use:
|
|
310
347
|
|
|
@@ -312,14 +349,15 @@ If you need auth for a specific model request, use:
|
|
|
312
349
|
const auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);
|
|
313
350
|
```
|
|
314
351
|
|
|
315
|
-
(Still supported for extensions in Pi 0.80.8+; SDK code should use `ModelRuntime.getAuth()` — see `references/sdk.md`.)
|
|
352
|
+
(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.)
|
|
316
353
|
|
|
317
|
-
|
|
354
|
+
Custom `streamSimple` implementations receive a normalized `TranscriptContext` since Pi 0.86.0 — see `references/providers.md`. See `references/sdk.md` and `references/providers.md` for the full provider/model schema.
|
|
318
355
|
|
|
319
356
|
## Handy Patterns
|
|
320
357
|
|
|
321
358
|
- Permission gates via `tool_call`
|
|
322
|
-
- Prompt injection via `before_agent_start`
|
|
359
|
+
- Prompt injection via `before_agent_start` (`systemPromptOptions.sections`)
|
|
360
|
+
- Model-context pruning via `context`, or durable omission via `context_edit` entries from `turn_end`/`agent_before_settle`
|
|
323
361
|
- Branch or compaction customization via `session_before_tree` / `session_before_compact`
|
|
324
362
|
- Provider payload inspection via `before_provider_request`
|
|
325
363
|
- Stateful tools via `details` plus `session_start` reconstruction
|
|
@@ -101,6 +101,7 @@ If there is no `pi` manifest, Pi auto-discovers:
|
|
|
101
101
|
- `@earendil-works/pi-coding-agent`
|
|
102
102
|
- `@earendil-works/pi-tui`
|
|
103
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
|
|
104
105
|
- Other Pi packages must be bundled explicitly
|
|
105
106
|
- Git package installs run `npm install --omit=dev` — runtime needs go in `dependencies`, not `devDependencies`
|
|
106
107
|
|
|
@@ -213,7 +213,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
213
213
|
|
|
214
214
|
## Claude Rules Integration
|
|
215
215
|
|
|
216
|
-
Scan `.claude/rules/` and
|
|
216
|
+
Scan `.claude/rules/` and add a system-prompt section. `event.systemPrompt` is read-only; mutating `event.systemPromptOptions` lets Pi append a transcript delta that keeps the cached prefix (returning `{ systemPrompt }` instead replaces the whole prompt for that run):
|
|
217
217
|
|
|
218
218
|
```typescript
|
|
219
219
|
export default function (pi: ExtensionAPI) {
|
|
@@ -224,7 +224,8 @@ export default function (pi: ExtensionAPI) {
|
|
|
224
224
|
.filter(f => f.toString().endsWith(".md"));
|
|
225
225
|
if (files.length === 0) return;
|
|
226
226
|
const listing = files.map(f => `- .claude/rules/${f}`).join("\n");
|
|
227
|
-
event.
|
|
227
|
+
event.systemPromptOptions.sections.project_rules =
|
|
228
|
+
`Project rules (${files.length} files):\n${listing}\nUse the read tool to load relevant rules.`;
|
|
228
229
|
});
|
|
229
230
|
}
|
|
230
231
|
```
|
|
@@ -9,12 +9,14 @@ 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**
|
|
12
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**
|
|
13
|
-
- 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
|
|
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`. Since Pi 0.86.0 a public Radius catalog ships for immediate/offline selection (cached and live gateway catalogs overlay it); custom gateways use their own catalog
|
|
15
|
+
- Meta Muse (Pi 0.86.1) — `/login meta` with automatic Model API key refresh; `META_API_KEY` also works
|
|
14
16
|
|
|
15
|
-
`/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.
|
|
17
|
+
`/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.
|
|
16
18
|
|
|
17
|
-
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.
|
|
19
|
+
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`.
|
|
18
20
|
|
|
19
21
|
## API Key Providers
|
|
20
22
|
|
|
@@ -44,9 +46,13 @@ Since Pi 0.80.8, built-in catalogs are complemented by dynamic ones: `/model` re
|
|
|
44
46
|
| Hugging Face | `HF_TOKEN` | `huggingface` |
|
|
45
47
|
| Fireworks | `FIREWORKS_API_KEY` | `fireworks` |
|
|
46
48
|
| Together AI | `TOGETHER_API_KEY` | `together` |
|
|
49
|
+
| Baseten | `BASETEN_API_KEY` | `baseten` |
|
|
47
50
|
| Kimi For Coding | `KIMI_API_KEY` | `kimi-coding` |
|
|
51
|
+
| Meta (Muse) | `META_API_KEY` | `meta` |
|
|
48
52
|
| MiniMax | `MINIMAX_API_KEY` | `minimax` |
|
|
49
53
|
| MiniMax (China) | `MINIMAX_CN_API_KEY` | `minimax-cn` |
|
|
54
|
+
| Qwen Token Plan / Individual | `QWEN_TOKEN_PLAN_API_KEY` | `qwen-token-plan` / `qwen-token-plan-individual` (Pi 0.81.0 / 0.84.1) |
|
|
55
|
+
| Qwen Token Plan (China) | `QWEN_TOKEN_PLAN_CN_API_KEY` | `qwen-token-plan-cn` (Pi 0.81.0) |
|
|
50
56
|
| Xiaomi MiMo | `XIAOMI_API_KEY` | `xiaomi` |
|
|
51
57
|
| Xiaomi MiMo Token Plan (CN/AMS/SGP) | `XIAOMI_TOKEN_PLAN_{CN,AMS,SGP}_API_KEY` | `xiaomi-token-plan-{cn,ams,sgp}` |
|
|
52
58
|
|
|
@@ -188,19 +194,28 @@ Common `api` values:
|
|
|
188
194
|
|
|
189
195
|
### Model & Compatibility Knobs
|
|
190
196
|
|
|
197
|
+
- `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.
|
|
191
198
|
- `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.
|
|
192
199
|
- `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.
|
|
193
|
-
- `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`, `headers`, `compat`.
|
|
200
|
+
- `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`, `inputLimits`, `promptCache`.
|
|
201
|
+
- `inputLimits.images.resize` (Pi 0.87.0) sets per-model cache-safe image encoding — `maxWidth`, `maxHeight`, `maxBytes` (base64 payload), `jpegQuality`; defaults 2000×2000, 4.5 MiB, quality 80 — applied once to attachments, `read` images, and tool-result images (switching models does not re-encode history).
|
|
202
|
+
- `promptCache: { short?, long? }` (Pi 0.86.0) declares best-effort cache lifetimes in seconds per retention tier; models without a lifetime for the active tier are not eligible for cache warming (see `cacheWarming` in `references/settings.md`).
|
|
203
|
+
- `compat.allowedFallbackModels` (Pi 0.86.0) overrides or disables Anthropic server-side fallback models; `compat.supportsMidConvoEffort` (Pi 0.84.4) marks custom Anthropic Messages models that accept per-turn effort changes.
|
|
204
|
+
- OpenAI-compatible local servers: `vllmPriority` and `supportsMaxOutputTokens` (Pi 0.85.0) plus configurable thinking-token budget fields for vLLM, Qwen/SGLang, and llama.cpp (Pi 0.84.3).
|
|
194
205
|
- `openRouterRouting` is forwarded as-is in the OpenRouter `provider` field (fallbacks, ZDR, ignore lists, throughput/latency).
|
|
195
|
-
- `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`,
|
|
206
|
+
- `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`.
|
|
196
207
|
- **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`.
|
|
197
|
-
- `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 (see `references/extensions.md`).
|
|
198
|
-
- Advanced `compat` flags exist for proxy quirks (`cacheControlFormat
|
|
208
|
+
- `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`.
|
|
209
|
+
- 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.
|
|
199
210
|
|
|
200
211
|
### Context Overflow Recovery
|
|
201
212
|
|
|
202
213
|
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`.
|
|
203
214
|
|
|
215
|
+
### llama.cpp
|
|
216
|
+
|
|
217
|
+
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).
|
|
218
|
+
|
|
204
219
|
## Custom Providers via Extensions
|
|
205
220
|
|
|
206
221
|
Use extensions when you need custom streaming, custom headers, OAuth/device-flow logic, or want to override an existing provider's `baseUrl`/`headers`:
|
|
@@ -227,6 +242,10 @@ pi.registerProvider("my-provider", {
|
|
|
227
242
|
pi.registerProvider("anthropic", { baseUrl: "https://proxy.example.com" });
|
|
228
243
|
```
|
|
229
244
|
|
|
245
|
+
### Custom Streaming (Breaking, Pi 0.86.0)
|
|
246
|
+
|
|
247
|
+
Custom `streamSimple` implementations receive a normalized `TranscriptContext` instead of `Context`. System prompts and tool declarations live in transcript system messages: read them with `getCurrentSystemPrompt(context.messages)` and `getCurrentTools(context.messages)` (not `context.systemPrompt` / `context.tools`), and call `collapseSystemMessages(context)` if the backend cannot accept mid-conversation system messages. `ToolCall.arguments` and `ToolResultMessage.details` must be JSON-compatible. Pi 0.84.3 also renamed `GoogleThinkingLevel` to `GoogleApiThinkingLevel`.
|
|
248
|
+
|
|
230
249
|
## SDK / Extension Auth Lookup
|
|
231
250
|
|
|
232
251
|
If extension code needs auth for a specific model request, use `getApiKeyAndHeaders(model)` rather than the removed `getApiKey(model)`:
|
|
@@ -238,4 +257,4 @@ if (!auth.ok) throw new Error(auth.error);
|
|
|
238
257
|
const { apiKey, headers } = auth;
|
|
239
258
|
```
|
|
240
259
|
|
|
241
|
-
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`.
|
|
260
|
+
This matters for providers whose headers or auth values resolve dynamically on every request. For nested model calls, `ctx.modelRegistry.streamSimple(model, context, options)` (Pi 0.86.0) resolves auth itself. 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`.
|
|
@@ -71,7 +71,6 @@ const { session } = await createAgentSession({
|
|
|
71
71
|
customTools: [/* defineTool(...) entries */],
|
|
72
72
|
resourceLoader: new DefaultResourceLoader(),
|
|
73
73
|
sessionManager: SessionManager.inMemory(),
|
|
74
|
-
shouldStopAfterTurn: (state) => state.turnCount >= 5,
|
|
75
74
|
});
|
|
76
75
|
```
|
|
77
76
|
|
|
@@ -82,7 +81,7 @@ Notes:
|
|
|
82
81
|
- `customTools` accepts `ToolDefinition[]`. Build them with `defineTool({...})` for full TypeScript inference.
|
|
83
82
|
- The `create*Tool(cwd)` factories still exist for code that needs explicit `AgentTool` instances (e.g. when wiring tools into pi-agent-core directly), but they are no longer the value passed to `createAgentSession({ tools })`.
|
|
84
83
|
- `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).
|
|
85
|
-
-
|
|
84
|
+
- **Breaking (Pi 0.87.0):** pi-agent-core's `shouldStopAfterTurn` option was removed (it was never a `createAgentSession()` option). On a low-level `Agent`, set `finishTurn` instead: it runs after the assistant message and tool results are finalized but before `turn_end`, also for error/aborted responses. Return `{ action: "end" }` to stop, `{ action: "continue" }` to ensure one more request, or `undefined` for normal scheduling — guard hard exits first: `if (turn.message.stopReason === "error" || turn.message.stopReason === "aborted") return;`. Inside `createAgentSession()`, use an extension's actionable `turn_end` / `agent_before_settle` boundaries (see `references/extensions.md`).
|
|
86
85
|
|
|
87
86
|
## Models & Auth (`ModelRuntime`)
|
|
88
87
|
|
|
@@ -114,6 +113,8 @@ const inMemory = await ModelRuntime.create({ credentials: new InMemoryCredential
|
|
|
114
113
|
|
|
115
114
|
`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
115
|
|
|
116
|
+
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.
|
|
117
|
+
|
|
117
118
|
To match CLI model parsing, use the exported resolver helpers (Pi 0.80.4):
|
|
118
119
|
|
|
119
120
|
```typescript
|
|
@@ -213,10 +214,12 @@ Use `runtime.newSession()`, `runtime.switchSession()`, and `runtime.fork()` for
|
|
|
213
214
|
Useful state:
|
|
214
215
|
|
|
215
216
|
- `session.sessionFile` / `session.sessionId`
|
|
216
|
-
- `session.agent.state.messages`
|
|
217
|
+
- `session.agent.state.messages` — read-only view in practice: since Pi 0.87.0 `SessionManager` is canonical for provider context, so assigning it no longer changes future requests
|
|
217
218
|
- `session.model`
|
|
218
219
|
- `session.thinkingLevel`
|
|
219
220
|
|
|
221
|
+
To change model context from the SDK (Pi 0.87.0): restore external history with `SessionManager.inMemory(cwd, { id }, entries)` (Pi 0.85.0), navigate with `session.navigateTree()`, or append through `session.sessionManager` and call `session.refreshContext()`. `sessionManager.appendContextEdit(entryId, null)` omits one message from future provider context (a `{ content }` replacement rewrites it) without touching raw history, usage, or UI; `appendCompaction(summary, null, tokensBefore)` records a retain-none compaction. `SessionEntry` now includes `ContextEditEntry` (`type: "context_edit"`), so exhaustive entry switches must handle it.
|
|
222
|
+
|
|
220
223
|
## Events
|
|
221
224
|
|
|
222
225
|
```typescript
|
|
@@ -234,25 +237,37 @@ session.subscribe((event) => {
|
|
|
234
237
|
case "agent_end": // one low-level run; may be followed by retry/compaction/queued follow-ups
|
|
235
238
|
case "agent_settled": // fully settled — no automatic continuation left (Pi 0.80.4)
|
|
236
239
|
case "turn_start":
|
|
237
|
-
case "turn_end":
|
|
240
|
+
case "turn_end": // Pi 0.87.0: carries turnIndex, messageEntryId, toolResultEntryIds
|
|
238
241
|
case "queue_update":
|
|
239
242
|
case "compaction_start":
|
|
240
243
|
case "compaction_end":
|
|
241
244
|
case "auto_retry_start":
|
|
242
245
|
case "auto_retry_end":
|
|
246
|
+
case "summarization_retry_scheduled": // Pi 0.81.1 — compaction/branch-summary retries
|
|
247
|
+
case "summarization_retry_attempt_start":
|
|
248
|
+
case "summarization_retry_finished":
|
|
243
249
|
break;
|
|
244
250
|
}
|
|
245
251
|
});
|
|
246
252
|
```
|
|
247
253
|
|
|
248
|
-
`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.
|
|
254
|
+
`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.
|
|
255
|
+
|
|
256
|
+
**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.
|
|
257
|
+
|
|
258
|
+
## Remote Sessions (experimental)
|
|
259
|
+
|
|
260
|
+
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.
|
|
249
261
|
|
|
250
262
|
## RPC Mode
|
|
251
263
|
|
|
252
264
|
`pi --mode rpc` speaks newline-delimited JSON over stdio. Additions since Pi 0.79:
|
|
253
265
|
|
|
254
266
|
- `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.
|
|
255
|
-
- `
|
|
267
|
+
- `clear_queue` (Pi 0.84.4) returns and removes queued steering and follow-up messages; direct RPC `steer`/`follow_up` commands pass through extension `input` handlers since Pi 0.86.0.
|
|
268
|
+
- `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.
|
|
269
|
+
- 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.
|
|
270
|
+
- `compact` responses include summary `usage`; `get_tokens`/`get_status` totals cover assistant messages, tool-reported usage, and summaries (Pi 0.81.0).
|
|
256
271
|
- `@earendil-works/pi-coding-agent/rpc-entry` (Pi 0.80.3) launches Pi directly in RPC mode from an importing process.
|
|
257
272
|
- RPC extension UI request/response types are exported from the public API (Pi 0.79.0).
|
|
258
273
|
- Package asset path helpers are exported from the public API (Pi 0.79.0).
|
|
@@ -18,6 +18,7 @@ Edit JSON directly or use `/settings` for common interactive options.
|
|
|
18
18
|
"defaultThinkingLevel": "medium",
|
|
19
19
|
"hideThinkingBlock": false,
|
|
20
20
|
"showCacheMissNotices": false,
|
|
21
|
+
"cacheWarming": "streaming",
|
|
21
22
|
"thinkingBudgets": {
|
|
22
23
|
"minimal": 1024,
|
|
23
24
|
"low": 4096,
|
|
@@ -29,7 +30,9 @@ Edit JSON directly or use `/settings` for common interactive options.
|
|
|
29
30
|
|
|
30
31
|
- 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`.
|
|
31
32
|
- `hideThinkingBlock` hides visible thinking output in the UI
|
|
32
|
-
- `showCacheMissNotices` (Pi 0.80.4) shows transcript notices for significant prompt-cache misses
|
|
33
|
+
- `showCacheMissNotices` (Pi 0.80.4) shows transcript notices for significant prompt-cache misses; newer releases also report successful cache warming, compaction/branch-summary usage, and provider recovery
|
|
34
|
+
- `cacheWarming` (Pi 0.86.0, global only): `"off"`, `"streaming"` (default — keep eligible caches alive during long tool runs), or `"idle"` (also between runs). Pi warms only when the model declares a `promptCache` lifetime and it estimates at least $0.05 in avoided cache-miss cost; refresh usage counts toward session totals but never enters model context. `/session` shows the next decision; extensions can override via `cache_warming_decision`
|
|
35
|
+
- `/model` and `/thinking` (Pi 0.84.3) selections are session-scoped; press `Ctrl+S` in the selector to save as the global default
|
|
33
36
|
|
|
34
37
|
## UI & Display
|
|
35
38
|
|
|
@@ -51,10 +54,30 @@ Edit JSON directly or use `/settings` for common interactive options.
|
|
|
51
54
|
- `doubleEscapeAction`: `"tree"`, `"fork"`, or `"none"`
|
|
52
55
|
- `treeFilterMode`: `"default"`, `"no-tools"`, `"user-only"`, `"labeled-only"`, or `"all"`
|
|
53
56
|
- In `/tree`, `Shift+T` toggles timestamps on entry labels
|
|
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`.
|
|
55
|
-
- `outputPad` (Pi 0.80.3, `0` or `1`) sets horizontal padding for user messages, assistant messages, and thinking blocks.
|
|
57
|
+
- `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.
|
|
58
|
+
- `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).
|
|
56
59
|
- `externalEditor` (Pi 0.80.3) sets the `Ctrl+G` external editor command and takes precedence over `$VISUAL`/`$EDITOR`.
|
|
57
60
|
|
|
61
|
+
## Fullscreen TUI Mode
|
|
62
|
+
|
|
63
|
+
Experimental since Pi 0.84.0:
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"tuiMode": "regular",
|
|
68
|
+
"fullscreenExitOutput": "transcript",
|
|
69
|
+
"fullscreenScrollbar": "auto",
|
|
70
|
+
"fullscreenCopyOnSelect": true
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
- `tuiMode`: `"regular"` (default) or `"fullscreen"`; `/settings` switches at runtime, `--tui-mode` overrides per run
|
|
75
|
+
- `fullscreenExitOutput` (Pi 0.84.2): `"transcript"` prints the final transcript on exit; `"resume-hint"` restores the previous screen and prints only a resume hint
|
|
76
|
+
- `fullscreenScrollbar`: `"auto"` shows while scrolling, `"always"` reserves the rightmost column, `"hidden"`
|
|
77
|
+
- `fullscreenCopyOnSelect` (Pi 0.84.4, default `true`): when `false`, `Ctrl+X` copies the active selection (falling back to the last assistant message)
|
|
78
|
+
- 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
|
|
79
|
+
- Theme tokens `scrollbarThumb`, `searchMatchBg`, `searchMatchText` are optional additions with fallbacks (`selectedBg`, `selectedBg`, `text`)
|
|
80
|
+
|
|
58
81
|
## Compaction, Branch Summary, Retry
|
|
59
82
|
|
|
60
83
|
```json
|
|
@@ -62,7 +85,10 @@ Edit JSON directly or use `/settings` for common interactive options.
|
|
|
62
85
|
"compaction": {
|
|
63
86
|
"enabled": true,
|
|
64
87
|
"reserveTokens": 16384,
|
|
65
|
-
"keepRecentTokens": 20000
|
|
88
|
+
"keepRecentTokens": 20000,
|
|
89
|
+
"modelOverrides": {
|
|
90
|
+
"anthropic/claude-opus-5-5": { "reserveTokens": 32768 }
|
|
91
|
+
}
|
|
66
92
|
},
|
|
67
93
|
"branchSummary": {
|
|
68
94
|
"reserveTokens": 16384,
|
|
@@ -72,6 +98,7 @@ Edit JSON directly or use `/settings` for common interactive options.
|
|
|
72
98
|
"enabled": true,
|
|
73
99
|
"maxRetries": 3,
|
|
74
100
|
"baseDelayMs": 2000,
|
|
101
|
+
"maxAgentDelayMs": 60000,
|
|
75
102
|
"provider": {
|
|
76
103
|
"timeoutMs": 3600000,
|
|
77
104
|
"maxRetries": 0,
|
|
@@ -83,7 +110,8 @@ Edit JSON directly or use `/settings` for common interactive options.
|
|
|
83
110
|
|
|
84
111
|
Notes:
|
|
85
112
|
|
|
86
|
-
- `
|
|
113
|
+
- `compaction.modelOverrides` (Pi 0.86.0) sets per-model `reserveTokens`/`keepRecentTokens` keyed by exact `provider/modelId`; each value falls back to the ordinary compaction setting, then the default.
|
|
114
|
+
- `retry.maxRetries` (default `3`) and `retry.baseDelayMs` (default `2000`) govern Pi's own agent-level retry with exponential backoff, capped per attempt by `retry.maxAgentDelayMs` (default `60000`, Pi 0.86.0).
|
|
87
115
|
- `retry.provider.*` controls the underlying provider SDK's request timeout and retry/backoff — useful for slow local LLMs and flaky proxies. `retry.provider.timeoutMs` sets the SDK request timeout; `retry.provider.maxRetries` defaults to `0` (keep it there unless you need SDK-level retries, since raising it can let provider retries swallow usage-limit errors before Pi handles them).
|
|
88
116
|
- `retry.provider.maxRetryDelayMs` (default `60000`) caps how long a server-requested retry delay can be before the request fails immediately with an informative error; set to `0` to disable the cap. The old top-level `retry.maxDelayMs` was renamed to this and is auto-migrated.
|
|
89
117
|
- `branchSummary.skipPrompt` skips the confirmation step when navigating with `/tree`.
|
|
@@ -115,7 +143,10 @@ Notes:
|
|
|
115
143
|
"showImages": true,
|
|
116
144
|
"clearOnShrink": false,
|
|
117
145
|
"showTerminalProgress": false,
|
|
118
|
-
"imageWidthCells": 60
|
|
146
|
+
"imageWidthCells": 60,
|
|
147
|
+
"hyperlinks": "auto",
|
|
148
|
+
"images": "auto",
|
|
149
|
+
"trueColor": "auto"
|
|
119
150
|
},
|
|
120
151
|
"images": {
|
|
121
152
|
"autoResize": true,
|
|
@@ -131,6 +162,7 @@ Notes:
|
|
|
131
162
|
- `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/`.
|
|
132
163
|
- `terminal.showTerminalProgress` (default `false` since Pi 0.70.0) toggles OSC 9;4 progress reporting in supporting terminals (iTerm2, WezTerm, Windows Terminal, Kitty).
|
|
133
164
|
- `terminal.imageWidthCells` (Pi 0.68.1) caps inline tool-output image width in terminal cells.
|
|
165
|
+
- `terminal.hyperlinks` / `terminal.images` (`"kitty" | "iterm2" | "auto" | false`) / `terminal.trueColor` (Pi 0.84.4) override capability detection (settings win over `PI_HYPERLINKS`, `PI_IMAGE_PROTOCOL`, `PI_TRUE_COLOR`). Only force what the full terminal path (tmux, SSH) supports.
|
|
134
166
|
|
|
135
167
|
## Warnings & Telemetry
|
|
136
168
|
|
|
@@ -149,14 +181,19 @@ Notes:
|
|
|
149
181
|
{
|
|
150
182
|
"sessionDir": ".pi/sessions",
|
|
151
183
|
"enabledModels": ["claude-*", "gpt-4o", "gemini-2*"],
|
|
184
|
+
"defaultTools": ["bash", "read", "edit"],
|
|
152
185
|
"markdown": {
|
|
153
|
-
"codeBlockIndent": "
|
|
186
|
+
"codeBlockIndent": " ",
|
|
187
|
+
"mermaid": "streaming"
|
|
154
188
|
}
|
|
155
189
|
}
|
|
156
190
|
```
|
|
157
191
|
|
|
158
192
|
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.
|
|
159
193
|
|
|
194
|
+
- `defaultTools` (Pi 0.84.2) picks the built-in tools enabled at startup (default `read`, `bash`, `edit`, `write`; also available: `grep`, `find`, `ls`, and `powershell` on Windows since Pi 0.84.3) (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.
|
|
195
|
+
- `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.
|
|
196
|
+
|
|
160
197
|
## Project Trust
|
|
161
198
|
|
|
162
199
|
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.
|
|
@@ -273,9 +310,13 @@ pi [options] [@files...] [messages...]
|
|
|
273
310
|
# prompts and misc
|
|
274
311
|
--system-prompt <text> replace default
|
|
275
312
|
--append-system-prompt <text> repeatable; appended with double newlines
|
|
313
|
+
--tui-mode regular|fullscreen experimental fullscreen TUI (Pi 0.84.0)
|
|
314
|
+
--use-theme <name[/name]> per-run initial theme, saved settings untouched (Pi 0.84.2)
|
|
276
315
|
--verbose
|
|
277
316
|
```
|
|
278
317
|
|
|
318
|
+
Use `/bug [description]` (Pi 0.86.0) to report a problem with redacted diagnostics, optionally the transcript or a model-written summary; it uploads to Radius or exports a ZIP. Crashes are recorded in `~/.pi/agent/crashes.json` and attached to the next report.
|
|
319
|
+
|
|
279
320
|
## Environment Variables
|
|
280
321
|
|
|
281
322
|
| Variable | Effect |
|
|
@@ -284,14 +325,20 @@ pi [options] [@files...] [messages...]
|
|
|
284
325
|
| `PI_CODING_AGENT_SESSION_DIR` | Override session storage; `--session-dir` still wins |
|
|
285
326
|
| `PI_PACKAGE_DIR` | Override package storage directory |
|
|
286
327
|
| `PI_SKIP_VERSION_CHECK` | Skip the `pi.dev` latest-version request at startup |
|
|
287
|
-
| `PI_OFFLINE` | Disable all startup network operations (update checks, telemetry) |
|
|
328
|
+
| `PI_OFFLINE` | Disable all startup network operations (update checks, telemetry, model catalog refresh) |
|
|
288
329
|
| `PI_TELEMETRY` | Override install/update telemetry and provider attribution headers (`1`/`0`); does not gate update checks |
|
|
289
330
|
| `PI_CACHE_RETENTION` | Set to `long` for extended prompt-cache retention where supported |
|
|
290
331
|
| `PI_OAUTH_CALLBACK_HOST` | Bind the OAuth callback server to a custom interface |
|
|
291
|
-
| `
|
|
332
|
+
| `PI_SHARE_VIEWER_URL` | Override the base URL used by `/share` |
|
|
333
|
+
| `PI_HARDWARE_CURSOR` | `1` shows the hardware cursor (see terminal-setup docs) |
|
|
334
|
+
| `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 |
|
|
335
|
+
| `PI_EXPERIMENTAL` | `1` enables experimental features (strict JSON-schema sampling for built-in tools no longer needs it since Pi 0.86.0) |
|
|
336
|
+
| `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) |
|
|
292
337
|
| `VISUAL`, `EDITOR` | External editor for `Ctrl+G` (the `externalEditor` setting takes precedence) |
|
|
293
338
|
| Provider API key env vars | See `references/providers.md` |
|
|
294
339
|
|
|
340
|
+
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.
|
|
341
|
+
|
|
295
342
|
## Practical Notes
|
|
296
343
|
|
|
297
344
|
- Project settings are good for shared package/resource configuration.
|