# pi client (cosmic) [pi](https://pi.dev) coding agent 1.4.0 on the workstation, pointed at Strata. Config lives in `~/.pi/agent/`; the copies in [`pi/`](../pi) have the API key replaced with ``. ## models.json [`pi/models.json`](../pi/models.json) defines provider `strata`: - `baseUrl: http://192.168.1.67:8080/v1`, `api: openai-completions` - `contextWindow: 131072` (matches Strata's `--max-context`) - `maxTokens: 32768` - `reasoning: true`, `input: text + image` - `compat`: - `supportsDeveloperRole: false`, `supportsReasoningEffort: false` - `thinkingFormat: "chat-template"` with `chatTemplateKwargs` `{ enable_thinking: {$var: thinking.enabled}, reasoning_effort: {$var: thinking.effort, omitWhenOff: true} }`. **Without this, pi's thinking level never reaches Strata** and every request thinks at full effort. ## settings.json [`pi/settings.json`](../pi/settings.json): default provider/model, thinking `medium`, and ```json "compaction": { "reserveTokens": 32768, "keepRecentTokens": 20000 } ``` Pi compacts once context exceeds `contextWindow - reserveTokens`, so this starts at ~98K. Keep `reserveTokens` ≥ `maxTokens`. ## Thinking levels | pi level | What Strata does | |---|---| | off | No thinking | | low | System note asking for brief thinking | | minimal / medium | System note: think as much as the task needs | | high / xhigh / max | Unrestricted thinking | Use medium day to day, high for hard debugging or planning. Compaction reuses the session's level. ## How compaction works (and why it failed) Pi sends one summary request containing everything except the last `keepRecentTokens`. Its output is capped at the model's `maxTokens` and it uses the current thinking level. If the reply ends with `stopReason: "length"`, pi refuses to save the partial summary ("generation hit the token cap and the summary is incomplete") and tries again on the next turn. See the [2026-10-26 changelog entry](changelog.md#2026-10-26-pi-auto-compaction-loop). If it ever happens again: `/thinking off`, `/compact`, then set thinking back. ### Summary snowball and the budget-compaction extension The default update prompt tells the model to "PRESERVE all existing information from the previous summary", so every compaction copies the old summary forward and adds to it. On the `husky-walk` session it grew 9.9K → 86.6K chars over 13 compactions (~22K tokens), and rewriting that plus ~11K of thinking no longer fit in 32K: the loop came back. The text was legitimate (1,458 of 1,573 lines unique), mostly an ever-growing `### Done` list. [`pi/extensions/budget-compaction.ts`](../pi/extensions/budget-compaction.ts) hooks `session_before_compact` and replaces the summary step: 1. If the previous summary is over the limit, condense it on its own first (a short call). 2. Merge it with the new messages into one fresh checkpoint, with a word allowance per section, **2,500 words** in total (`PI_COMPACT_WORDS` overrides). 3. Count the words; if still more than 25% over, run up to two condense passes on the result. All calls run with thinking off, whatever the session's level. If a call fails, pi's default compaction runs instead. The read-only file list is capped at 25 entries (modified files are always listed), and `/compact ` still adds a focus. An instruction alone was not enough: the first version only asked for 2,500 words, and on a copy of `husky-walk` the model produced 10,401 words (21K tokens, 129 s), copying the old summary forward. The enforced version on the same copy: | | Prompt-only version | Enforced version | |---|---:|---:| | Time | 129 s | 44.5 s | | Output tokens | 21,158 | 4,719 (two calls) | | Checkpoint | 10,401 words | 1,183 words | | Context after compaction | 39.5K tokens | 23.1K tokens | The previous 11,542-word summary condensed to 1,162 words and the checkpoint kept the current state, contracts, decisions and next steps. 0 reasoning tokens in every call. Install: copy it to `~/.pi/agent/extensions/` and restart pi (extensions load at startup). Testing without touching real sessions: copy the session `.jsonl` and a pi config into a scratch dir, then run `PI_CODING_AGENT_DIR=/agent pi --mode rpc --session ` and send `{"id":"c1","type":"compact"}` on stdin. Project-level `.pi/settings.json` needs project trust, so use the agent-dir override instead. `maxTokens` costs no VRAM. Strata sizes the KV cache from `--max-context` / `--kv-resident` at engine start; `max_tokens` is only a per-request stop, and Strata shortens it to the room left in the window.