## [0.96.5] - 2026-08-24

### Added

- Added root-only version-aware durable learning state that recognizes installed runtime and memory-policy transitions, attaches one exact claim to the existing provider reflection turn, and automatically revalidates durable intent, corrections, reusable procedures, preferences, and project knowledge through the existing evidence-gated memory and skill tools.
- Added bounded, lock-serialized transition history with strict retry/continuation settlement, child and worker zero-footprint behavior, byte-preserving unsupported-state fallback, and canonical OKF routing while workflow context keeps references instead of duplicate truth.

### Fixed

- Stopped repeated tool-call cycles after three identical observable-result periods without preempting changing results before the existing configurable coarse fuse, and gave active goals state-changing recovery guidance instead of re-polling unchanged status.
- Kept goal satisfaction and increment aligned with final acceptance by requiring trusted evidence before either transition, repairing legacy satisfied-but-unproven requirements before completion, surfacing unproven requirement IDs, and returning generated evidence IDs with their trust status.

## [0.96.4] - 2026-08-23

### Fixed

- Restored OpenRouter Ox Alpha tool use by defaulting it to Pi's text tool protocol and omitting the unsupported `reasoning.effort: none` default.

## [0.96.3] - 2026-08-23

## [0.96.2] - 2026-08-23

### Fixed

- Made foreground and delegated-worker retries honor provider wait boundaries and fail closed when a requested wait exceeds the configured maximum.
- Kept signed commentary and orchestration payloads out of the visible assistant transcript while retaining normal assistant text.
- Let accepted xAI streams use the HTTP-bounded quiet-stream allowance before first generated progress instead of the generic short first-token timeout.

## [0.96.1] - 2026-08-22

### Changed

- Kept durable goals active across bounded runaway guards, stalled turns, repeated requirement blockers, and timed-out workers; each condition now injects recovery guidance and requires a different autonomous approach instead of silently waiting for manual continuation.
- Automatically reopened goals blocked by bounded runaway/provider-turn guards when restoring a session while preserving explicit owner pauses, cancellations, terminal failures, budgets, and approval boundaries.

### Fixed

- Prevented internal goal-continuation and recovery notices from impersonating new owner turns and repeatedly re-admitting an unchanged failed tool operation; real successful operations and new user turns still advance recovery.
- Honored the resource selector's exact negative extension filter when deciding whether to load default-on TPS.
- Made background completion summaries report succeeded, verification-needed, failed, and canceled counts as disjoint outcomes instead of describing failed work as both finished and failed.
- Kept every provider default resolvable after catalog refreshes and moved the retired Cerebras default to `gpt-oss-120b`.

## [0.96.0] - 2026-08-22

### Added

- Added one canonical five-phase work lifecycle—Survey, Contract, Plan/Route, Execute, Prove/Deliver—wired through the existing goal, task, delegation, evidence, and approval owners, with project-relative POC/MVP versus complete-feature delivery contracts.
- Added a scrollable Ctrl+Q work inspector for full goal, requirement, evidence, task-plan, worker, and background-tool details.
- Bundled the passive TPS footer meter as a default-on extension for fresh installations.

### Changed

- Made solo/team routing, independent review, and verification depth adaptive to delivery risk and evidence instead of treating long work as an automatic team trigger.
- Classified one plain local `git commit` as a reversible scoped checkpoint after green verification while keeping composed commands, history rewrites, push/tag/release/publish, and destructive operations approval-gated.

### Fixed

- Preserved active-branch ancestry when excluding lifecycle-ledger records from compaction input, preventing context accounting from collapsing to only the newest tool result.
- Reconciled already-notified terminal tmux jobs into freshly hydrated host lane state so absent workers cannot remain displayed as active.
- Kept the five-phase lifecycle contract within chat and minimal model prompt budgets across host checkout-path formats while retaining the full contract for larger profiles.

## [0.95.0] - 2026-08-22

### Breaking Changes

- Removed tmux standing dispatch grants and the public `workerDelegation.writePaths` setting. Workers now receive one immutable launch profile; an omitted path inherits machine-wide project access and an explicit path narrows the worker.
- Native delegated workers are leaf agents. Fresh nested delegation is rejected, and worker profiles no longer expose recursive-agent limits.
- Replaced delegated `readPaths`/`writePaths` and task-profile resource/budget overrides with focused model, thinking-level, path, and tool controls that can only inherit or narrow the foreground authority.
- Renamed delegated query-only memory retrieval from `memory` to `memory_read`; the raw root `memory` tool is no longer valid in worker profiles.

### Added

- Added lightweight worker profile controls for model, thinking level, path, and tools, with exact model-pin conflict handling and inherited foreground defaults.
- Added fresh, worker-safe adapters for bounded artifact retrieval, toolkit scripts, skill search/read, and skill audits without sharing foreground extension/session instances.
- Added a root-only, default-on reflection cue consumed inside the orchestrator's next ordinary provider turn, with audited automatic application for safe additive memory and skill writes.

### Changed

- Collapsed the remaining worker, background-tool, worktree, and process-supervision messages into one-line TUI activity summaries, with one in-place thinking/working lane and compact verification identifiers.
- Made native and tmux workers autonomous by default: routine dispatch needs no grant, Pi workers inherit compatible parent tools and resources, and managed tmux panes receive their initial task only after capture is armed.
- Made the foreground cost guard an explicit opt-in; legacy positive thresholds remain dormant until enabled.
- Goal completion now refuses every open task step, active goal-owned worker or tool task, cited unfinished tool task, and active pipeline.
- Moved automatic reflection into the current root session with no isolated/background model request; automatic background Auto Learn launches are disabled while explicit `/auto-learn run` remains available.

### Fixed

- Prevented duplicate or stale background terminal wakes by rechecking durable observation and goal ownership at the provider boundary.
- Prevented OKF organization from matching or deleting a substring of a hot-memory fact; exact removal now occurs under the managed memory lock.
- Isolated default AgentSession test storage from the real user agent directory.
- Made tmux deadline handling terminate the owned pane, while dismiss only detaches supervision.
- Rejected every fresh-only model, thinking, path, tool, profile, or fork override when reusing a persistent worker instead of silently ignoring it.
- Blocked direct `run_process` argv access to worker-private auth, session, settings, and memory paths while preserving ordinary machine-wide project access.
- Bounded and made cancellable worker skill audits, and rejected explicit profiles whose requested worker adapter is not active instead of silently narrowing them.
- Moved provider tool-guideline budget diagnostics out of the chat renderer and into `/context` diagnostics.
- Dismissed pending current-session reflection cues and refreshed the root prompt synchronously when reflection is disabled, preventing stale learning work from resurfacing after re-enable.
- Bounded reflection response scanning, accepted writes, memory and skill fields, automatic overlap audits, and `skillify` draft bodies; truncated automatic promotion audits now fail closed.
- Omitted raw root memory tools and prompt snapshots from child sessions; managed workers receive memory only through the bounded, source-labeled query broker.
- Corrected platform-aware machine-root resolution and case-insensitive drive deduplication so Windows multi-drive workers retain machine-wide authority without global reservation serialization.
- Routed bundled tmux extension dependencies through the embedded package runtime so compiled Bun releases load the manager without missing `dist/core` modules.

## [0.94.1] - 2026-08-21

### Added

- Added orchestrator-owned project OKF organization with proactive local recall, bounded read-only worker queries, and loss-safe audited rollback.

### Changed

- Unified foreground tools, background tasks, and delegated workers under compact `Performed N actions` activity counters with details available through Ctrl+T.

### Fixed

- Suppressed already-observed background completions and late duplicate parent wakes while retaining durable terminal handoffs for explicit verification.
- Kept reflection and durable memory lifecycle writes exclusive to the main orchestrator, including managed-worker and Auto Learn subprocesses.
- Isolated project OKF records and rejected unsafe paths, symlink traversal, oversized fields, conflicting overwrites, and stale rollback deletion.

## [0.94.0] - 2026-08-21

### Breaking Changes

- Removed extension `toolGroup` and `toolGroupSummary` rendering hooks; every model tool invocation now follows the native action-transcript contract.

### Changed

- Replaced Bash, file, skill, goal, task, worker, and extension-specific collapsed cards with one append-only `Performing N actions` / `Performed N actions` row. Main-chat actions stay collapsed; their only detailed projection opens through Ctrl+T.

### Fixed

- Kept repeated calls as distinct transcript actions instead of relocating presentation instances, and moved operational session warnings from permanent chat lines to the transient activity lane.

## [0.93.19] - 2026-08-21

### Changed

- Collapsed every agent Bash invocation into bounded command-counter rows, moved expanded transcript scrollback to Ctrl+T, and replaced hidden reasoning lines with one in-place Thinking/Working status; direct user shell output remains visible.

### Added

- Added fingerprint-only provider request snapshots, atomic foreground tool reservations, canonical result terminals, compaction lifecycle brackets, and deterministic interrupted-session repair.

### Fixed

- Fixed auto-compaction preflight to anchor ongoing same-model sessions to provider-reported usage and account only request-envelope changes, preventing fixed character heuristics from compacting code/tool-heavy histories prematurely.
- Fixed provider-usage admission reintroducing context-GC-removed history, and made post-compaction usage staleness follow durable branch order instead of message timestamps.
- Fixed memory-provider lifecycle hooks so hung providers time out, are abandoned across reload generations until their late operation settles, and emit bounded source-labelled diagnostics.
- Fixed budget-limited goals remaining projected as active, malformed requirement dependencies crossing storage boundaries, worker model pins being hidden from persistent-agent listings, and public subscriber failures escaping the session event boundary.

## [0.93.18] - 2026-08-21

### Fixed

- Matched Grok subscription compaction to the installed CLI lane: reuse the live structured session prefix, tool catalog, cache affinity, priority-processing wrapper, 80% trigger, original-request-plus-checkpoint replacement, and a durable full-transcript pointer while leaving API-key xAI behavior unchanged.

## [0.93.17] - 2026-08-21

### Fixed

- Learned a bounded next-attempt first-progress timeout from censored stream stalls, scoped it to comparable prompt sizes, and cleared it after a successful stream instead of repeating identical Grok timeout windows.
- Allowed credential-safe source brace globs and explicit source filenames even when one path is stale, while retaining directory and dotenv protections.
- Bounded retained failed jscpd evidence by age, count, and total bytes while protecting concurrent scans and explicit report directories.

## [0.93.16] - 2026-08-20

### Fixed

- Recovered repeated xAI retained-history token-generation failures after one unchanged retry by performing one bounded provider-recovery compaction and continuing the same foreground run.
- Prevented print/RPC JSON streams from repeating the complete accumulated assistant prefix on every delta, which could turn one long response into gigabytes of output; streaming records now stay below 50 KiB and the terminal event remains authoritative.

## [0.93.15] - 2026-08-20

## [0.93.14] - 2026-08-20

### Fixed

- Adapted the first model-progress watchdog to measured prefill throughput so zero-output Grok subscription turns fail promptly without constraining genuine long reasoning.

## [0.93.13] - 2026-08-20

### Added

- Added autonomous machine credential discovery and encrypted Bitwarden Secrets Manager profile storage.

### Fixed

- Preserved failed background child results as operation outcomes and made waits event-driven without losing terminal parent wakeups.
- Kept worker terminal reports inline through 50 KiB, then persisted the complete output and returned its verified file pointer.
- Allowed agents to start durable goals autonomously while stripping unapproved token budgets and generating stable record IDs.
- Blocked credential-file access before tool execution and serialized concurrent Secrets Manager profile mutations.

## [0.93.12] - 2026-08-20

### Changed

- GitHub release publication now requires isolated npm/Node and Bun binary smoke tests covering model discovery, streamed prompts, and interactive TTY conversations.

## [0.93.11] - 2026-08-20

### Added

- Added bounded model-blind credential discovery for the current working tree and process environment, so agents can locate and organize supported local secrets without asking owners for source paths or variable names.
- Added provider-native `/fast` controls with an enabled-state footer badge: OpenAI Codex and Grok use priority/default processing independently from reasoning effort.

### Changed

- Durable goal creation is now available at agent discretion during ordinary owner turns while exact token budgets remain owner-controlled; explicit chat goal phrasing still starts goals directly.

## [0.93.10] - 2026-08-19

### Fixed

- Preserved classified tool-execution metadata through credential-output redaction, so completed non-zero shell exits remain `operation_outcome` results in the real session runtime instead of reverting to harness failures.
- Stopped goal continuation after an aborted/error provider turn and suppressed idle autosteer after an interrupted foreground response, preventing one abort from consuming the entire stall allowance with immediate hidden replays.

## [0.93.9] - 2026-08-19

### Fixed

- A shell command that runs to completion and exits non-zero is now reported as an operation outcome rather than a tool failure, so a red test baseline, a search that matched nothing, or a false predicate reaches the model as its own verbatim output and no longer consumes recovery budget. Timeouts and blocked broad searches remain tool failures.
- Removed the task-step "recovery exhausted" guidance branch. Task context is only ever injected alongside a user prompt, and a user turn already re-admits the operation, so that branch could only ever describe a refusal that had just been cleared.
- Aligned lean and minimal system prompts with the agent package's shared retry rule: an unchanged operation is not replayed immediately and is readmitted after another successful tool call or a new user turn.

## [0.93.8] - 2026-08-19

### Fixed

- Bash failures now carry the exit code and a stable SHA-256 digest of the complete raw output, independent of bounded previews and managed output paths.

## [0.93.7] - 2026-08-18

### Fixed

- Fixed native Windows RPC shutdown after a persistent PowerShell command by re-arming child terminal observation before teardown.

## [0.93.6] - 2026-08-18

### Changed

- Context GC keeps investigations intact: the recency window default rose from 8 to 24 messages, tool results referenced in recent assistant turns are protected from packing (superseded reads still pack), and packed stubs now cite retrieval as an imperative `read <path>` call.
- Skill vault loads accept an optional pin (up to two): pinned skills are protected from eviction while loaded, still expire idle and count against the slot and byte budgets, and eviction now honestly selects the oldest-loaded unpinned skill (per-skill use is unobservable, so the previous least-recently-used ordering was effectively load order).
- The standing system prompt slimmed down: the N+2 architecture and evidence-gate statutes moved out of the full core into on-demand skills (new bundled `n-plus-2-architecture`; existing `evidence-gated-tdd`) behind one pointer line, and the contract gained explicit precedence (current-turn user instructions override standing style, never security) and answer-shape rules (analysis asks get complete answers; harness protocol text is never restated as an answer).
- Release preparation now delegates mandatory full-suite validation exclusively to successful GitHub Actions CI on the exact preflight HEAD; local release commands never run the full suite.

### Fixed

- Same-batch edits to one file no longer collide: an identity change observed at execution triggers a bounded re-read and anchor revalidation (twice at most), with the write serialized against this process's mutation queue and checked against the revalidated version immediately beforehand, and a stale anchor caused by this run's own earlier mutation says so. A write by another process landing between that check and the write itself is still neither detected nor preserved — an unchanged pre-existing limitation, now stated literally in the code instead of described as atomic.
- File-identity checks no longer discard the nanosecond timestamps `stat` already returns, so a same-size in-place rewrite completing inside one millisecond is now visible to the edit tool's staleness checks instead of comparing equal. The two identity fields are optional additions, so existing implementers of the published inspection contract are unaffected.
- Policy rejections that teach no longer lose their lesson to diagnostic truncation: broad-search blocks resolve through a catalogue entry whose guidance carries the narrow-form advice and the `broadSearch="route-to-file"` escape route un-truncated.
- Tests spawning the CLI as a child process now pass the suite's `pi-source` resolution condition, so a stale gitignored `dist` build can no longer crash the child at startup and fail six startup tests with unrelated assertions.
- Blocked-replay and circuit-exhaustion failure records now lead with the retained root-cause diagnostic and carry the replay or circuit notice in a separate note field, and the all-caps recovery corrections were replaced with one calm actionable sentence each — anti-replay semantics, thresholds, and termination unchanged.
- Compacted lean system-prompt guidance: streamlined Windows bash tool guidelines and tightened the lean operating contract so 16k context-window models stay within the 8192-character capability budget under representative Windows runner working directory paths.
- Hardened Windows process lifecycle and worktree cleanup synchronization: synchronous best-effort termination now feeds one keyed, watchdog-bounded shell barrier that tracks every admitted child generation through `close` and reports strict release failures; worktree harnesses compare platform-correct canonical paths, clean all owned roots after partial initialization, and retain teardown errors; worker model pin tests use authoritative event-driven completion without polling; and background tool handoff has a deterministic tool-start barrier.

## [0.93.5] - 2026-08-17

### Changed

- Made the skill vault multi-slot: up to three concurrent skills share one byte budget with least-recently-used eviction, load results state the pending activation, base directory, and any evicted skills instead of claiming immediate activation, and unload/status operate per slot.
- Bash failure results now report the effective working directory the command ran in on a final `cwd:` line — shell-reported `$PWD` from a collision-safe length-framed POSIX exit sentinel, or the state-tracked effective cwd on the Windows contract — and the tool description states the persistent-cwd contract.

### Fixed

- Stopped tool-failure records from destroying evidence: missing-path failures retain the diagnostic naming the exact path, and executed process-exit failures carry a bounded sanitized tail of the command output as evidence while blocked replays gain nothing new.
- Made catalogued per-error guidance lead the failure correction ahead of the recovery gate's loaded-action text, so specific advice (such as listing a missing path's parent) is no longer displaced by generic repair-action instructions.

## [0.93.4] - 2026-08-17

### Changed

- Made active extension/project/account tools explicitly on-demand: availability, wildcard profiles, repository context, prior sessions, or tool guidance alone no longer establish relevance, and optional credential gaps do not trigger speculative `secret_store` use.

### Fixed

- Made stale `edit` anchors return a bounded digest-qualified snapshot from the exact current source checked by the atomic matcher, while keeping exhausted edit operations local so corrective reads and changed edits remain available without redundant post-success rereads.
- Fixed workflow lifecycle and capability envelope defects: enforced mutating tool capabilities on `pipeline`, `worktree_sync`, and `improvement_loop`, unified cwd-aware path envelope evaluation across relative roots and denied subtrees, prevented stranded waiters and admission races across manual and automatic compaction, re-armed multi-batch goal auto-continuation loops without phantom budget charges on pre-provider exhaustions, stage-scoped open pipeline checklist gates, bounded recursive stage output discovery against external symlink escapes, and captured trailing out-of-process mailbox replies on timeout without error suppression.
- Re-authorized action-sensitive memory and pipeline calls at the compiled gateway while preserving explicit extension manifests, kept delegated memory query-only, enforced credential-migration source scopes, and gated every context-scout child read through one immutable caller envelope without inventing outer paths for composite or fixed-store reads.
- Persisted exact pipeline run/stage checklist links with explicit unlinking and one authoritative normalization/bounds path, serialized project-wide pipeline lifecycle mutations across processes, and made run/definition/context restoration project-owned, symlink-safe, bounded, disk-authoritative, fail-closed on corrupt or conflicting manifests, and resilient to stale or unavailable session snapshots.
- Preserved primary manual-compaction failures through reconnect cleanup, kept path-scope authorization realpath-authoritative while denying resolved escapes, isolated malformed pipeline definitions, and made bounded durable reads symlink-resistant and version-stable while context-scout line counting stays constant-memory.
- Restored background tool tasks only from the active session's bounded fork lineage, excluding unrelated records from task lists and monotonic task-id allocation.
- Kept constrained system prompts within their cross-platform capability budgets by canonicalizing resources to LF, using compact connector/edit/checklist guidance, and charging pipeline-link instructions only when the pipeline tool is active.

## [0.93.3] - 2026-08-17

### Changed

- Made root and nested-worker delegation guidance provider- and reasoning-independent with task-scoped parallelism criteria, removed per-dispatch budgets from model-facing worker starts and task profiles, disabled foreground cost warnings by default, and left worker-tree cost/time ceilings unbounded unless explicitly configured.

### Fixed

- Kept local worker terminal messages out of provider usage and reservation accounting, classified worker protocol faults without transport retries, and allowed incremental edits after prior successes without cross-operation failure-family shutdowns or contradictory completion guidance.

## [0.93.2] - 2026-08-17

### Fixed

- Prevent image-heavy sessions from entering ineffective auto-compaction and report fixed versus compactable context separately when bounded compaction cannot recover.

## [0.93.1] - 2026-08-17

## [0.93.0] - 2026-08-16

### Breaking Changes

- Removed `ACTIVE_SKILL_CONTEXT_CUSTOM_TYPE`; active skill guidance is now projected through `AgentContextPlan.transientSystemPrompt` instead of a custom message.

### Added

- Added compact provider-neutral `create_goal`, `get_goal`, and `update_goal` lifecycle tools on every model-capability class, backed by the existing authoritative goal executor and persistence path.
- Added `--service-tier` and a session-level `serviceTier` SDK option so harness requests can opt into xAI Priority Processing while retaining request-level overrides.

### Changed

- Split the coding-agent CI suite into four independent shards per OS and removed test-only system setup from release fast paths, targeting a sub-five-minute critical path without reducing coverage or Windows worker parallelism.
- Replaced eager agent-core runtime barrel imports with lean owner entry points to reduce `AgentSession` startup and focused-test import time.
- Updated the Anthropic SDK and sandbox-runtime extension examples to the current releases.

### Fixed

- Kept Linux-relative Windows benchmark ratios visible without letting independent runner variance block binaries that satisfy the absolute release budgets.
- Projected transient active-skill guidance through the provider system channel so models cannot mistake repeated skill projection for new user instructions.
- Kept every collapsed tool panel header-only, including partial, failed, extension, unknown-tool, lazy-history, and direct-shell results, until the user expands it, without orphan expansion hints for renderers that intentionally stay blank.
- Made goal auto-continuation independent of research/delegation lane capability and host-counted unchanged passes toward the durable stall limit, preventing models from bypassing the stop by omitting `no_progress`.
- Let compact lifecycle models report concrete active progress and reject agent-requested goal blocking until three consecutive stalled turns have been recorded while keeping active-goal provider context within its 400-character overhead budget.
- Recorded and reported provider-turn cost-fuse stops distinctly from repeated identical-tool loops, including the correct durable goal stop reason.

## [0.92.0] - 2026-08-15

### Breaking Changes

- Native Windows now requires PowerShell 7 (`pwsh.exe`) as its sole agent-shell host; legacy Windows PowerShell 5.1 and custom non-`pwsh` shell paths are rejected.

### Changed

- The persistent Windows PowerShell host now uses process-scoped headless performance settings and a warmed command path without changing the native code page; managed Unicode stays UTF-8 and mixed Windows-1252 output is decoded compatibly.

### Fixed

- Bun-compiled binaries now await CLI startup, preventing RPC mode from exiting before it attaches stdin and returns the first response on Windows.
- Windows runtimes now prewarm and validate one persistent PowerShell process without a disposable startup probe, and release publishing is gated on native x64/ARM64 latency against Linux.
- PowerShell command completion now joins stdout with a nonce-framed stderr barrier, preventing late stderr from leaking into the next command or racing session teardown.
- Worker-lane teardown now disposes the complete Windows shell execution session before temporary directories are removed, preventing locked-cwd `EPERM` failures.

## [0.91.4] - 2026-08-15

### Fixed

- Empty `profile_inspect` bases no longer read as a start gate. Native `delegate start` still omits `profileId` and uses `authority`; `profile_create` is the only action that needs an owner-authored explorer or implementer base.
- An explicit owner phrase such as `this is a goal` or `the task is a goal` now starts the durable goal from the rest of that message or the previous user task, instead of only authorizing a later `goal start` tool call.
- Handover language after `this is a goal` (`by the way`, `i'm handing over`, sub-agent/role assignment) is classification, not the objective. The previous user task becomes the goal.
- `delegate start` with only the shared-schema `task` field now starts the worker using that brief. Sending both `task` and `instructions` is still rejected so neither value is dropped.
- Failed ad-hoc Python `-c`, Node `-e`/`--eval`/print, and interpreter heredoc probes no longer advertise workspace edit/write repair. That guidance was steering the model to rewrite the probe instead of stopping.
- `read` on a Pi session `.jsonl`, including sessions under a configured custom agent directory, now returns a labeled user/assistant/summary/tool transcript. Authoritative compaction and branch summaries remain visible, while thinking, signatures, summary details, and successful tool payloads are omitted.
- Owner course-changes such as `instead of …, I want to …` and `I want to refactor …` now start the durable goal and authorize `goal start`.
- Explicit goals queued behind an active turn are admitted only when their user message starts, so clearing the queue cancels them and their first request plus retries retain the declared token-budget lease.

## [0.91.3] - 2026-08-15

### Fixed

- Release promote now dispatches the destructive suite on `release-vX.Y.Z` instead of a raw commit SHA, which GitHub rejects and left promote polling until timeout.
- Release prepare now refuses unless HEAD already has a successful `ci.yml` run, so a red or unfinished tree cannot buy another full Ubuntu+Windows matrix or burn a version number.
- CI skips `npm test` and the Windows runner on `Release v*` commits and on the tag publish quality gate. The suite already ran locally (`./test.sh`) and on HEAD. Workspace tests now stop at the first failing package or file.

## [0.91.2] - 2026-08-15

## [0.91.1] - 2026-08-15

### Added

- Host-owned `pipeline` tool walks numbered folder stages (ICM): status is `output/` files, increment completes the current stage then starts the next. `task_steps advance` and `goal increment` share that complete-current-then-start-next verb. Goal complete refuses an active pipeline; pipeline increment refuses linked open task_steps and running `tool_task`s. Current-stage context is injected as a GC-managed `<pipeline_context>` page. Workers and lean models cannot activate `pipeline`. The bundled `icm-architect` skill is the authoring method for building a workspace; the runtime does not name it from the tool.

## [0.91.0] - 2026-08-14

### Breaking Changes

- Omitted worker `forkTurns` now defaults to self-contained birth context (`none`) even for same-provider/model root workers. Set `forkTurns` to `all` or a positive turn count to inherit sanitized parent turns.
- Repository `AGENTS.md`/`CLAUDE.md`/`GEMINI.md` stay off until a settings layer sets `projectContextFiles` to `"on-demand"`, which lists paths only. They are not injected. Global `~/.pi/agent` context files remain mandatory. `--no-context-files` no longer disables the global file.

### Changed

- Packed tool output and truncated bash/python model previews now keep a head+tail window so first hits and terminal errors both survive. Live TUI preview stays tail-only. Full output is still saved to the artifact or managed file.
- Repository `AGENTS.md` loading is opt-in per directory. Default is global `~/.pi/agent` files only. `/settings` → Project AGENTS.md enables listing this project's files or keeps global-only; save per directory, project, or all projects.
- Collapsed file edits no longer dump the full diff. Consecutive edit/write calls group into a count, a 2–3 file snippet, and the last successful action; `Ctrl+O` expands the full list. Thinking blocks are hidden by default (`hideThinkingBlock`, `Ctrl+T` to show).
- Collapsed tool groups use human nouns: Task Step(s), Skill(s), Worker(s). Skill, Skillify, and Skill Audit share one skills group.
- Worker terminals that need parent review no longer interrupt the owner with Review now / Keep blocked. The parent agent wakes on the existing terminal handoff and decides via `delegate` status/review. The human stays on the edge: no blocking owner question is queued.
- `Ctrl+O` only expands or collapses tool output. Deferred session history loads on `Ctrl+Shift+H` (`app.history.load`) so an expand never remounts the transcript.
- Exported `loadProjectContextFiles()` now matches the live loader: default is global files only; `includeProject: true` lists project paths without injecting their bodies.
- Long-term memory retrieval now consults a local durable graph when one is present on disk, so graph recall happens automatically on the next turn.
- Wired built-in `memory`, `skillify`, `skill_audit`, and `improvement_loop` onto the default capable-session tool surface so they activate when the model/session can use them. Session create now initializes the bundled memory providers, so SDK sessions that never bind extensions still get the `memory` tool when the grant allows it. A `memory` write of a repeatable procedure now triggers reflection, and a clean `promote_skill` lands as a loadable skill under stock policy. An owner who enabled auto-apply and omitted `skill` still keeps that ceiling. Workers still cannot take the write/self-adaptation tools.
- Goal, `task_steps`, and `tool_task` now share a live join: a still-running background tool cannot verify goal evidence, agent complete refuses while linked checklist steps or cited tool tasks remain open, and continuation waits on those running tasks.
- A just-written or archived skill refreshes the live catalog, so `skill` search/load can use it in the same session without `/reload`.

### Fixed

- Goal start authority now accepts owner speech such as `this is a goal, use it` while still rejecting `goal-oriented` compounds and ordinary task text.
- Failed goal actions, including unauthorized start, now return `isError` so tool-failure recovery can block unchanged retries in the same turn.
- Failed `delegate` validation, API-correction, and start-skip results now return `isError` so unchanged retries are blocked instead of burning another worker turn.
- Worker `delegate list` now marks which session peers the caller can control. Nested-limit guidance tells the model to reuse only `controllable=true` descendants, not siblings.
- Nested worker start is rejected at admission when the tree already holds its `maxAttempts` ceiling, instead of returning started and dying before the first provider token.
- Corrected the `delegate` `forkTurns` parameter description so omitted starts document `none`, matching the runtime default.
- A worker tool denial for an exhausted token/cost/wall/tool budget now terminals the lane instead of blocking one call and letting the model retry other paths.

## [0.90.12] - 2026-08-14

### Fixed

- Stopped `task_steps_context` from telling the model to continue an in_progress step after tool-recovery exhaustion of the last unchanged operation.
- Healed extension tool calls that omit identity already produced by a successful result from the same extension (for example `boardId` after `resolve_project_scope`), so the next call executes with that evidence instead of repeating the empty operation.

## [0.90.11] - 2026-08-14

### Fixed

- Anchored Windows tool/recovery/package-command fixtures to `realpathSync.native(tmpdir())` and gave the leftover module-level bash tool a disposable session, so release-gate load no longer hangs `exit 1` or `rmSync` on 8.3 short paths.

## [0.90.10] - 2026-08-14

## [0.90.9] - 2026-08-14

### Fixed

- Disposed the session resource-loader extension generation on shutdown so Windows can remove the session tree instead of hanging `rmSync` after an all-active profile load.

## [0.90.8] - 2026-08-14

### Fixed

- Rejected provider requests from goal-owned foreground executions after their authoritative goal becomes paused, blocked, usage-limited, completed, cancelled, budget-limited, replaced, or cleared, without mislabeling generic stopped goals as token exhaustion.
- Parsed natural-language goal token budgets with spelled-out units and separator grouping ("5 million", "500 k", "1.000.000"), failed closed on unparseable explicit ceilings, and scoped budget parsing to text outside the goal objective so subject-matter numbers are never adopted as ceilings.
- Stopped goal executions cleanly before the next provider call when the token budget crosses mid-turn, instead of truncating output at a tiny cap or surfacing a synthetic error message; wrap-up turns after a mid-turn goal stop drain gracefully while dead goals still cannot restart.
- Recorded buffered goal usage loudly (warning plus continuation failure) when execution state vanishes instead of silently discarding spend.
- Projected budget-exhausted worker attempts that finish with partial claims as budget-exhausted, and tallied blocked/partial/canceled workers in a new attention count so terminal statuses always partition.
- Bounded a hung worker wait when a blocked write-reservation restore left it with no deadline, evaluated the deadlock guard before the yield erases its evidence, and cleared yield bookkeeping on denied restores so concurrency is not over-admitted.
- Woke a blocked worker-wait restore from the write-reservation availability event instead of a 1s poll, so swarm waits resume on the release that unblocked them; the 300s bound remains a watchdog, not a retry loop.
- Stopped worker lease heartbeats at run completion and fenced renewals with the lease captured at start, so stale runs cannot extend foreign leases and successful workers are not converted to failures during finalization.
- Restored bounded default worker-tree ceilings ($0.50 / 120s); unbounded trees are an explicit opt-in only.
- Excluded retired agents from nested-session delegation limits.
- Kept a stuck worker terminal handoff observable and recoverable: an observe-only watchdog warns, the undelivered batch is preserved for restore, and durable identity is ensured at flush time so restarts replay it without redispatching in-flight work.
- Ordered mandatory delegate directives ahead of optional profile listings in the provider guideline budget, dropped overflowing guidelines whole with a visible diagnostic instead of truncating mid-word, and surfaced worker model pin gaps (roles-only configs list unpinned roles; delegations bypassing pins via an unpinned role are flagged).
- Released write-reservation leases on coordinator dispose and stopped leaking the goal execution lease on a synchronous prompt failure.
- Centralized goal-active checks behind isGoalExecutionActive with a boundary rule banning inline goal-status comparisons outside core/goals.
- Stopped labeling OpenRouter's OAuth (a permanent API-key exchange, not a subscription) as "(sub)" in the footer/usage cost summary and stopped routing its billing failures through subscription-hop failover; both now key off the provider's `isSubscription` flag instead of bare OAuth-auth-type.

### Added

- Showed each OAuth provider's login label (e.g. "Sign in with SuperGrok or X Premium") as secondary text in the `/login` provider selector.
- Documented xAI (Grok/X subscription), Kimi Code, and OpenRouter under docs/providers.md's Subscriptions list; added `grok`/`supergrok` CLI provider aliases for `xai`.

### Changed

- Split releases into prepare and promote: the tag is created only after CI is green on the exact release commit, staging uses an explicit allowlist, the gate guard is an execution proof, and changelog or release-note gaps abort loudly.
- Made model catalog generation hermetic by default (live fetch only with PI_FETCH_MODELS=1) with a scheduled drift check that fails on removal of repo-referenced models.
- Extracted extension runtime binding from AgentSession into ExtensionBindingController and ratcheted the session line ceiling down (4000 to 3900).
- Defaulted the xAI provider to grok-4.6; the native catalog is grok-4.5 and grok-4.6 on the subscription Responses path.
- Added the full H1 crash sweep and executable invariant catalogue (`test:destructive`), plus a nightly/dispatch `destructive.yml` gate that `release:promote` requires before tagging.
- Added H3 seeded interleave and H4 virtual-time soak to `test:destructive` (INV-W1/W2/W3/W5/B1 under shuffled worker ops; stall/worker-wait/budget and stuck-notify/heartbeat watchdogs).
- Documented the propertyAliasNormalize repair mode in the bundled tool-call-repair skill and reference grammar.

## [0.90.7] - 2026-08-13

### Fixed

- Acknowledged worker terminal notifications at durable message acceptance without redispatching an in-flight handoff, and prevented late goal-bound terminals from restarting a stopped parent.
- Required current owner authorization for model-created goals and exact owner authorization for token ceilings.
- Charged every goal-owned provider response with the shared cache-discounted token rule and bounded each subsequent provider output by the remaining explicit budget.

## [0.90.6] - 2026-08-12

### Fixed

- Fixed oversized extension tool prompt snippets and guidelines crashing session startup instead of being bounded for provider-visible context.

## [0.90.5] - 2026-08-12

### Added

- Added optional provider-neutral worker model pins with global-first role/default precedence, immutable fresh-worker and verifier admission, fail-closed validation and availability checks, effective-binding reporting, and zero provider prompt/routing overhead when unconfigured.

## [0.90.4] - 2026-08-12

## [0.90.3] - 2026-08-12

### Fixed

- Removed the implicit `$0.50` and two-minute worker-tree ceilings while preserving explicitly configured global, profile, and inherited budgets.
- Renewed durable worker leases during long provider and tool waits so active workers can checkpoint and publish terminal handoffs after the original lease expiry, with host-safe intervals for explicitly unbounded leases.
- Rejected `laneId` on `delegate start` instead of silently discarding it and creating an unexpectedly anonymous worker.
- Preserved provider-authored `delegate` arguments while sanitizing action-specific dispatch copies so durable worker transcripts cannot diverge after tool execution.
- Retried provider-neutral isolated worker error completions and retained bounded failure detail for durable recovery instead of flattening them to `model_error`.
- Suppressed ineffective auto-compaction retries when the next context estimate drifts downward without material growth.
- Classified recursive ancestor-directory shell searches as broad and exposed the existing bash timeout ceiling in the tool schema so model-generated calls cannot silently request millisecond-style hour-long commands.
- Kept ordinary fresh delegation lean when budget authority is omitted, exposed explicit per-worker authority ceilings alongside inherited and profile budgets, removed the runtime-only verifier role from the model-facing start contract, restored bounded recursion to the profile-free baseline, and kept that recursion when ordinary worker tools are narrowed unless an explicit capability restriction makes the worker a leaf.
- Limited profile-free workers to one direct child at depth one through immutable admission state, while preserving broader owner-authored profile limits and preventing descendants from widening an ancestor's limit.
- Limited the lean profile-free session to one retained nested identity across all root workers so parallel roots cannot each create a duplicate child tree; authored profiles can explicitly raise the session-wide nested limit.
- Aligned PowerShell discovery with its cold-start availability probe and bounded the native incident-collector test around both PowerShell subprocesses under loaded Windows/WSL hosts.
- Marked broad-search guard rejections as pre-execution operation feedback so compaction cannot promote a corrected search call into a harness failure.
- Defaulted nested workers to self-contained birth context so foreground orchestration instructions cannot make a scoped read-only leaf report missing parent authority as a harness failure; explicit same-model inheritance remains available.
- Marked inherited foreground history as context-only in the mandatory worker system contract so parent-owned orchestration cannot override the latest task envelope or consume nested capacity.
- Classified queued workers as admitted event-driven work across start, status, and task projections, forbade interrupting healthy workers to force a queue, taught read-only authority narrowing for genuine parallel review, and required cancellation of a superseded queued task after its replacement starts so safety serialization cannot become duplicate execution.
- Preserved review-pending results as `partial`, project-level blockers as `blocked`, and evidence-classified retries as nonterminal so foreground orchestration does not mistake them for harness failures.
- Rejected worker self-waits and made child waits yield then reacquire the caller's exact fenced write reservation so queued recursive orchestration can run without concurrent mutation or a parent-created deadlock.
- Identified depth, direct-child, nested-session, and session identity capacity denials as expected policy outcomes and directed workers to reuse an eligible idle worker instead of misreporting the denial as harness instability.
- Required parents to drain every paginated child transcript before judging a terminal handoff and added mandatory literal guidance that delivered `worker_blocked` claims are task blockers, not lost worker state or harness failures.
- Allowed one exact failed shell probe to run again after a successful `edit` or `write` mutation in the same canonical workspace, while keeping policy failures, unrelated workspaces, and untrusted custom adapters isolated.
- Distinguished explicit-reply inbox waits from worker-completion waits, preserved pre-deadline completion through delayed caller-resource restoration, reported late idle results as completed-after-timeout, required non-timeout idle waits to retrieve durable claims through status or every transcript page, classified suspended workers as durable nonterminal state with host-owned retry guidance, and added mandatory literal timeout and follow-up guidance so waits cannot become false worker stalls or missed-completion diagnoses.
- Rejected profile-only `task` and top-level `budget` fields on `delegate start` instead of silently dropping a child objective or turning explicitly bounded work into an unbudgeted dispatch; mandatory guidance classifies both as expected API corrections and requires one immediate retry with the value unchanged in `instructions` or `authority.budget`.
- Preserved attempt-local and worker-tree budget exhaustion as authoritative `budget_exhausted` terminal outcomes instead of flattening bounded denials to generic `completion_error` failures, with mandatory handoff guidance that earlier transient transcript errors cannot replace the terminal cause.
- Classified an unknown optional worker profile as correctable routing policy, with mandatory guidance to omit `profileId` for adaptive authority or use an exact listed preset instead of reporting harness failure.
- Classified unavailable optional worker models and presets as correctable routing policy, with mandatory guidance to omit the model/profile selection and inherit adaptive authority instead of reporting harness failure.
- Classified `agentId` as reuse-only in mandatory guidance and treated an unknown reuse identifier as a side-effect-free API correction rather than lost worker state or harness failure, preserving the instructions and intended authority for one fresh retry.
- Kept the fully wired root delegate schema and guideline surfaces below the provider startup ceilings while retaining explicit budgets and mandatory caveman task, budget, timeout, reuse, and profile rules.
- Kept terminal worker execution errors separate from harness health and added mandatory caveman handoff/status guidance that tool timeouts and provider, API, network, WebSocket, fetch, overload, or exhausted-retry failures must not stop healthy siblings unless orchestration state, delivery, or control evidence actually fails.

## [0.90.2] - 2026-08-11

## [0.90.1] - 2026-08-11

### Fixed

- Projected failed and canceled background-task waits as tool errors, and blocked active goals after recovery-exhausted or runaway stops so automatic continuation cannot restart the loop.

## [0.90.0] - 2026-08-11

## [0.89.0] - 2026-08-11

### Fixed

- Kept the Windows Bash tool schema within the provider-context budget without removing its routing contract.
- Made process-matrix watcher ticks expose their asynchronous completion to deterministic timer drivers.

## [0.88.0] - 2026-08-11

## [0.87.0] - 2026-08-11

### Breaking Changes

- Removed `formatSkillsForPrompt`; skill catalogs are no longer rendered into system prompts. Use the host-owned `skill` vault/tool lifecycle.
- Provider prompt additions from extensions must use replay-safe `context.transientMessages`; `before_provider_request` now rejects payload growth after request admission.

### Added

- Added autonomous model-blind credential migration from environment variables, dotenv files, and credential/key files into current-project Bitwarden profiles without exposing values; an unavailable TUI vault requests only one masked `BW_SESSION` key before continuing.
- Added import-free provider-prompt and tool-contract budgets that reject oversized harness prose before it reaches a model.
- Added provider-only extension context messages that remain outside durable session history and compaction summaries while participating in complete request admission.

### Changed

- Compressed system, tool, worker, recovery, and dynamic provider context while retaining mandatory rules, exact capabilities, security boundaries, and user or skill content.
- Unified worker status, review, event waits, and profile management under `delegate`; removed `context_audit` and obsolete split delegation tools from the default model surface while retaining `/context` and explicit diagnostics.
- Changed skill discovery to retain bounded frontmatter only; one compact tool now searches metadata and loads one exact body request-locally, while the host owns monotonic usage, idle expiry, file/profile invalidation, and context-cost reporting.

### Fixed

- Made tool-failure recovery records explicitly mandatory and guaranteed one tool-free user delivery after the recovery circuit opens.
- Made provider request planning transactional across extensions, memory, goals, active skills, tool projection, and text-only tool protocol; only durable history is compacted, replanned history is adopted by the live loop, and irreducible mandatory envelopes fail explicitly.

## [0.86.17] - 2026-08-10

## [0.86.16] - 2026-08-10

### Fixed

- Fixed Windows tool-failure recovery contract fixtures to use canonical temporary paths.

## [0.86.15] - 2026-08-10

### Added

- Added explicit recovery contracts for `read`, `write`, `edit`, and `ls`; only raw successful `write` evidence from the same backend authority and canonical path can prove that a missing file was created, while inspection and retarget actions require changed calls. Custom operation adapters must share an explicit authority before cross-tool recovery is taught or admitted.

## [0.86.14] - 2026-08-09

## [0.86.13] - 2026-08-09

## [0.86.12] - 2026-08-09

## [0.86.11] - 2026-08-09

### Fixed

- Preserved `reply_target_forbidden` for explicit destination overrides on `reply` while allowing extraneous fields on `inbox` and `reply` to be automatically sanitized.

## [0.86.10] - 2026-08-09

### Fixed

- Fixed delegate tool rejections by auto-sanitizing extraneous optional fields on flat action schemas so LLM dispatches proceed cleanly without dropping execution.
- Increased terminal handoff timeout to 30 minutes (1,800,000ms) and ensured active subagent progress runs unconstrained while idle watchdogs handle transport stalls.
- Reinforced Team Lead orchestration policy and event-driven wakeup so orchestrators immediately address subagent help requests and steer active parallel execution.

## [0.86.9] - 2026-08-09

### Fixed

- Fixed host-denied capability tool calls (like writing outside workspace bounds or accessing private memory) permanently marking the overall agent worker attempt as blocked; agents can now self-recover from a policy denial and complete the task successfully.

## [0.86.8] - 2026-08-09

## [0.86.7] - 2026-08-09

### Fixed

- Fixed delegate worker authority hallucinations crashing the worker by normalizing platform tool aliases (`python_tool` -> `python`, `powershell` -> `bash`) and automatically reconciling the `workflow.delegate` capability when the orchestrator explicitly includes the `delegate` tool in authority constraints.
- Removed Windows-specific `powershell` prompt guidelines and tool manifests to enforce the strict bash shell contract and prevent model confusion.
## [0.86.6] - 2026-08-08

### Added

- Enforced goal-graph dependency validation during worker admission, blocking worker dispatches whose target requirements depend on unsatisfied or open requirements.
- Automatically injected memory query capability and memory tools into worker execution plans when memory retrieval is enabled.

### Fixed

- Allowed auto-injected memory query capability and memory tool through worker execution contract boundaries without violating static capability ceilings.
- Exempted worker verification requests from goal-graph dependency checks so completed worker tasks can always be verified.

## [0.86.5] - 2026-08-08

## [0.86.4] - 2026-08-08

### Added

- Made persistent workers the default delegation workflow: `delegate start` with an `agentId` now dispatches the new task onto that existing worker's durable conversation (idle agents only; the worker keeps its admitted authority — passing `authority`/`profileId` is rejected with `reuse_keeps_admitted_authority`; busy/unknown agents fail with explicit reasons), `list` reports each agent's live `activity` so idle specialists are discoverable, and the tool contract teaches the orchestrator to prefer reuse over minting unnecessary fresh worker identities. Starting without `agentId` creates a fresh specialist identity and conversation whose bounded birth context follows `forkTurns`.
- Added a host-owned, restart-durable worker attempt ladder: a delegated worker that fails on an evidence-classified transient error (network, 5xx, rate limit) is suspended durably and re-enqueued after jittered backoff, resuming from its persisted transcript under a fresh fence — instead of terminalizing and forcing the orchestrator to re-delegate blind. Bounded by the grant's durable `maxAttempts` ceiling (default 2 total attempts; `maxAttempts: 1` never ladders), evidence-gated (failures without a classified transient cause never retry), and restart-safe through persisted suspended state and the existing recovery path.
- Added a live agents panel (`ctrl+q` toggles, `escape` closes; configurable via `app.agents.open`/`app.agents.close`) as the detail view behind the statusline's aggregated concurrency counts: each worker lane with status, runtime, profile, elapsed time, and cost, plus running background tools — rendered in the same orchestration-panel row language as the delegate tool output.
- Added a shared bounded `delegate tasks` view of durable DAG tasks and attempts, same-objective `dependsOn` dispatch gates, peer `broadcast`, event-driven `wait_many`, subtree-scoped wake/control actions, durable root reply inboxes, and replay-safe idle-leaf retirement that preserves agent bindings and transcripts.
- Added immutable sanitized worker birth context with `forkTurns: "none" | "all" | "N"`: same-provider/model children inherit all bounded complete turns by default, cross-provider/model children default to none, and explicit cross-boundary inheritance is rejected.

### Changed

- Redesigned the activity statusline above the editor into a fixed-slot layout (turn state · plan position · concurrency counts · last event): slots keep stable positions instead of shifting as chips arrive, concurrent background tools aggregate into per-runtime counts (`2 bash · 1 python`) instead of enumerating task ids, background tool chips show the task description instead of internal `tool-task-N` ids, color now carries status only, and only the plan slot truncates when width runs out.
- Bounded recursive orchestration before durable side effects (depth 8, 64 direct children, 256 each for session agents, tasks, and attempts, and 256 queued dispatches), persisted retry eligibility as exact `notBefore` deadlines, and exposed bounded retry/dependency state through the shared task projection.
- Raised the default global worker concurrency from 1 to 20 while retaining explicit positive safe-integer overrides and the existing fixed fleet, queue, budget, and write-reservation safety bounds.

### Fixed

- Fixed TUI startup benchmarks stopping the renderer without disposing session-owned resources, which left packaged smoke and profiling processes running indefinitely.
- Fixed the native Windows incident collector honoring an ambient session-directory environment variable over an explicitly supplied agent directory.
- Fixed persistent-worker control recovery so task-bearing wakeups, terminal handoffs, and inferred replies remain crash-safe and replay-safe after mailbox history pruning; bounded mailboxes now reserve mandatory byte, entry, and replay-evidence capacity, terminal notification failures retry autonomously, session-root replies use an explicit acknowledged inbox, and poisoned terminal-correlated tasks no longer block later work.
- Fixed delegated workers dying with bare `completion_error`: token budgets now charge prompt-cache reads at 10% instead of face value (a fixed ~3k-token cached system prompt no longer turns `maxTokens` into a request counter), non-viable grants (`maxTokens` under 5000) are rejected at `delegate start` with `token_budget_below_floor` instead of starving mid-flight, worker failure summaries and research lane results carry the underlying executor error, and transient provider failures (socket drops, 5xx, rate limits) retry with jittered backoff inside the worker attempt instead of failing instantly at $0.
- Fixed corrupted TUI rendering (stale duplicated status lines, wrapped line fragments) on terminals that render East Asian ambiguous characters (`·`, `…`, `●`) as two columns, such as Windows consoles with a CJK codepage/font: the renderer now probes the terminal's actual character width at startup and recalculates layout accordingly.
- Replaced timer-loop parent terminal-handoff retries with one bounded attempt-keyed retained queue that drains only on explicit terminal, mailbox-capacity, state-change, and recovery events; exact replays are inert, conflicts fail closed, callback failures remain retained, and reentrant signals redrain without polling.
- Fixed worker orchestration edge cases around bounded transcript paging, reopened transcript equality, tied attempt timestamps, long mailbox-control payload sanitization, paused suspended resumes, and concurrent mandatory verifiers: raw-entry cursors now disclose empty continuations and oversized-message omissions, canonical JSON and shared tool-detail retention prevent false divergence after a locked reopen, durable insertion order selects activity, paused work stays nonterminal, and admitted verifier demand retains queue/projection headroom plus capacity-event replay.
- Fixed orchestration authority drift by routing command admission, event replay, and snapshot recovery through exact shared reducers and strict codecs; canonical persistence and replay now reject unsupported fields, conflicting identities, invalid graph relationships, and divergent retained state, while file-locked exact-content reconciliation prevents stale worker-session owners from duplicating durable control delivery.
- Fixed persistent-worker transcript and completion ownership: one revision-fenced conversation core now verifies exact append bytes and bounded callback-evidenced suffixes across retries and cancellation, rejects stale supported writers, ownership-boundary content changes, unreserved results, and late output, preserves immutable birth metadata, accounts cumulative retry cost, and retains shared provider reservations until returned usage is charged.
- Fixed worker crash recovery discarding a durably persisted empty terminal response and calling the provider again; recovery now replays the empty completion so the original deterministic output validation runs without duplicate work or cost.
- Fixed malformed ancestor `.git` markers capturing project credential scope; repository discovery now requires a bounded, valid symbolic or detached Git `HEAD` before reading remote configuration.

## [0.86.3] - 2026-08-06

### Fixed

- Enforced a maximum 1-level delegation nesting model (orchestrator + leaf workers): removed `delegate` and `workflow.delegate` from default worker authority, and rejected nested subagent `delegate` `action: "start"` calls with `subagent_delegation_disabled`.

## [0.86.2] - 2026-08-06

### Fixed

- Aligned memory state sidecar paths with the `managedMemoryStateFile` SSOT, preventing root-level `.pi-managed.json` file generation beside `MEMORY.md` / `USER.md`.
- Enhanced `migrateAgentDirLayout` to automatically discover and migrate unexpected root files and folders under `~/.pi/agent/` to their canonical `state/` directories.
- Relaxed `wrapToolWithCredentialExposureGuard` to execute tool calls without upfront blocking errors on search or Python scope heuristics, relying on redacting loaded secrets from tool results instead.

## [0.86.1] - 2026-08-05

### Fixed

- Matched active project credentials across canonical, symlinked, and Windows short-path working directories, and aligned orchestration regression gates with explicit non-delegating leaf profiles and effective profile-free capability telemetry.

## [0.86.0] - 2026-08-05

### Breaking Changes

- Replaced the local `SecretVault`/dotenv-materialization API and model-driven credential mutation actions with a provider-neutral credential manager backed by Bitwarden; the model-facing `secret_store` now exposes only status, metadata listing, and project-authorized activation.

### Added

- Added automatic pinned `bw` provisioning, the private `/secrets` owner workflow, portable Git-project bindings, cross-machine Bitwarden sync, and in-memory credential injection for Bash, Python, and allowlisted direct processes without exposing `BW_SESSION` to model-controlled execution.

## [0.85.9] - 2026-08-05

### Added

- Added durable recursive worker-agent trees with inherited delegation, exact paginated peer transcripts, threaded messages, event-driven agent controls, platform-shell execution, and model-authored model/reasoning/tool/capability/path/budget selection.

### Changed

- Changed orchestration profiles into optional presets: profile-free agents receive the maximum host-permitted core surface, direct project writes are enabled by default, roles are labels unless the host supplies a ceiling, root budgets are cumulative, and the global scheduler replaces framework depth, fan-out, and per-profile concurrency caps.

### Fixed

- Made recursive worker orchestration parent-aware: queued children now have stable identities, waiting parents yield scheduler capacity, terminal children deliver one durable idempotent parent handoff, peer controls stay tree-scoped, reply replay is atomic, explicit leaf grants remain non-delegating, and concurrent descendants share cumulative provider budgets.
- Counted durable agent attempts that ended before their first usage checkpoint when reconstructing a root tree's cumulative attempt budget after restart.
- Resolved omitted adaptive-agent reasoning from the selected model's supported default instead of assuming `medium` and rejecting non-reasoning models.
- Chunked wall-clock timers above the host timer limit and saturated durable lease timestamps at the maximum representable date so unrestricted safe-integer budgets cannot overflow into immediate timeouts or failed starts.
- Removed per-event idempotency marker files from the bounded orchestration event store and made its corruption cursor a non-atomic derived overwrite, reducing Windows filesystem and security-scanner churn while retaining exact cross-process deduplication and cursor recovery.

## [0.85.8] - 2026-08-05

### Changed

- Upgraded the pinned test toolchain to Vite 8.2 and Vitest 4.1, enabled the native Node module runner, and made Linux and Windows workflows verify and use the same source-resolution contract.
- Split extension loading, factory execution, virtual-module catalogs, threat scanning, extensionification, and tool-definition construction into explicit lifecycle owners, and replaced broad cross-package barrels with narrow owner imports.

### Fixed

- Serialized supervision start/stop transitions, cleaned partially started peers, awaited runtime-owned memory, GC, shell, and supervision shutdown before process-matrix and early CLI exits, and made Windows memory cleanup wait for worker termination before removing its state tree.
- Made suite and manual-session cleanup await idempotent session disposal before unregistering providers and deleting state, preventing background workers, extension runtimes, and Windows file handles from leaking across tests.
- Serialized same-target async atomic writes and advisory-lock admission with self-removing per-path queues, preventing Windows rename retry storms without bottlenecking unrelated files or tenants.
- Isolated draft extension validation from the live generation, bounded extension factory and disposal lifecycles, and fenced process-matrix storage and llama process ownership behind injected adapters.
- Removed the Vite transform graph from targeted source tests and narrowed heavyweight test fixtures, reducing cold focused-test startup from roughly 7–12 seconds to roughly 2–3 seconds.

## [0.85.7] - 2026-08-04

### Fixed

- Isolated external-resource discovery and reload-rollback regressions from unrelated bundled-extension imports so native Windows release validation retains deterministic time bounds.

## [0.85.6] - 2026-08-04

## [0.85.5] - 2026-08-04

### Fixed

- Treated final ripgrep and grep exit code 1 as successful zero-match results across Linux and Windows, preserved PowerShell grep IO/regex failures as exit code 2, kept routed external commands in the persistent Windows shell, and kept goal-continuation budgets independent from the core identical-tool-call runaway guard.
- Prevented later turns from re-entering an auto-compaction frontier that failed to restore headroom until materially new compactable history exists, while preserving overflow recovery.
- Serialized context-GC payload and artifact ownership updates across processes, replaced quadratic shared reference-array rewrites with bounded holder markers, and kept read-only GC projections from replacing the latest committed report.

## [0.85.4] - 2026-08-04

### Breaking Changes

- Removed model-visible `action` and `intentId` phases from `write` and `edit`; callers now send one semantic mutation containing the path and payload while the harness owns preflight.

### Added

- Added a Pi-managed local execution path for the complete Bonsai and Ternary-Bonsai GGUF families through a pinned Prism llama.cpp runtime, with exact model identity checks, bounded host-derived resource profiles, warm residency, validated paired-drafter policy, and complete Windows x64 CUDA archive installation.
- Added LFM2.5-8B-A1B Q4_K_M to the curated local-model roster as a native-tool-first sparse-MoE worker candidate, with task-scale `/fitness` gating before role assignment and phone-protocol calibration only after native-call failure.

### Changed

- Shape and hard-gate the stable system prompt from the same model-capability profile that filters tools and lanes: lean, minimal, and chat models receive bounded role-specific contracts, oversized project instructions are deferred by path, constrained static memory obeys its prompt budget, and aggregate expansion is rejected after extension overrides without changing native-versus-phone tool protocol selection.
- Made `write` and `edit` single-call model operations while keeping path/capability preflight, serialized stale-target rechecks, and exclusive create semantics harness-owned.

### Fixed

- Hardened phone-protocol tool execution for non-native local models with reasoning-channel envelope recovery, parallel-call identity, single-call write/edit examples, bounded corrective teaching after failures, and protection against repeating an already-successful mutation.
- Prevented write/edit safety preparation from duplicating model tool calls; edit now also rechecks target identity immediately before writing and discards preview plans when source bytes differ, preserving and reporting external changes.
- Retained an exact, digest-verified write or edit payload after a target-only collision or path failure so repair needs only a corrected path; references are session-isolated, bounded, expiring, kind-checked, and consumed after a successful mutation, while invalid references and non-target failures are never presented as retargetable.
- Prevented active goals from becoming permanently blocked by an `Agent is already processing` race: foreground ownership now spans retry/follow-up idle gaps, background handoffs queue into that owner, and goal continuation waits event-first without counting rejected admission as a turn or failure.
- Kept sanitized tool-failure projections authoritative through session context extensions and invoked each extension context handler once per provider request.
- Fixed simultaneous background-tool completions racing separate notification prompts: terminal handoffs are now bounded, coalesced, and serialized while every task result remains individually retrievable through `tool_task`.
- Required Amazon Bedrock to use a durable verified profile-and-region scope, with STS/control-plane discovery, bounded runtime probes, exact model visibility, and request-level region/profile binding; `us-east-2` now resolves only US inference profiles.
- Kept source and bundled extension loading compatible with the lean Bedrock provider entry so startup and transactional reload resolve the same module boundary.
- Updated Undici to 8.9.0 to fix cache-directive parsing, retry framing, blob media-type, cache-control whitespace, and cookie-attribute advisories.
- Serialized asynchronous foreground preparation and terminal background delivery under one identity-bound owner; isolated retained mutation payloads per session and lane without cross-tenant eviction; incrementally indexed worker-input handoffs for long sessions; and transactionally reconciled concurrent `MEMORY.md`/`USER.md` writers with interrupted-write recovery.

## [0.85.3] - 2026-08-03

### Fixed

- Fixed the bundled Windows incident collector on PowerShell 5.1 hosts where the module-provided `Get-FileHash` command is unavailable.
- Fixed native Windows path canonicalization so 8.3 short paths and their long-path spellings resolve to one resource identity.
- Fixed cooperative worker cleanup under Windows file-lock contention so terminal state is durably persisted, including cleanup requested during the adoption grace window.
- Fixed system Python detection incorrectly accepting the Windows Store execution alias or another non-Python executable as an installed interpreter.

## [0.85.2] - 2026-08-03

### Fixed

- Fixed fresh Windows search-tool provisioning by pinning checksum-verified `fd` release assets instead of relying on GitHub's rate-limited latest-release API, and hardened Windows release-gate portability without enabling unsupported native tmux.

## [0.85.1] - 2026-08-03

### Fixed

- Prevented concurrent and ineffective repeated auto-compaction runs in image-heavy sessions and contexts with protected recent messages.
- Fixed Windows runtime probes and case-insensitive context-file identity, plus Bash-like path parsing, portable `printf`, word-list and arithmetic `for` loops, and nested `break`/`continue` in the managed shell.
- Preserved managed-tool provisioning causes and bounded execution-failure guidance in recovery logs, failure corpora, and `/toolhealth`.
- Kept proven native tool-call models off the phone/text protocol and routed phone validation, repair teaching, and failure guidance through the shared tool pipeline.
- Required the exact release ref to pass Linux and Windows CI before publishing binaries.

## [0.85.0] - 2026-08-02

### Breaking Changes

- Changed `write` and `edit` to path-first `prepare`/`commit` protocols; `write` is now create-only, and custom file adapters must provide a shared mutation-intent controller plus `createFile` no-clobber semantics.

### Added

- Added session-bounded exact-content references so successful writes and edits can copy unchanged bytes without retransmitting content.
- Added live and terminal elapsed time to every interactive tool panel, including read, Python, extension, error, and replay paths.
- Added `profile_writer` for immutable, session-branch-scoped worker profiles that can narrow owner-approved tools, resources, budgets, models, and thinking levels without writing profile files.
- Bundled the pinned Rust `jscpd` 5.0.14 scanner for every desktop release target and provisioned it only into Pi-managed storage.

### Changed

- Edit commits can bind anchors to inclusive read-line ranges, prove uniqueness globally without occurrence arrays, and reuse a compact preview match plan and diff during execution.
- The core agent contract now treats the user's desired outcome as authoritative over suggested methods and requires evidence-backed disagreement when a method may undermine that outcome.
- Compacted the always-loaded core, goal, checklist, profile-writer, and trust-boundary instructions while preserving their behavioral and security invariants.

### Fixed

- Rejected write collisions, missing edit targets, and stale prepared edits before mutation; non-UTF-8 edits now fail through the centralized change-approach workflow.
- Removed full edit-argument serialization from asynchronous TUI preview rendering.
- Bounded collapsed streamed write previews so growing content is neither rescanned nor fully split and highlighted on each update.
- Kept native delegation available when tmux is missing or unsupported, validated tmux before worktree/process side effects, and prevented regular agents from overriding the owner's worker profile at dispatch time.
- Kept base-profile delegation working with branch-unaware session adapters while explicitly blocking session task-profile persistence on that unsupported boundary.
- Kept local binary release packaging able to stamp the bundled jscpd version when dependency installation is intentionally skipped.

## [0.84.1] - 2026-08-02

## [0.84.0] - 2026-08-02

### Breaking Changes

- Require Node.js 24.18.0 or newer.

### Added

- Provision checksum-pinned ripgrep 15.2.0 and jq 1.8.2 binaries for supported Linux, macOS, and Windows targets, and report both through `/doctor`.

### Changed

- Guide agents to use ripgrep for candidate filtering and jq for bounded JSON projection before native semantic parsing.

### Fixed

- Block jq filters that project the process environment while preserving ordinary `.env` JSON field queries.

## [0.81.43] - 2026-08-02

### Added

- Added provider-neutral `deduplicate-by-evidence` and `evidence-gated-tdd` bundled skills, including evidence scoring and authorized security-scanner references.
- Added bundled `authorized-web-security-audit`, `secure-agent-tool-surfaces`, and `skill-creator` skills for evidence-scored exploit awareness, least-privilege tool design, and portable specialization authoring across providers.
- Added a pinned strict production clone gate that covers all owned TypeScript, JavaScript, Python, shell, PowerShell, CSS, and markup sources, rejects scanner omissions, and requires zero verified 50-token clones.
- Added per-session background tool tasks: calls still running after 15 seconds, or manually transferred with Ctrl+B, return a task ID immediately, persist bounded output, emit event-driven completion, and support one-shot wait or cancellation without polling or cross-session sharing.
- Added a live transcript pager on Shift+PageUp that preserves the viewed position while output continues and resumes tail following only after an explicit jump back to the bottom.
- Added a native PowerShell incident collector, shipped beside `pi.exe`, that places its ZIP beside the script by default and packages the affected human session, recovery/orchestration/TUI evidence, runtime fingerprints, and bounded Windows event records while excluding credential and configuration stores.
- Added bounded command-aware test-output projection for persistent shell sessions: passing chatter is collapsed, failure identity and summaries remain in context, exact raw bytes are handed off through a managed file, and unknown/error paths fall back to raw output without changing exit status.
- Added session-core proactive memory reflection and provider lifecycle delivery across print, RPC, and interactive modes, using bounded semantic turn digests that exclude raw tool-result payloads.
- Added high-confidence natural-language goal admission so explicit chat goals use the same durable continuation state as the goal command without treating ordinary tasks as persistent goals.

### Changed

- Bounded tool-selection observation history by both count and encoded bytes, and compacted machine-owned host-state serialization to reduce rewrite and parse cost in long-lived installations.
- Updated the core agent prompt with a compact, language-agnostic adaptive systems posture: explicit lifetime grouping, zero-valid states where safe, benign stubs at suitable internal boundaries, linear execution, and mandatory correctness/security/API-boundary exceptions.
- Moved the repository to the stable TypeScript 7 compiler through one no-fallback execution path and upgraded the fixed test/build toolchain while retaining exact dependency pins.
- Reduced source and packaged startup transformation by importing lean AI entry points and preferring compiled JavaScript for Pi-owned bundled extensions while preserving TypeScript-first user extension loading.
- Consolidated provider, resource, session, selection, export, process, and TUI lifecycle ownership behind focused systems, with strict clone evidence proving no verified production clones remain.
- Reduced avoidable turn latency by batching independent read-only calls in one model turn, coalescing checklist transitions, reading tool-performance evidence once per decision, moving transcript recall indexing into one bounded worker owned by each session, and exposing bounded passive phase timings through `/toolhealth`.
- Lowered the default fractional compaction trigger from 70% to 60% of the model window while preserving explicit overrides, reserve headroom, recent-context retention, anti-thrash savings, and summary verification.

### Fixed

- Fixed background task control bypassing explicit tool allowlists, resource and orchestration profiles, custom tool surfaces, and model-capability filtering while preserving it on the default session surface.
- Fixed the direct zAI default selecting the retired `glm-5.1` model by resolving to current `glm-5.2` and verifying the default against the generated catalog.
- Fixed large piped stdin ingestion repeatedly copying the accumulated prefix by retaining UTF-8 chunks and joining once after end-of-stream.
- Fixed oversized-file line scanning repeatedly copying newline-free prefixes by assembling decoded fragments through the shared linear line owner.
- Fixed Windows Python-engine latency by keeping one serialized coordinator process per agent session instead of spawning Python for every complex command, with request-correlated output/control barriers and whole-process recovery after aborts, timeouts, crashes, or protocol faults.
- Fixed incident collection to include the current session-owned orchestration namespace after its consolidation under `state/orchestration/sessions`.
- Fixed native Windows incident correlation to derive its bounded Event Viewer window from the selected session and filter shared recovery/failure logs by session identity or timestamp.
- Fixed Windows shell execution so quoted or piped ripgrep patterns retain their proven file/stdin scope, common `ls -la` works across both routing tiers, redirected `.ps1` commands use the selected PowerShell host, native combined commands skip unused PowerShell discovery, and host output no longer leaks duplicate CLIXML records.
- Fixed oversized `USER.md` writes by migrating the full profile into deterministic bounded OKF shards with a compact index, including retry-safe multi-shard migration, archived fact updates, and pre-write rejection of redirected archive directories.
- Fixed compaction to collect provider memory handoff once per run, reuse its bounded result across retries, and preserve the existing compact active-goal projection for automatic continuation.

## [0.81.42] - 2026-07-27

### Changed

- Rebuilt delegated workers around immutable owner-authored execution contracts, durable logical-agent identities, resumable conversations and mailboxes, fenced write reservations, bounded resource materialization, verified model-pinned compaction, and event-driven terminal handoffs.
- Consolidated session-owned orchestration events, actions, mailboxes, conversations, and deletion under one bounded artifact bundle while keeping cross-session write reservations globally coordinated.

### Fixed

- Made the Windows shell engine preserve `$?`, support controlled `exit`, and accept `head`/`tail -N`, so diagnostic-capture command chains complete with a terminal result instead of losing status or treating `exit` as an external command.
- Added a provider- and tool-neutral WSL incident collector that packages the latest human session, recovery and orchestration records, explicitly requested command logs, TUI evidence, boot identity, installed-runtime hashes, bounded kernel diagnostics, and relevant Windows host events without collecting credential stores or emitting false missing-log warnings.
- Made pre-start worker failures publish exactly one durable terminal handoff, rejected malformed typed result envelopes, and handled null or Buffer filesystem watcher filenames on Windows.
- Made orchestration session paths portable across Windows and POSIX and bounded profile, process, event, result, and cumulative usage payloads at their owning contracts.
- Kept explicit empty worker tool surfaces inside the repair loop and persisted immediate or argument-repaired tool requests in durable execution order, preventing unavailable-tool calls from collapsing into completion errors or divergent transcripts.
- Preserved bounded host-observed changed-file progress when an agent-bound worker is suspended, so owner-session disposal remains resumable without fabricating terminal parent-session records.

## [0.81.41] - 2026-07-27

### Added

- Added a model-blind native secret store with a private plaintext dotenv editor, encrypted bounded profiles and workspace bindings under Pi state, metadata-only tool results, user-only UAC routing, normal Bash/Python environment activation, and credential-path/output exposure guards.
- Added a provider-neutral shell search guard that rejects broad `rg`/recursive `grep`/`find`/`fd` scans before execution and supports an explicit managed-file override with bounded disk use.
- Added an OpenAI subscription `/usage` flow for inspecting earned reset passes, reviewing reset details, confirming redemption, retrying idempotently, and refreshing remaining availability.
- Added one event-driven activity lane above the editor for routing, tools, task steps, goals, workers, queues, compaction, and retries, plus an explicit `--session-mode user|worker` audience contract for unattended terminals.
- Added managed Amazon Bedrock SSO login for the exact configured AWS profile, with bounded single-flight CLI execution, automatic pre-response recovery, and a strict no-browser boundary for worker and background requests.

### Changed

- Made durable goals use compact Codex-style provider context and continue without implicit turn, active-time, or spend limits; only owner-supplied token and per-invocation limits stop execution, while time/spend remain observable accounting.
- Split AgentSession contracts, durable goal lifecycle/accounting, owner-input replay, interactive event dispatch, and startup-resource rendering into focused owners, with a repository check preventing either coordinator from reclaiming those responsibilities or exceeding its size boundary.

### Fixed

- Kept retry-guided compaction provider failures inside the exact-request retry layer instead of restarting the compaction plan as an unknown failure.
- Removed successful orchestration bookkeeping from collapsed chat history, retained full detail on explicit expansion, and prevented resumed terminal state from replaying as new completion feedback.
- Deferred retained tool-result reads, renderer construction, and image conversion during collapsed history reload until explicit expansion, with the materialized payload released again on collapse.
- Prevented denied extension code and embedded profile content from crossing the read/import boundary, preserved exact CLI/live grants through reloads without invalidating their shared runtime, and made core acceptance fail on skipped or todo evidence.
- Preserved durable usage from tool hooks, compaction, branch summaries, and resumed sessions across session, daily, and cumulative accounting.
- Rejected resource directories as context files, resolved scoped model IDs literally, exposed unavailable selections, and clarified unsaved-session fork failures.
- Consolidated external-editor execution, restored the Windows terminal title after package checks, reported aborted retries as failures, and corrected manual update checks, npm uninstall compatibility, read-error rendering, and sibling extension paths.

## [0.81.40] - 2026-07-24

### Added

- Added one targeted `accept:core-workflows` gate covering active-worker crash/restart fencing, simultaneous durable writers, repeated compaction/reopen cleanup, provider-neutral routing/reasoning/result/retry contracts, and adversarial UAC omission without running the full test suite.
- Added owner-authored orchestration profiles with pinned model/thinking/tool/resource/budget policy, architect-owned worker allowlists, durable DAG attempts and fenced typed results, exact-session process-worker resume, and a constrained direct-argv `run_process` launcher for execution profiles.
- Added one event-driven native interaction layer for human questions, task steps, and worker lanes: batched single/multi-select questions with unrestricted custom text, clipboard image attachments, skip/review flows, grouped width-bounded work status, durable human worker labels/profile ids, quiet idle behavior, progressive evidence detail, and host-owned lifecycle across extension reload and session resume. Worker UAC excludes the question tool before construction, and the legacy question examples now adapt this native contract instead of carrying two UI implementations.
- Added a bounded session image store for clipboard attachments, configurable through `images.clipboardDirectory`, with stable numbered references that survive `/resume` and deterministic latest-image resolution for prompts such as “look at the image.”

### Fixed

- Fixed Windows startup migration of the NTFS `auth.json:Zone.Identifier` alternate data stream so its bytes move into bounded legacy state and the named stream is removed without rewriting the auth file.
- Persisted one immutable admission-time worker execution contract across queueing, retry, restart recovery, and mandatory verifier recovery, so profile edits cannot silently switch a pending worker's model, thinking level, tools, execution policy, or resource identity; current host policy may still narrow the recorded authority.
- Rebased durable-runtime startup tails onto a projection snapshot installed during the initial read, preventing a concurrent compaction from replaying post-snapshot events without their prefix.
- Made durable orchestration replay and append fail closed on missing event ordinals, truncated tails, inaccessible storage, invalid snapshot idempotency data, and missing or changed published snapshots without reparsing an unchanged projection on every append.
- Fenced process-matrix reconciliation, adoption, cleanup, self-owned heartbeat/exit, resumed-worker PID publication, terminal persistence, and delivery acknowledgement with one shared per-entry conditional-write contract so stale process generations cannot overwrite newer registrations.
- Made session teardown, activation, and quit failures drain every cleanup step; replacement failures reconstruct and rebind the previous durable session, clean rejected candidate resources/artifacts, remain distinct from post-commit callbacks, and serialize process disposal behind any admitted replacement.
- Made session replacement transactional through candidate preparation and awaited old-session resource shutdown, moved process/worktree supervision under the active session lifecycle, restored exact session+task workers only after goal activation, persisted late terminal notices for replay to the owning session, denied automatic recovery for mismatched or terminal goals, and bounded process-matrix retention.
- Fenced overlapping session replacements and RPC prompt/replacement races, and made durable worker terminal notifications acknowledge delivery only after the bounded parent handoff is persisted; owner-question handoffs no longer spend a redundant model turn.
- Made `/resume`, `--resume`, `--continue`, and exact `--session` restore a blocked goal through the same core persisted transition as `/goal resume`, before worker supervision starts.
- Bounded durable orchestration persistence with immutable digest-verified projection snapshots, a count/byte-limited append-only event tail, bounded retained idempotency evidence, crash-safe pointer publication, and monotonic ordinals across compaction and concurrent-runtime catch-up.
- Made owner-input requests crash-safe and transport-neutral: `ask_question` now checkpoints before display, uses the full multi-line editor without an answer-length clamp, RPC exposes the same fail-closed typed question protocol as the TUI, `/resume` replays the original tool-call id, large custom answers remain exact in bounded artifacts, RPC images are retained before checkpoint, client-forged artifact references are rejected, non-vision image submission fails visibly, and worker `ask-user` verdicts create deterministic parent requests instead of relying on prompt compliance.
- Made the clipboard paste action match platform conventions (`Ctrl+V` on Unix/macOS, `Alt+V` on Windows, both on WSL), preserve ordinary text paste when no image is present, resize image payloads through the shared safety path, and keep default storage out of working directories.
- Added a zero-write, single-namespace extension storage contract for durable state, rebuildable cache, and automatically released bounded work; extension loading now honors injected agent directories for transform cache and storage, while `pi doctor` reports unexpected root writers through a bounded read-only audit.
- Contained directory profile overlays and configuration backups under canonical `profiles/` and `state/` namespaces, archived obsolete root scratch/Auto Learn layouts, and added bounded conflict-preserving migration with zero-write legacy reads.
- Consolidated generated context payloads under one leased, bounded per-session work namespace; context/report inspection and unflushed session creation are now zero-write, recognized legacy stores migrate safely, and empty session namespaces are pruned without applying retention to transcripts.
- Consolidated fitness, adaptation, and tool-selection host state behind one validated lock-safe atomic store; concurrent sessions no longer overwrite profile or tool evidence, and worker read-only mode remains zero-write.
- Extracted managed tmux-worker lifecycle and claim review from the background coordinator, made managed and in-process workers share one durable task runtime and terminal outbox without materializing a withheld execution controller, required every managed dispatch to carry its fixed profile, authorization, instruction, provider, turn, lease, tool, path, and budget contract, persisted the full compiled execution grant before process/prompt side effects, rejected scope-changing follow-ups, removed the extension's duplicate parent wake path, removed the research controller's circular dependency on its parent, and renamed raw worker-claim modules so untrusted claims are no longer presented as durable results.
- Consolidated failure-corpus, tool-recovery, and worktree-audit persistence behind one lock-safe bounded JSONL sink; worktree audit is no longer unbounded, concurrent failure-corpus rotation cannot lose appends, and worker terminal telemetry no longer masquerades as an accepted result.
- Unified process supervision and durable orchestration on one logical-agent identity, pinned initial tmux workers and exact-session resumes to the same managed lane, and made resume prefer the persisted session file while rejecting divergent lane context.
- Separated untrusted worker claims from host-fenced durable worker results, removed parallel result adapters, and made session, goal, status, telemetry, and review projections use the claim contract without implying worker self-report is accepted task truth.
- Unified capability envelopes, profile grants, lane construction, runtime gates, research policy, and worker execution on one canonical capability vocabulary; equivalent grants such as `worktree.read` and `tests.execute` now survive through execution instead of failing a second translated gate.
- Consolidated foreground envelopes, runtime gates, orchestration profile validation, and lane manifests behind one tool-capability policy catalog; active network, skill, source, verifier, and status tools no longer disappear from capability visibility while separate authorization tables drift.
- Unified goal and durable-objective acceptance/lifecycle transitions: every satisfied requirement now needs its own trusted proof, goal pause/resume/cancel/complete reconciles already-loaded worker execution without defeating lazy UAC, terminal objectives cancel residual attempts with explicit reasons, and worker terminal publication has one idempotent path.
- Consolidated goal requirements, foreground task steps, and delegated DAG work behind one identity-based read model; task steps now persist explicit requirement links, legacy text inference has one conservative fallback, and worker dispatch synchronizes durable objective acceptance criteria without treating worker self-report as proof.
- Consolidated versioned session snapshot persistence, validation, defensive cloning, list reads, latest reads, and branch-ancestry fallback behind one typed codec shared by goal, task, evidence, learning/audit, lane, and worker state; live accessors and review acknowledgements now read one active branch while diagnostics retain explicit whole-session history, and domain validators share explicit plain-record and general record-object guards.
- Consolidated worker admission, profile/verifier resolution, capability checks, durable attempt preparation, and resumed lane-id allocation so immediate, queued, recovered, and scheduler-revalidated dispatches share one policy contract, durable tasks are the sole identity source, and a lifecycle instantiated before late durable writes cannot reuse an existing lane id.
- Unified managed-worker identity across dispatch, goal binding, persistence, reload recovery, and terminal reporting; running tmux lanes now restore under the same durable id instead of degrading into indeterminate bindings after `/reload`.
- Persisted per-check compaction verification score ranges across retry fallback and surfaced them in session analytics and `/usage` diagnostics.
- Made foreground prompt preparation transactional: routing events stay balanced, failed extension preflight retains pending `nextTurn` context, queued messages cannot reset active-turn cost accounting, and pre-start execution failures release early-painted message identities.
- Consolidated terminal foreground response handling behind one recovery coordinator with deterministic transient retry, quota failover, retry closeout, compaction, and queued-continuation ordering.
- Consolidated manual and automatic compaction detection, execution, retry, cancellation, persistence, and extension notification behind one controller with a shared result-application path and provider-neutral policy types.
- Consolidated foreground model tool-protocol selection, probing, calibration, circuit breaking, repair teaching, and turn-local telemetry into one controller shared by session call sites.
- Made execution policy a mandatory durable pre-lease gate: approvals and owner notifications now replay, approval never grants authority without a newly compiled grant, paused objectives cannot start or resume work, and workers bind their grant before entering leased/running state.
- Split goal auto-continuation, autonomous research, model-fitness probing, and shared lane-model resolution into single-owner controllers, leaving the background facade responsible only for composition and the separate managed-lane bridge.
- Moved durable worker scheduling, execution, recovery, verification, and terminal notification behind one controller; capacity-bound workers now queue consistently across providers, owner-pinned verifier profiles run automatically before acceptance and retry event-driven recovery after temporary admission failures, and dead Pi workers resume the exact persisted session and logical-agent identity with checkpoint/resource handoff.
- Consolidated worker profile resolution, risk classification, capability grants, execution budgets, lifecycle state, structured-action enforcement, and terminal notifications behind single-owner contracts; removed delegate/settings authority overrides, made undelivered in-process terminal handoffs resume-safe, and enforced trusted acceptance evidence before task/objective completion.
- Made out-of-process managed workers emit the same bounded event-driven terminal handoff as in-process delegates, taught models to retrieve results once after that handoff instead of polling, and let unprofiled background lanes use the selected model's declared or provider-agnostic reasoning default.
- Unified foreground startup, background-lane defaults, and isolated-completion clamping through the shared provider-neutral model capability resolver.
- Made foreground and isolated worker tool routing share the same calibrated text-protocol variant instead of silently forcing subagents onto the default dialect.
- Classified process-matrix/tmux children as workers from their parent identity, and applied worker/resource-profile UAC before built-in/override tool construction and live extension import, so withheld tools invoke no runtime factory and denied extensions load no module code.

## [0.81.39] - 2026-07-20

### Added

- New `processMatrix` system (on by default, `processMatrix.enabled: false` is the explicit opt-out): a durable, restart-surviving master/worker process matrix under `state/process-matrix/`. A worker launched with a known parent (`PI_PARENT_PID`/`--parent-pid`, threaded automatically through `tmux_agent_manager`'s `fire_task`) self-registers and watches its parent's liveness; on parent death it winds down gracefully (never silently), leaving a resumable payload, and either gets adopted by a new master or self-exits after a bounded grace window. A master's startup scan for orphaned workers ALWAYS asks the owner before touching anything (adopt, cooperative cleanup, or leave untouched) and is report-only with zero writes/kills when non-interactive — see `docs/process-matrix.md`.
- Closed the tool-selection observe/promote loop: durable per-(model, intent) agreement tracking, an evidence-gated compact prompt hint (activates only past utility/margin/min-evidence thresholds, deactivates when its tracked efficacy drops, never auto-executes), a `getReport()` surface joined into `/toolhealth`, and `PI_TOOL_SELECTION_OBSERVE` / `PI_TOOL_SELECTION_HINTS` kill switches.
- Goal evidence now carries a validated ref and a `verified` flag: `add_evidence` checks a "tool" ref against real session tool-call records or a "file" ref against the filesystem, and marking a goal `complete` requires at least one satisfied requirement backed by verified or user-confirmed evidence (configurable, default on).
- Delegated workers whose mutation needs a human look are now observable and sticky in `delegate_status` instead of purely advisory text: an unreviewed-mutation notice persists until the parent explicitly acknowledges it via a new `delegate_status` review action. Enforcement stays visibility-only, never write-blocking.
- Goals now carry a durable, per-goal cumulative continuation budget (turns, active wall-clock, and attributed USD spend) across every continuation invocation for the goal's lifetime, with a conservative default ceiling and a visible `goal_budget_exhausted` stop reason.
- A turn-boundary advisory nudge fires when the task_steps workflow contract (one in_progress step, no stale open steps) is violated for 3 consecutive turns — a one-line harness note, never a blocking gate.
- The goal continuation snapshot and prompt now include a read-only summary of open task_steps steps, and satisfying or completing a goal requirement nudges when an open task step appears to reference it — read-only cross-visibility between the goal and task-steps systems, with no shared state machine.
- A canonical, typed path module (`agent-paths.ts`) is now the single source of truth for everything machine-managed under the agent directory (`state/`, `cache/`, `work/`, runtimes, models, sessions, npm/git installs); an idempotent startup migration relocates the confirmed root-level straggler (`trust.json`) into `state/`.
- tmux workers launched via `tmux_agent_manager` are now PERSISTENT and talkable mid-run: a new `send_followup` action re-injects a fresh prompt into an already-live job's pane using a unique per-turn marker pair and re-arms the pane's completion watcher, reusing the existing event-driven per-turn handoff; session start now also reconciles tmux sessions against this session's own job records (an orphaned session is marked informational, never killed; a live session with a pending turn has its watcher re-armed); a new `dismiss` action stops tracking a job without killing its tmux session, and an idle worker (no turn currently dispatched) no longer holds a reload-quiesce registration.
- tmux worker dispatch is now approval-gated by a persisted, per-session/per-goal STANDING GRANT: `grant_dispatch` (interactively confirmed, or opt-in via `--allow-tmux-dispatch` with no UI) authorizes repeated unattended `fire_task`/`send_followup` launches within a budget (`maxLaunches`, optional expiry, goal/tool/path scope); `revoke_grant` ends it early; a launch with no covering grant and no interactive approval is refused, never silent. A grant-covered `pi` child is launched with a restricted profile (`--tools`/`--resource-profile` or `--no-extensions --no-skills`, plus a scoped `--append-system-prompt` naming the grant and its hard stops) pushed into the child's own launch configuration; non-`pi` agents are bounded at the launch layer only. Self-reported worker usage is ingested as an advisory, idempotent claim (`reportSpawnedUsage`), never a hard cross-process cap.
- A new host bridge (`pi.reportManagedLane`) makes out-of-process tmux workers first-class `tmux-worker` lanes: visible in `/autonomy` and `delegate_status` alongside in-process worker lanes, reload-quiesce-registered only while a turn is dispatching, and left as a bounded claim snapshot on terminal. A tmux worker's self-reported changed files are re-checked against the session's active write scope and flagged for parent review when out of scope (reusing the existing in-process worker review path verbatim); in-process worker lanes are now goalId-tagged, matching the existing research-lane tagging.
- Goals gain a `worker` evidence kind (verified against the worker's lane/result and its review flag, so an unreviewed worker completion can never ungate goal completion) and a structural `dispatch_worker` action that records a requirement↔lane binding without silently satisfying the requirement; the binding and worker-evidence verification are wired live (dispatches a real in-process worker lane today — tmux-worker selection from this tool is not yet available).
- The goal loop no longer stalls out or races a redundant re-dispatch when a worker is actively handling an open requirement: a new `waiting` continuation state (reason `worker_in_flight`) pauses the loop without submitting a hollow pass and stops the idle scheduler from re-dispatching, resuming automatically once the worker's lane goes terminal; per-goal worker/subagent spend is now tracked (`continuationWorkerSpendUsd`, summed from the goal's own lanes) against a new conservative default ceiling, accurate for in-process lanes today and advisory for tmux workers pending a documented follow-up.
- The goal tool's `dispatch_worker` action can now target a persistent tmux worker instead of the default in-process one (`dispatchTarget: "tmux"`, opt-in per call): core structurally invokes the tmux extension's `fire_task` itself — the same tool call the model would make — single-agent and 1:1 to the requirement's bound lane, still gated by the existing standing-grant authorization; an unattended dispatch with no covering grant is honestly refused (`dispatchSkipReason: "no_standing_grant"`), never silently launched and never a fabricated lane id. Correlating the extension's own dispatch report back to the internal lane id is a new deterministic keyed lookup (`BackgroundLaneController.resolveManagedLaneId`), not a racy lane-list diff.
- New `worktreeSync` system (on by default, `worktreeSync.enabled: false` is the explicit opt-out): a hard-gated, worktree-per-lane parallel-work workflow (`worktree_sync` tool: `status`/`create_lane`/`sync`/`continue`/`abort_sync`/`land`/`release_lane`/`reconcile`) where every writing agent works in its own git worktree/branch and integration is always rebase-onto-main + fast-forward, serialized under one integration lock with a configurable land-time gate command verified at the exact landing tip — see `docs/worktree-sync.md`. Wired into the goal loop and tmux dispatch: two new continuation reason codes (`lane_sync_required`/`lane_sync_conflict`) give the goal loop a deterministic directive when a bound worker's lane is stale or has a rebase stopped on conflicts; the goal runtime snapshot can surface per-requirement worktree lane state; a goal-bound tmux dispatch (`dispatchTarget: "tmux"`) creates the lane FIRST when worktree-sync is enabled, aborting cleanly before any tmux launch on a creation refusal (`dispatchSkipReason: "worktree_create_failed"`), and launches the worker with `--worktree-lane <key>` plus one extra lane-doctrine system-prompt clause; `LaneRecord` gains an optional `worktreeLaneKey` so `/autonomy` and the goal snapshot can render the pairing.
- A new session-role identity (`core/session-role.ts`) gives a worker session (lane-bound or `PI_SESSION_ROLE=worker`) a strict UAC ceiling: `goal`/`delegate`/`delegate_status`/`improvement_loop`/`extensionify`/`skillify`/`run_toolkit_script`/`model_fitness`/`tmux_agent_manager`/`context_scout`/`python` can never activate, wins over any allow-list or resource-profile grant; `worktree_sync`'s `create_lane`/`release_lane`/`reconcile` are refused and `land` is deny-by-default (new `worktreeSync.workerLand` setting) for a worker, which may only ever target its own bound lane; `land`/`release_lane` now refuse `lane_owner_conflict` when a different, still-alive session owns the target lane; a lane-bound session's `edit`/`write` targets are checked (symlink-safely) against the lane's own worktree root, refusing `path_outside_lane`; and every scattered on-disk store plus `SettingsManager`'s write path go read-only for a worker session, so no worker ever touches `~/.pi/agent/state` or `settings.json` — see `docs/worktree-sync.md`'s "Identity, UAC, and zero footprint" section.
- Lane-worker eligibility now rides the model-capability system end to end (`evaluateLaneWorkerRefusal` in `core/model-capability.ts`): a worktree-sync lane worker requires capability class `full`, a declared registry context window, an advertised native tool-call path (`Model.textToolCallProtocol` unset/false), and no graded `/toolprobe` demotion to text-protocol/none — a goal→tmux dispatch refuses early as a best-effort check (`dispatchSkipReason: "worker_capability_insufficient"`, zero lane/pane side effect) and the dispatched child session refuses authoritatively at its own startup with a deterministic, greppable log line, regardless of how it became lane-bound. The lean capability class also now blocks the full orchestration surface (`goal`, `worktree_sync`, `improvement_loop`, `extensionify`, `skillify`, `model_fitness`, `context_scout`, `tmux_agent_manager`) in addition to `delegate`/`context_audit` — see `docs/worktree-sync.md`'s "Capability adaptation" section.

- The Windows `bash` contract now routes through three tiers instead of one: the existing simple-command PowerShell floor (unchanged), a new bundled Python shell engine (uv-provisioned Python 3.13) for pipelines, redirection, chaining, quoting/expansion/globs, and the coreutils vocabulary, and named fail-closed refusals for constructs outside that grammar (job control, process substitution, arithmetic expansion, heredocs, nested shells, control-flow, `eval`/`source`/similar, and more) — see `docs/windows.md`. State-mutating commands (`cd`, `export`, `unset`) always route to the engine, the sole mutator; working directory and environment persist across calls and across tiers, with subshells (`( … )`) isolated and brace groups (`{ …; }`) sharing state like bash. A new `windowsShell.pythonEngine` setting (default `true`) is the hard kill switch: explicit `false` restores the prior PowerShell-only, simple-command-only contract verbatim. When the Python runtime cannot be resolved, the PowerShell floor keeps working and engine-only commands return a named, actionable degradation error instead of a silent wrong-approximation downgrade. Proven by a new engine conformance suite (Linux + Windows CI), a Linux-only differential oracle comparing engine output against real `bash -c` across the supported grammar, and Windows cross-tier integration tests exercising state handoff between the PowerShell and engine tiers.

### Changed

- Self-adaptation (native reflection + learning policy) is now on by default for a fresh session in every autonomy mode (off/safe/balanced/full) — evidence-gated (confidence threshold + `ObservationStore`). The preset lattice is monotonic: increasing autonomy no longer silently disables self-adaptation. All kill switches (`PI_NATIVE_REFLECTION=0`, `learningPolicy.enabled=false`, `AutoLearnSettings.enabled=false`) still disable it in every mode. The raw autonomy-prompt standing-grant authority block stays gated on `autonomy.mode` (`"off"` default unchanged).
- The `delegate` tool's description and prompt guidelines now vary by wiring mode: an async start/poll contract when worker delegation is asynchronous, the synchronous contract otherwise.

### Fixed

- Bundled Python shell-engine source now keeps `BuiltinContext.stderr` optional for direct builtin callers, and its conformance/oracle tests parse the terminal control frame from stderr, matching the runtime transport.
- Tmux dispatch grants now authorize and charge every launched child process; persistent follow-ups reserve their turn before pane injection to prevent duplicate external prompts after a crash. Process-matrix workers verify a fresh parent-session heartbeat alongside PID liveness, and worktree landing advances the named main ref with compare-and-swap recovery stages rather than merging whichever branch is checked out.
- `/goal start` no longer double-fires its continuation loop: a single mutex now serializes the idle-driven and manual goal-continuation paths, eliminating both the "Agent is already processing" warning and an unhandled rejection that previously fired on effectively every `/goal start` (the idle auto-continue timer's default 0ms delay meant the manual and idle paths raced on nearly every invocation); the command layer gained try/catch parity and status-line handling for the new skip outcomes.
- Task/goal state resolution (and the whole goal runtime snapshot: goal state, evidence, worker results, learning decisions) now walks the active session branch's own ancestry instead of scanning every branch's flat entry list — fork/branch-switch no longer leaks another branch's goal or task-steps state.
- `task_steps`'s `add` action dedupes a retried add of an already-open duplicate step instead of creating a second copy (a legitimate re-add of previously completed work still creates a new step); a completed step with no evidence attached now surfaces a reminder in both the tool response and the injected per-turn context; and a `set`/`update` call that silently demotes another in_progress step to pending now names it in the response.
- Goal stall detection now keys on satisfied-requirement and verified-evidence counts instead of raw event count, so hollow goal-tool calls that append events without making real progress can no longer defeat the stall guard.
- Session disposal now durably persists canceled/in-flight worker lane records and a bounded worker result (including changed files) before the dispose cutoff, instead of losing them to an in-memory-only completion; queued (not-yet-started) workers are now visible to the reload quiesce gate from the moment they're enqueued, not just once running.
- All goal-state free text rendered in the continuation prompt (the user goal, requirement text, blocked reason, evidence summaries, and the open task-steps summary) is now wrapped as untrusted data, matching the existing worker-result boundary — closing a prompt-injection vector reachable via a model's own `add_requirement`/`block_goal` calls.
- The injected `task_steps_context` block is now GC-managed like `memory_context`, ending unbounded per-turn context growth for sessions with an open checklist; fixed a latent default drift between two independently hand-kept copies of the context-GC defaults (one was missing the `run_toolkit_script` tool, the other was missing `python`/`powershell`) by deriving both from one canonical source.
- Runaway-loop stops and repeated tool-validation-failure escalations are no longer silent: both log a session entry; runaway stops surface a user-visible warning; validation escalation feeds the model router's existing cheap-route escalation gate. Isolated/reflection child loops inherit the runaway handler when on the foreground model.
- Atomic, locked writes for model-adaptation, tool-recovery event-log rotation, the learning observation store, and skill-curator usage tracking (new shared `src/core/util/atomic-file.ts`); standing model-adaptation rules now also retire early once evidence shows they stopped reducing recurrence (in addition to the 30-day bound).
- Reflection's automatic skill promotion runs the same `skill_audit` overlap check the `skillify` tool enforces; a near-duplicate draft is held as a consolidation proposal (learning-audit trail) instead of written.
- Background/research/worker/reflection/fitness isolated-completion lanes carry a stable namespaced synthetic cache-affinity key (never the real session id), so provider session-affinity / `prompt_cache_key` caching actually hits on repeat lane calls.
- The session cost guard folds this turn's background/spawned spend (per-turn baseline delta) into the same ceiling as the foreground projection (default action stays "warn"; per-lane caps untouched).
- Spawned-usage accounting is idempotent: every `addSpawnedUsage` call site supplies a stable, content-derived `reportId`; the model-fitness probe threads its tool-call id as the idempotency token (separate deliberate runs count; retries dedupe).
- `IsolatedCompletionOptions.cacheRetention` is required at the type level (silent "none" default removed).
- Ollama/Transformers/prism readiness caching keyed per (server, model) instead of per-server — a second model on a confirmed server is never waved past the installed/residency checks. `LocalRuntimeController.reconcile()`/`dispose()` stops pi-spawned runtimes dropped from the live configuration on reload (detected-only servers never touched), wired into the reload path.
- Compaction's summarizer honors managed-local readiness/residency for auto and manual `/compact`; also fixed a latent manual-`/compact` bug that dropped the resolved fallback model/failure and could pair a model with the wrong credentials.
- Compaction pre-check accounts for this turn's own context-GC savings (read-only GC projection; suppression-only — near-full hard trigger unaffected).
- Reload gate honors all in-flight work via a unified in-process quiesce registry (`reload-blockers.ts`): foreground streaming/compaction, research/worker/model-fitness lanes, context-scout runs, and isolated completions (registered at their single choke point).
- Context-policy prompt-enforcement defaults now derive from the live context-GC settings (explicit values still win); corrected the stale GC-defaults doc comment (12/2500 → 8/1200).
- Documented and test-pinned the system-prompt cache-stability invariant (one provider-cached block, rebuilt only on tool-surface change, day-granularity date).
- A text-protocol ("phone") model that fails to parse the same tool-call signature 3 times in a row is now demoted to native fallback for real: the persisted tool-probe verdict itself is now cleared (was: only the cached protocol was cleared, leaving the phone flag on), which previously caused every subsequent turn to re-run up to 8 inline calibration completions before the user's prompt and, on failure, throw the user's turn away entirely. Ensuring the text protocol for the active model no longer performs blocking inline calibration or throws out of the prompt path under any circumstance; calibration now only ever runs off the hot path, via an explicit `/toolprobe` or the new evidence-gated auto-probe below.
- A model whose native tool calls keep failing argument validation is now automatically probed and, on graded evidence, escalated: a local/managed model gets an evidence-gated auto-probe (native is tried first; the model is only routed to the text protocol if native genuinely has no working path), and a cloud model escalates to a more capable router tier. This replaces a validation-failure escalation path that previously reused the mutation-blast-radius escape hatch and so treated a read-only tool's repeated validation failures as a no-op.
- The model router's tier resolution and configured-model lookup now honor a persisted "no working tool-call path" probe verdict for local/managed models: a medium-tier turn falls back to the expensive tier (or the model is skipped) instead of routing to a model already proven unable to call tools.
- A buffered cheap-tier routed turn that throws now rolls the live in-memory session state back to match what was actually persisted, instead of leaving never-flushed messages permanently stranded in memory.
- Native tool-call probe trials and text-protocol calibration completions now count toward the turn-scoped cost guard and daily usage totals (were previously untracked — up to ~10 free completions on a model's first probe).
- A text-protocol model that repeatedly emits unparseable prose instead of a tool call now receives an in-loop corrective reminder (throttled after the first firing), closing a gap where the existing runaway/stall backstop only trips on repeated *parsed* tool-call signatures.
- A dead tmux session whose job never reached a terminal state now releases its bound managed lane (one report per non-terminal agent, `reasonCode: "tmux_session_orphaned"`) during session-start reconcile, so a goal bound to it stops waiting on a worker that can no longer report back; nothing is killed, only the lane record is released.
- A goal waiting on a dispatched worker now escalates to the owner (`action: "ask-user"`, reason `worker_wait_timeout`) after a bounded max-wait (default 60 minutes) instead of waiting indefinitely, when the worker is alive but hung past its deadline; every pre-existing caller that omits the new optional wait-clock arguments behaves byte-identically (waits indefinitely, as before).
- A managed (tmux) worker's terminal usage claim now attributes to its lane's advisory `costUsd`, closing the previously-documented undercount in a goal's `continuationWorkerSpendUsd` for tmux-worker spend.
- A goal requirement bound to a worker lane that vanished after `/reload` (a genuinely-running managed lane is never snapshotted at dispatch time) is no longer at risk of a duplicate re-dispatch: `dispatch_worker` now refuses re-dispatch when the bound lane's liveness/outcome cannot be determined (`bound_lane_indeterminate`) or is still live (`requirement_already_bound`), preserving the existing binding unchanged; a bound lane with a confirmed terminal outcome still allows a legitimate retry.
- Hardened worktree synchronization with token-bound lock ownership, lifecycle serialization, exact gated-tip landing, crash-recovery reconciliation, cumulative overlap checks, and typed lane Git/check actions; hard lane workers no longer expose unrestricted `bash`.
- Fixed concurrent atomic writes by giving each invocation an exclusive same-directory temporary file and cleaning up only its own temporary path.

### Performance

- Memoized per-message context-audit and token-estimate work within a session (object-identity keyed), byte-identical vs full recompute across compaction and branch-switch boundaries — the full-history rescan no longer reruns on every tool-call round trip.
- Precompiled and cached minimatch patterns for resource-profile filtering (~8% of startup CPU; refired on every reload/profile switch before).
- Extension TS transforms cached in a durable `agentDir/cache/jiti-transforms` directory (jiti's content-hash fsCache made explicit; hot-reload module isolation preserved).
- Lazy highlight.js: `lib/core` + register-on-first-use (~190 eager grammar registrations removed from startup), identical output/alias resolution.
- Cached resolved `fd`/`rg` system-PATH locations across runs (no `spawnSync` probe per launch; staleness re-probes).

### Tests

- Pinned the transform-before-cost-guard pipeline-order invariant (regression test fails under a simulated inverted order).
- Added a permanent regression guard proving goal/task state resolution survives compaction whose cut point lands past the latest snapshot, in-memory and after a session-file reload (investigated as a suspected bug; the repro passed, so no source change was needed).

## [0.81.38] - 2026-07-16

### Changed

- Updated repository development and CI to Node.js 24 and moved GitHub workflows to Node 24-based action releases while retaining Node.js 22.19 as the published runtime minimum.

### Fixed

- Fixed Windows shell routing for native drive and UNC paths, extension live reloads, managed Ollama executable discovery, and canonical delegated-worker path reports.
- Fixed Windows full-path find/FFF search parity, cross-platform watcher/runtime test behavior, and SQLite handle cleanup when runtime-index schema validation fails.
- Fixed the Windows Bash-like router to prefer a usable PowerShell 7 executable, preserve `echo -n`, no-match `grep`, `rm -f`, `mkdir -p`, directory-copy, and hidden-listing semantics, and reject unquoted pathname, brace, and home expansion instead of passing it literally.

## [0.81.37] - 2026-07-16

### Fixed

- Updated release validation for the native Python/task-step surface, update preflight, platform-shell output, and prompt-cost growth, and made the Windows binary smoke test prove the stable Bash-like contract executes through PowerShell.

## [0.81.36] - 2026-07-16

### Added

- Added native session-persisted task steps with the built-in `task_steps` tool and `/task`/`/steps` commands, replacing the machine-local checklist extension.
- Added one stable `bash` tool contract on every platform, with deterministic finite-grammar conversion to UTF-8 PowerShell execution on Windows, fail-closed handling for unsupported shell constructs, and legacy `powershell` tool-name remapping.
- Added a native uv-managed `python` tool with pinned/checksummed runtime provisioning, direct cross-platform execution, bounded process-tree deadlines, streamed output artifacts, doctor/update/postinstall integration, and native UAC/profile registration.

### Changed

- Agent, interactive, and RPC shell calls now have a 120-second wall-clock default, including continuously producing commands; agent-tool overrides cap at one hour. Removed the unbounded synchronous full-file/recursive optimizer path and added scoped paths-first search guidance.

### Fixed

- Made the platform-limited FFF native binding optional so clean Android/Termux installs use the supported fallback instead of failing with `EBADPLATFORM`.
- Listed the native `python` and `task_steps` surfaces in CLI help for clean-install discovery.
- Updated `undici` to 8.5.0 to resolve current TLS, WebSocket, header, cache, and connection-reuse advisories.

## [0.81.35] - 2026-07-15

## [0.81.34] - 2026-07-15

## [0.81.33] - 2026-07-15

### Added

- Added a profile-selectable bundled tmux agent manager with portable team templates, event-driven terminal result signals, exactly-once parent wake handoffs, startup reconciliation, and packaged binary resources.
- Added a leased multi-tenant transient workspace under `~/.pi/agent/work/<category>/<tenant>/<run-id>` with ownership manifests and bounded age, count, byte, scan, and depth retention.
- Added native Windows x64 and ARM64 build, test, smoke, and release gates.

### Fixed

- Added in-settings profile model editing, including returning an existing profile to session/default-model inheritance and immediate transactional reload for active profiles.
- Made profile extension choices use collision-safe path identities and description/folder labels, so separate folder-based `index.ts` extensions can be enabled independently.
- Made goal ledgers user-recoverable with manual status, resume, reopen, complete, close, and override controls while retaining evidence-gated agent completion.
- Removed redundant approval waits and unbounded repair loops from the bundled skill/extension authoring and harness-learning workflows.
- Made delegated worker terminal events queue bounded, serialized parent wake handoffs without injecting untrusted worker output, status polling, or debounce-timer races.
- Made child-process waits settle when attached after a fast child already emitted its terminal event, and routed exec cancellation through event-driven process-tree escalation.
- Removed Unix-only temporary-path, shell, editor, clipboard, package, and runtime assumptions from Windows execution paths.

## [0.81.32] - 2026-07-13

### Fixed

- Fixed published installs to include dependencies nested under internal workspace packages, including the OpenAI SDK required by Fugu Responses models.

## [0.81.31] - 2026-07-13

## [0.81.30] - 2026-07-13

### Added

- Added a bundled harness self-adaptation skill with evidence, layer-selection, measurement, retention, rollback, and authority gates for compounding Pi work without gratuitous self-modification.
- Added per-delegation, lane-profile-gated read-only memory retrieval for isolated workers while keeping private memory files and every memory mutation unavailable.
- Added explicit queued/running worker status and lane-specific completion notifications without injecting late worker output into the active foreground transcript.

### Fixed

- Bounded long-session telemetry by bytes with cumulative per-session summaries, made recovery-log worker replacement batch-safe, added active-session-safe age/count/byte retention for context payload stores, replaced repeated full-session footer, context, analytics, and background-lane scans with incremental or indexed reads, and invalidated provider request-prefix caches immediately after compaction.
- Avoided full copies of large context strings during curation, artifact hashing, context GC, RPC framing, local-runtime progress parsing, and HTML branch reconstruction.
- Made managed local-model readiness verify the configured Ollama model after startup, exit cleanly when it is missing, and prevent prefix warming from silently falling back to another model.
- Kept startup running when an extension fails to load, while reporting the failure, restoring prior provider and flag state, and discarding partial event registrations.
- Preserved bounded read-only delegated worker output when a worker returns plain text, custom JSON, or reaches its output limit instead of failing it as unparseable.
- Made worker delegation follow the selected lane model's provider and tool protocol, and prevented multiple queued local workers from deadlocking.
- Restored OAuth rejection recovery for Codex subscription models by matching the provider ID instead of the Responses API ID.

## [0.81.29] - 2026-07-10

### Fixed

- Updated capability, fitness, and regression coverage for the artifact and delegation companion tools and plain-text worker results.

## [0.81.28] - 2026-07-10

### Fixed

- Added bounded recovery for locally unexpired OAuth credentials rejected with an initial Codex 401, including locked reload/refresh and rotated-token persistence.

- Made delegated workers session-owned background jobs with non-blocking starts, explicit local-foreground queuing, bounded `delegate_status` retrieval, and safe read-only plain-text result handling.

## [0.81.27] - 2026-07-10

### Added

- Added first-class `max` and reinforced-orchestration `ultra` thinking-level support across CLI, settings, profiles, skills, custom model metadata, selectors, themes, and cost-guard downgrades.

### Changed

- Bounded delegation context by packing stale `delegate` results while retaining retrievable originals, and made goal continuation prioritize and structurally fence the newest worker snapshots.
- Enabled bounded delegation by default for capability-eligible models while preserving explicit disable, profile/tool, concurrency, cost, time, write-scope, and validation gates; Ultra now strengthens proactive delegation without owning the capability.
- Enabled local safe-auto memory retrieval and budget-gated prompt inclusion by default while retaining explicit disable and compact-model caps.
- Applied delegation and research capability gates to each resolved lane model, so configured lane models neither inherit nor bypass the foreground model's capacity verdict.
- Upgraded profile-shipped research and worker lanes to isolated, turn-bounded child tool loops with exact glob-expanded UAC surfaces, read/write path enforcement, multi-turn usage accounting, direct-write reporting, relative profile references, and fail-closed diagnostics for opaque tool grants.
- Rebuilt routed-turn prompts for effective thinking changes, including same-model tier overrides, and made the cost guard account for the actual routed model, full provider-bound prompt/tool surface, and model-declared long-context pricing while projecting output from the session reserve instead of a model's absolute output ceiling; opt-in downgrades affect the imminent request without mutating routed/profile/session thinking, and the exported default matches the runtime's warning-only `$2.50` default. The USD warning guard remains independent from the `0.7` compaction trigger and does not impose an artificial ceiling on GPT-5.6's public context window.

### Fixed

- Fixed clean-checkout TypeScript resolution for the exported `@caupulican/pi-agent-core/paths` subpath before package builds exist.
- Restored default stream-stall bounds after partial settings spreads so HTTP timeout clamping cannot create `NaN` watchdog delays.
- Made `contextPolicy.memory.enabled: false` authoritative for both retrieval paths; fail-closed legacy/opaque memory query egress unless a provider is explicitly local or external egress is explicitly enabled; centrally source-fenced all legacy recall output; blocked common raw tokens, bearer credentials, and signed URLs; synchronized live-loaded/unloaded extension memory providers; and exposed the external-egress consent in `/settings`.
- Synchronized profile UAC across SDK, startup, editing, and reload: SDK sessions retain the shared goal/delegation/toolkit defaults and accept complete one-shot situations; extension-provided profile models resolve on startup; reusable situations preserve soul and complete router settings; relative references and explicit empty selections apply consistently; and failed generations roll back settings, providers, memory, tools, model/thinking, discovery state, and diagnostics together.
- Made profile edits, selection changes, deletion, and configuration restore transactional across runtime validation and persistent storage; backups now round-trip canonical multi-profile and explicit-none selections without restoring external-root trust.
- Removed the duplicate CURRENT/TODAY/SUBAGENTS cost summary from the autonomy footer line; the compact footer stats remain authoritative and `/cost` retains the detailed report.
- Restored the proactive over-ceiling cost-guard warning in that authoritative footer line without duplicating session totals.
- Restored the `(sub)` marker for subscription-equivalent current cost and stopped applying USD cost-guard projections to ChatGPT subscription usage.
- Counted cached-read and cache-write tokens in adaptive prefill profiling, rejected effectively deferred response headers as a false prefill boundary, and made the profiler terminate cleanly when an inner provider stream rejects or ends without a terminal event.
- Kept the stream-stall watchdog authoritative for short HTTP idle settings by constraining every watchdog phase and its adaptive ceiling below each nonzero transport timeout; disabling the HTTP timeout still leaves adaptive watchdog protection active.
- Kept research evidence provenance valid when `maxSources` is one by reserving the synthesis source cited by generated findings.
- Re-clamped thinking, resynchronized the capability-filtered tool surface, and rebuilt the base prompt on every model set/cycle path so model switches cannot expose stale tools or orchestration guidance.
- Preserved generated models' default thinking level and thinking-level map in faux-provider registrations so GPT-5.6 and Ultra harness runs exercise the production capability contract.

## [0.81.26] - 2026-07-09

### Fixed
- Fixed dynamically registered provider models to honor configured `modelOverrides`.

## [0.81.25] - 2026-07-09

### Fixed
- Added session-level compaction gate failure and deterministic gap-fill telemetry to make nonzero gate-failure rates visible in stats and `/session` output.

## [0.81.24] - 2026-07-09

### Fixed
- Fixed cost displays to use one CURRENT/TODAY/SUBAGENTS summary across the footer and autonomy cost line, with subagent cost included in CURRENT and local-midnight TODAY rollover.

## [0.81.23] - 2026-07-09

### Added
- Added background worker-thread tool-recovery logging with bounded queue/drop counters surfaced in `/toolhealth`.

### Changed
- Made tool-argument repair a built-in path by removing the `toolRepair.repair` setting; `toolRepair.logging` now controls only recovery log writes.

## [0.81.22] - 2026-07-09

### Fixed
- Fixed model-router judge handling so static decisions bypass the judge, judge-unavailable fallback preserves the baseline reason, and nested shell execution forms escalate correctly.
- Fixed auto-compaction failure and abort paths to preserve queued steering-message processing.
- Fixed resumed long sessions to populate prompt input recall immediately while keeping transcript rendering lazy.

## [0.81.21] - 2026-07-08

### Added
- Added a local cold-start live acceptance gate for stock-stall Ollama tool-call turns.
- Added runtime residency adapters for Ollama, pi-managed Transformers, and advisory external serves.

### Changed
- Made the pi-owned Ollama model store canonical, with `/models import` adopting user-store models by hardlink/copy instead of re-download.
- Routed local model activation through the residency arbiter before serving or warming local models.

### Fixed
- Fixed local-class adaptive stall handling to raise cold connect bounds from measured prefill/load timing while keeping remote no-profile connect bounds unchanged.
- Fixed local context sizing to derive GGUF metadata by architecture key/suffix instead of architecture name lists.
- Fixed pi-managed Transformers venv setup to validate pip and interpreter coherence, repair with `ensurepip`, recreate stale venvs, and surface venv package install guidance.

## [0.81.20] - 2026-07-08

### Fixed
- Fixed pi-managed Transformers setup to resolve the environment Python before creating its venv and to repair existing incomplete venvs before Hugging Face model downloads.

## [0.81.19] - 2026-07-08

### Fixed
- Fixed post-compaction token measurement to keep passive estimates idempotent and use the same max real-usage/estimate basis as the auto-compaction trigger.

## [0.81.18] - 2026-07-08

### Added
- Added an exact Bonsai-4B GGUF Q1_0 curated local-model suggestion for one-step managed Ollama setup and curator-role probing.

### Fixed
- Excluded local-only planning docs from npm package file selection even when they exist in a local checkout.

## [0.81.17] - 2026-07-08

### Added
- Added host-local model perf profiles that record streamed prefill/decode rates and adapt quiet stall bounds from measured throughput.
- Added local OpenAI-compatible prefix warming and longer managed Ollama residency defaults for local-model startup.
- Added local-model context sizing that derives `num_ctx` from host RAM and model metadata, then creates a sized Ollama Modelfile alias for managed installs.
- Added a runtime residency arbiter core for fitting, evicting, refusing, and reserving local model loads across runtime adapters.
- Added local acceptance/bench perf-profile hydration so live protocol checks and opt-in local benches feed adaptive stall bounds.

### Fixed
- Documented every tool-repair registry mode in the bundled repair catalogue and covered the registry/docs link with tests.

## [0.81.16] - 2026-07-08

### Added
- Added graded `/toolprobe` native capability reporting and persistence so native verdicts require both an echo probe and a task-scale read probe, while echo-only or absent native support can calibrate the text protocol.
- Added MiniCPM5-1B to the live acceptance fleet as a full-base native tool-calling target through the pi-managed Transformers sidecar.
- Added a pi-managed Hugging Face Transformers runtime path for curated full-base local model suggestions, starting with `openbmb/MiniCPM5-1B`, using an isolated venv and pi-owned HF cache.

### Fixed
- Fixed tool probing so a real task-scale native tool call wins without requiring a separate echo-only probe, and the MiniCPM sidecar stops generation after a complete native function call.
- Documented the Ollama serving-context requirement for local OpenAI-compatible models.

## [0.81.15] - 2026-07-07

## [0.81.14] - 2026-07-07

### Fixed
- Fixed text protocol model gating so persisted probe verdicts opt in only text-protocol models after env/settings/model gates, while unflagged native models do not receive the primer.
- Documented the `propertyCaseNormalize` and `jsonObjectPropertySalvage` repair modes in the operator docs and bundled tool-repair skill.

## [0.81.13] - 2026-07-07

### Fixed
- Fixed custom model registration to preserve `textToolCallProtocol` and show it in `--list-models`.
- Fixed text tool protocol calibration failures to persist, fail fast until explicit reset, and invalidate stale calibrated protocols after repeated live parse failures.
- Added `/toolprobe` and RPC `tool_probe` to live-probe native/text-protocol tool-call support and persist host-local verdicts.

## [0.81.12] - 2026-07-07

0.81.10/0.81.11 retracted before distribution; changes are folded into this section for 0.81.12.

### Fixed
- Fixed external editor resolution so both inline and path-edit flows prefer `$VISUAL` before `$EDITOR`.
- Fixed registered extension models without token limits to receive default context and max-output limits.
- Fixed grep/find result-limit notices so exact-limit result sets are not reported as truncated.
- Fixed edit tool argument preparation to leave stringified `edits` for the shared validation repair layer.
- Added session analytics aggregation for shape-only tool argument validation telemetry.
- Added a host-keyed per-model adaptation store for repair rules, protocol calibration, and teach statistics.
- Added learned per-model tool-shape rules to system prompt assembly after repeated repair telemetry.
- Added per-model teach-efficacy aggregation for tool argument validation telemetry.
- Added per-model text tool-call protocol calibration before the first real turn.
- Added sanitized tool-validation bounce records to the local failure corpus for repair-mode discovery.
- Added tool repair health reporting, learned-rule removal, visible repaired-call markers, and repair/teach/protocol kill switches.
- Fixed delegated worker action parsing to use the shared tool-argument validation repair path.
- Documented tool repair diagnostics, controls, and replay workflow.

## [0.81.9] - 2026-07-07

## [0.81.8] - 2026-07-07

### Fixed
- Fixed manual compaction retry warnings to include verification failure details.
- Fixed auto-compaction custom-stream regression coverage to seed sessions above the real trigger threshold.
- Fixed overflow-triggered auto-compaction to apply one checkpoint before retrying the provider request even when measured tokens are below the configured threshold.
- Fixed git log filtering to preserve user arguments while applying default compact-log limits.
- Fixed fuzzy edit replacements to preserve unrelated file bytes and report diffs from the actual on-disk change.
- Fixed edit duplicate detection so exact matches are counted exactly before falling back to fuzzy ambiguity checks.
- Fixed RPC input validation so non-command JSON lines return errors without terminating the process.
- Fixed `read` tail results to return the requested content lines for newline-terminated files.
- Fixed initial CLI prompt construction to separate stdin, `@file`, and message sources with blank lines.
- Fixed worker edit actions to insert replacement text literally when it contains JavaScript `$` replacement patterns.
- Fixed cheap-tier shell tool escalation to fail closed on compound commands containing mutating segments.
- Fixed bare CLI model-id resolution to prefer the single authenticated provider and reject unresolved ambiguity.

## [0.81.7] - 2026-07-06

### Fixed
- Fixed native reflection cost deduplication to derive report IDs from a stable turn digest instead of an absent message id.
- Fixed extension `tool_call` event dispatch so a throwing handler emits diagnostics without skipping later handlers.
- Fixed settings overlay merging to recurse through nested objects while still replacing arrays.
- Fixed root-session migration to extract filenames correctly from both POSIX and Windows-style paths.
- Fixed scout truncation accounting to count assistant output tokens against the output-token cap instead of total input plus output tokens.
- Fixed reflection-engine malformed-response handling to preserve provider usage after completed calls.
- Fixed research-lane spend limits to clamp configured lane budgets to the foreground capability envelope.
- Fixed failure-corpus secret redaction for separator-bearing `sk-proj-` and `sk-ant-` API key formats.
- Fixed shared exec output decoding to preserve multibyte UTF-8 characters split across stdout/stderr chunks.
- Fixed overlapping bash execution cancellation so aborting bash cancels every running command instead of only the latest one.
- Fixed concurrent first-run managed-tool downloads to share one in-flight download per tool.
- Fixed interactive-mode cleanup leaks by sequence-guarding current-scope session loads and disposing replaced custom editors.
- Fixed the mutation-barrier regression test to wait on explicit scheduling conditions instead of timing sleeps.

## [0.81.6] - 2026-07-06

### Fixed
- Fixed interactive-mode `renderSessionContext` to serialize overlapping rebuild calls on a queue so that the newest generation wins the commit and the visible container remains intact.
- `/goal <text>` now deterministically seeds one open requirement from the goal text, so the continuation loop is drivable even when the model skips decomposition.
- Compaction retry warnings now name the summarizer selection reason and the input-size estimate, so gate failures identify the responsible model without a post-mortem.
- Fixed local-model compaction capacity checks to use measured served context-window evidence from the fitness probe instead of trusting the registered window guess, including tail-truncating local servers by requiring start and end capacity needles.
- Fixed manual `/compact` to preserve authoritative extension results, keep normal summary verification enabled, reserve deterministic checkpoints for gate-retry exhaustion, and surface provider failures.
- Fixed provider-failure corpus recording to write once per failed assistant message with the overflow-aware classification.
- Fixed startup migrations and project-trust reads to leave malformed `models.json` / `trust.json` files untouched instead of crashing startup.
- Fixed interactive mode to rebind the live extensions-changed UI refresh listener after session switches.
- Fixed extension factory and lazy-load failures to dispose partial event-bus subscriptions before retry or rollback.

## [0.81.5] - 2026-07-06

## [0.81.4] - 2026-07-06

### Added
- Added FastContext-1.0-4B and Ornith-1.0-9B to `/models` suggestions for one-step pull, probe, and role assignment; added the `scout` fitness role that writes `scout.model` and `scout.enabled`, gated on the `scout_auto` fitness exam.
- Added a bounded, redacted local provider-failure corpus plus provider-failure status counts for unknown-classification evidence gathering.

### Changed
- Compaction summarizer selection now consults the fitness doctrine (digest lane, subtractive) and the exhausted-provider registry; every fallback is visible.

### Fixed
- Fixed executor speculative retry persistence so the discarded first attempt is removed from the routed-turn session buffer before the refined retry is saved.
- Fixed the bash tool optimizer so `grep`/`rg` regex patterns fall through to the real command instead of being treated as literal substring searches.
- Fixed the bash tool `find` optimizer so symlinked directories are listed but not recursively followed outside the search tree.
- Fixed HTML session export asset injection so dollar sequences in template and vendor JavaScript are preserved exactly.
- Added the missing `/goal` command so users can start or inspect the goal ledger instead of only invoking `/goal-continue`.
- Fixed compaction summarizer selection to reject candidates whose context window cannot ingest the live span (visible `window_too_small` fallback to the session model), and to warn when an explicit `compaction.model` setting cannot ingest it.

## [0.81.3] - 2026-07-05


### Added
- Added `context_scout` and `ScoutController`, a bounded read-only repository scout with citation validity checks.
- Added FastContext scout install docs, a 10 GB reference profile, a consolidated per-tier model+thinking screen in Model Router settings, and a thinking-level picker during `/fitness` role assignment.
- Added opt-in `modelRouter.fitnessGate` routing: probed-unfit tier models are blocked subtractively, scout `auto` selection now requires passed fitness proof, and router status/settings surface the gate.
- Added provider quota failover handling: subscription usage limits halt retries and can hop once to an authenticated provider default; metered quota failures halt for explicit user choice.

### Changed
- Auto-compaction now uses the kernel closed loop and surfaces verification warnings from accepted fallback summaries.
- Router status now shows each tier's thinking level, including `thinking (inherit)`.
- Refactored executor and curation fitness gates onto the shared model-router fitness bar without changing their proof-required behavior.

## [0.81.2] - 2026-07-05


## [0.81.1] - 2026-07-05

### Added
- Phase-aware stream watchdog wiring in `AgentSession`, utilizing the new `StreamStallSettings` (`connectMs`, `activeIdleMs`, `quietIdleMs`) exposed and validated by `SettingsManager`.
- Compaction stream stalls are now fully retryable. Both manual and auto-compaction are wrapped in `_compactWithRetry`, ensuring transient stream stalls during summarization trigger retries rather than hard failures.

### Changed
- Increased `DEFAULT_HTTP_IDLE_TIMEOUT_MS` to 660s (from 120s) to support up to 10-minute quiet idles during long think phases without premature HTTP-layer kills.
## [0.81.0] - 2026-07-04

### Added
- Foreground bash commands with no explicit `timeout` are now killed after 600s of continuous
  silence (no stdout/stderr output), not by total runtime — a command that keeps producing output
  is never killed by this. Passing an explicit `timeout` disables the silence watchdog in favor of
  the wall-clock limit; backgrounded (`cmd &`) work is exempt by construction. Wires the
  `createSilenceWatchdog` primitive from `@caupulican/pi-agent-core`'s reliability kernel into the
  bash tool.
- A silently dead provider stream can no longer wedge a turn forever. Every provider stream a
  session starts is now wrapped once (at construction) with the reliability kernel's
  `withStreamIdleWatchdog`: it bounds the wait for the first event (120s connect allowance) and the
  gap between subsequent events (30s idle). On a stall it aborts the inner request and surfaces a
  retryable `stream stalled` error, which the existing auto-retry path picks up — so a hung
  connection now fails over instead of hanging. The bound is on silence, never on total runtime, so
  a stream that keeps emitting is never cut off.
- Process memory (rss, heap used, external — rounded to MB) is now surfaced as self-telemetry: the
  `/usage` command prints a "Process" section, and `getAutonomyDiagnosticSnapshot` gains a
  `processMemory` family rendered by `formatAutonomyDiagnostics`. Unlike the snapshot's other
  families, `processMemory` reflects live process state rather than recorded session activity, so it
  is always present, even when nothing else has happened yet.

### Changed
- truncate and sanitizeBinaryOutput now live in @caupulican/pi-agent-core (single canonical copy).
- convertToLlm and the custom message types (BashExecutionMessage, CustomMessage, BranchSummaryMessage, CompactionSummaryMessage) now come from @caupulican/pi-agent-core (moved out of `core/messages.ts`); coding-agent re-exports convertToLlm unchanged, so its public API is preserved.
- The tool-result-details retention helpers (`compactToolResultDetailsForRetention`, `compactRetainedDetails`, and their byte budgets) and the `normalizePath`/`resolvePath` path helpers now come from @caupulican/pi-agent-core (`message-retention` moved to the main entry, path helpers to the `/node` entry). `utils/paths.ts` re-exports `normalizePath`/`resolvePath` unchanged, so its consumers are unaffected.
- `SessionManager` no longer reads app config. Its constructor and statics (`create`, `open`, `continueRecent`, `forkFrom`, `list`) now take the agent config dir explicitly, and `listAll` takes the sessions-root dir explicitly — the kernel-promotion seam, so `SessionManager` no longer imports `config.ts`. A new host-layer `core/session-manager-factory.ts` (`createSession`, `openSession`, `continueRecentSession`, `forkSession`, `listSessions`, `listAllSessions`) is the single visible place that closes over `getAgentDir()`/`getSessionsDir()` and delegates; call sites that already hold their own agent dir (SDK, session runtime) pass it directly. Behavior is unchanged (`usesDefaultSessionDir()` now compares against the injected agent dir, identical to the previous config-derived value in the CLI).
- `SessionManager` and the session storage types (`SessionEntry`, `SessionHeader`, `SessionContext`, `SessionInfo`, `SessionTreeNode`, `CompactionEntry`, `BranchSummaryEntry`, `CustomEntry`, `CustomMessageEntry`, `LabelEntry`, `SessionInfoEntry`, `FileEntry`, `ReadonlySessionManager`, `NewSessionOptions`, `SessionListProgress`) and functions (`buildSessionContext`, `migrateSessionEntries`, `parseSessionEntries`, `getLatestCompactionEntry`, `getDefaultSessionDir`, `loadEntriesFromFile`, `findMostRecentSession`, `assertValidSessionId`, `isAutoLearnSessionId`, `CURRENT_SESSION_VERSION`) now come from `@caupulican/pi-agent-core/node` (moved out of `core/session-manager.ts`); `core/session-manager-factory.ts` still wraps it with the same host-layer API, so coding-agent's public surface and behavior are unchanged.
- The compaction + branch-summarization module (`shouldCompact`, `prepareCompaction`, `compact`, `generateSummary`, `findCutPoint`, `findTurnStartIndex`, `estimateTokens`, `estimateContextTokens`, `calculateContextTokens`, `getLastAssistantUsage`, `serializeConversation`, `DEFAULT_COMPACTION_SETTINGS`, `collectEntriesForBranchSummary`, `prepareBranchEntries`, `generateBranchSummary`, and the `CompactionResult`/`CompactionSettings`/`CompactionPreparation`/`FileOperations` types) now comes from `@caupulican/pi-agent-core/node` (moved out of `core/compaction/`); the `#30` cost-guard triggers (`triggerPercent`, `MIN_COMPACTION_SAVINGS`) ride along unchanged. `AgentSession` still owns the auto-compaction orchestration and calls into the promoted functions; coding-agent re-exports the surface unchanged, so its public API and behavior are preserved.
- Auto-retry, stalled-stream abort, bash silence watchdog, exec kill escalation, and bash/edit write serialization now ride the shared reliability kernel (@caupulican/pi-agent-core).
- Provider errors containing auth wording (401/unauthorized/invalid api key) are now terminal instead of retried, even when combined with transient wording (e.g. "fetch failed: 401 unauthorized") — retrying on bad credentials is pointless. Previously such mixed messages were retried.
- Custom retry settings are now capped at 120s per backoff step (maxDelayMs). Default behavior (2s/4s/8s) is unchanged; only aggressive custom baseDelayMs/maxRetries combinations are affected.
- The Auto Learn / native-reflection controller moved out of `interactive-mode.ts` into `modes/interactive/auto-learn-controller.ts` (new `AutoLearnController`): the disk-backed run-state machine (state.json + lockfile), the background-learner spawn/prune lifecycle, and the in-process reflection pass now live in one module. `InteractiveMode` constructs it with narrow deps (a live session accessor, the host's self-modification-source resolver, and a small UI callback surface) and delegates at every call-in point; behavior is unchanged.
- The local-runtime (Ollama) lifecycle moved out of `agent-session.ts` into `core/local-runtime-controller.ts` (new `LocalRuntimeController`): the cached per-server `OllamaRuntime` instances, the "confirmed up this session" flag, the #31 install-on-consent flow, and the #27 router tier-escalation fallback now live in one module. `AgentSession` constructs it with narrow deps (agent dir, a last-assistant-message accessor, the session's UI context/event emitter, and the router's own tier resolver) and delegates at every call-in point (`getLocalRuntime` keeps its public signature); behavior is unchanged.
- System-prompt construction moved out of `agent-session.ts` into `core/system-prompt-builder.ts` (new `SystemPromptBuilder`): the situational-soul (R6), self-modification, and autonomy guardrail blocks, the per-tool snippet/guideline options assembly, and the `_baseSystemPromptOptions` state now live in one module (distinct from the existing pure `core/system-prompt.ts` string renderer it feeds). `AgentSession` constructs it with narrow accessor deps (cwd, the settings/resource/memory managers, the tool registries, and the active extensions — each read fresh so mid-session reassignment is tracked) and delegates at every call-in point; behavior is unchanged.
- Autonomy telemetry and the status/diagnostic snapshots moved out of `agent-session.ts` into `core/autonomy-telemetry.ts` (new `AutonomyTelemetry`): the G3 telemetry sink, the G8 gate-outcome recorder plus the bounded gate-outcome history (owning the `_lastAutonomyGateOutcome` / `_gateOutcomeHistory` state), and the `getAutonomyStatusSnapshot` / `getAutonomyDiagnosticSnapshot` builders now live in one module. `AgentSession` constructs it with narrow accessor deps (the session manager, the last router decision, cost/goal/lane getters, and the research/delegation/learning snapshot getters — each read fresh) and delegates at every call-in point (`_emitAutonomyTelemetry`, `_recordGateOutcome`, `getGateOutcomeHistory`, and both public snapshot methods keep their signatures); behavior is unchanged.
- The background lanes moved out of `agent-session.ts` into `core/background-lane-controller.ts` (new `BackgroundLaneController`): idle goal auto-continue, the autonomous research lane, scout-worker delegation, and the model-fitness probe — plus the shared lane-model/profile/envelope resolution helpers — now live in one module, owning the lane timers, the single-flight guards, the last research-lane skip reason, the live `LaneTracker`, and the in-flight research/worker abort controllers. `AgentSession` constructs it with narrow accessor deps (the session manager, settings, model registry, live model, capability envelope, the model-capability profile, the goal continuation LOOP, the isolated-completion primitive, spawned-usage accounting, and the telemetry sink — each read fresh) and delegates at every call-in point: the idle triggers off the prompt tail, the dispose-time timer clears + lane aborts, the router judge's lane-model resolution, and the public `runResearchLaneOnce` / `runWorkerDelegationOnce` / `runModelFitness` / `getStoredFitnessReports` / `getLaneRecords` methods keep their signatures. The drive-loop boundary is preserved — the controller only ever asks the session to `continueGoalLoop`, never touching `prompt()` or streaming/retry state; behavior is unchanged.
- The memory subsystem moved out of `agent-session.ts` into `core/memory-controller.ts` (new `MemoryController`): the observe-only local OKF retrieval, the bounded prompt-evidence surfacing pilot, cross-session recall gating/effectiveness, and the plug-and-play `MemoryManager` (bundled file-store + transcript-recall providers plus extension contributions) now live in one module, owning the lazily-built OKF provider, the latest retrieval/prompt-inclusion reports, the reload-safe `MemoryManager`, the recall `EffectivenessTracker`, and the extension-contributed pending providers. `AgentSession` constructs it with narrow accessor deps (settings, the current turn index, agent/workspace dirs, the session id, the child-session flag, and the tool-registry refresh — each read fresh) and delegates at every call-in point: the context-transform hot path (`_runMemoryRetrieval` / `_maybeAppendMemoryEvidenceBlock` stay as one-line delegations so the transform keeps owning the pass ordering), the drive-loop cross-session recall (`shouldAttemptRecall` / prefetch / `recordRecallOutcome`), the context_audit memory diagnostics, dispose-time shutdown, reload's provider reset + re-init, the memory-tool surfacing, and the reflection engine's fresh-memory reads. The public `getMemoryRetrievalReport` / `getMemoryPromptInclusionReport` / `registerMemoryProvider` methods keep their signatures. The controller imports no compaction/context-pipeline internals; behavior is unchanged.
- The per-turn context pipeline moved out of `agent-session.ts` into `core/context-pipeline.ts` (new `ContextPipeline`): the observe-only context audit, the shadow prompt-policy plan and its correlation with legacy context-gc, the enforcement pilot, the relevance-curation queue plus the fitness-gated curation-model resolver / brain-curation drain / compaction pre-digest, the legacy context-gc pass and its packed-artifact reference release, the tool-output artifact store, and the current-context token estimate now live in one module, owning the latest audit/policy/correlation/enforcement/gc reports, the `BrainCurator` sidecar and its curation/pre-digest skip reasons, and the lazily-built artifact store. `AgentSession` constructs it with narrow accessor deps (the current turn index, the session/settings managers, the model registry, agent/workspace dirs, the active tool names, the disposed flag, the isolated-completion primitive, spawned-usage accounting, and the live `MemoryManager` — each read fresh) and delegates at every call-in point: `_installAgentContextTransform` stays host-side and keeps the pass ordering, with each stage (`_estimateCurrentContextTokens`, `_runContextAudit`, `_runPromptPolicyPlanning`, `_applyContextGc`, `_correlatePromptPolicyWithContextGc`, `_runPromptEnforcement`, `_enqueueRelevanceCuration`, `_maybeDrainBrainCuration`) a one-line delegation; the compaction pre-digest, executor reflex-brain model resolution, runtime tool-artifact-store build, per-turn cost guard, composition dashboard, and dispose-time artifact sweep likewise delegate. The public `getContextAuditReport` / `getPromptPolicyReport` / `getPromptPolicyGcCorrelation` / `getPromptEnforcementReport` / `getContextGcReport` / `getContextCurationStatus` methods keep their signatures. The pipeline reaches `MemoryController` only through the `getMemoryManager` dep (never imports it), and `MemoryController` never imports the pipeline, so the transform stays the single place the two subsystems meet; behavior is unchanged.
- Two pure computation clusters moved out of `interactive-mode.ts` into new sibling modules. `modes/interactive/history-reload-math.ts` holds the TUI reload-window math (`messagesForTuiHistoryReload`, `estimateTuiHistoryLines`, the text/message tail-trimmers, and the message-text extractors, plus the `TUI_HISTORY_RELOAD_MAX_LINES`/`_WRAP_WIDTH` budgets). `modes/interactive/resource-display.ts` holds the startup "loaded resources" formatters (path/label/scope-group/diagnostics rendering). `InteractiveMode` retains thin `this.`-delegating wrappers only where its stateful display code (`showLoadedResources`, `renderSessionContext`, `addMessageToChat`) or the existing prototype-based tests resolve a formatter through `this`; the rest are called directly from the modules. Behavior is unchanged.
- The editor-overlay swap that `interactive-mode.ts` repeats ~23× (both showing an overlay in place of the editor — selectors, dialogs, loaders, the reload notice — and restoring the editor afterwards) is now unified behind `modes/interactive/editor-overlay-host.ts` (new `EditorOverlayHost`). Its single `swap(component, options)` method performs the `clear → addChild → focus → requestRender` sequence, parameterizing the real per-site deltas: the focus target (defaults to the mounted component; the selector helper focuses a distinct child), `setFocus` vs `restoreFocus` (the latter for the two selector-return paths that prefer the topmost visible overlay), and the render request (`requestRender()`, `requestRender(true)` for the reload notice, or none where the caller renders later). Per-site cleanup that isn't a swap concern (component `dispose()`, temp-file unlink, clearing the stored selector reference, restoring saved editor text) stays inline at each call site. The editor-*replacement* path (`setCustomEditorComponent`, which clears early, rebuilds the editor, then mounts it) is a different shape and is left as-is. Behavior is unchanged.
- The resource-profile and external-source menu flows moved out of `interactive-mode.ts` into `modes/interactive/profile-menu-controller.ts` (new `ProfileMenuController`): the `/profiles` command, the resources-hub menu tree (active-profile selection, manage/create/delete/persist profiles, the per-profile library resource-grant editor, and external-root add/remove), and the profile-apply/reload/mutation-refresh logic now live in one module (23 methods). It holds no state of its own — every fact still lives in `settingsManager`, the profile registry, and the session resource loader — so `InteractiveMode` constructs it with narrow deps (a live session accessor and a UI callback surface, including the shared `showSelector`/`EditorOverlayHost`) and keeps thin one-line delegators at the three call-in points (`handleResourcesHubAction`, `handleProfilesCommand`, `refreshAfterProfileMutation`); behavior is unchanged.
- The auth / login / OAuth dialog flows moved out of `interactive-mode.ts` into `modes/interactive/auth-dialogs-controller.ts` (new `AuthDialogsController`): the `/login` and `/logout` command handling (provider resolution and selection, the auth-type/provider selectors), the subscription (OAuth) login dialog, the API-key login dialog, the Amazon Bedrock setup notice, the in-dialog OAuth select prompt, and post-login model adoption now live in one module (12 methods), together with the auth-provider classification helpers (`isApiKeyLoginProvider`, `isUnknownModel`, `hasDefaultModelProvider`, `BEDROCK_PROVIDER_ID`) that only those flows used. It holds no state of its own — every credential/provider fact still lives in `session.modelRegistry.authStorage` — so `InteractiveMode` constructs it with narrow deps (a live session accessor and a UI callback surface, including the shared `showSelector`/`EditorOverlayHost`) and reaches it at the single external call-in point (`showOAuthSelector`, for `/login` and `/logout`); behavior is unchanged.
- The config backup/restore commands and the read-only report/easter-egg commands moved out of `interactive-mode.ts` into two new sibling modules. `modes/interactive/config-backup.ts` holds `/config-backup` and `/config-restore` (the profile + resource-settings snapshot and its round-trip, including the pre-restore confirmation and the security rule that restored external roots come back untrusted). `modes/interactive/report-commands.ts` holds the read-only reports (`/usage`, `/changelog`, `/hotkeys`, `/debug`) and the easter-egg renders (`/arminsayshi`, `/dementedelves`, and the kimi-k2.5 daxnuts trigger). Both are plain function modules that operate through a narrow structural `host` seam (the settings manager plus status/error/selector callbacks; or the chat container, TUI, and a few read accessors), so `InteractiveMode` keeps thin wrappers that build the host from `this` at call time — required both because those fields are private and because the existing prototype-based tests invoke the wrappers through `this`. Behavior is unchanged.
- The model-router turn routing moved out of `agent-session.ts` into `core/model-router-controller.ts` (new `ModelRouterController`): the regex/executor route resolver, the optional bounded routing judge, the executor lane (Level-0 toolkit direct hit plus the speculative brain-refined retry), the per-tier thinking/tool-surface swap around a routed turn, the cheap-research-turn session buffer with mutating-tool escalation to an expensive retry, and the router status/diagnostics report now live in one module, owning the transient per-turn route state (active intent/route, the cheap-turn session buffer, the escalation-requested and retry-in-flight flags) and the sticky last-decision/skip-reason/intent. The parallel routed drive path (`runRoutedTurn`) keeps the actual agent.prompt()/continue() loop host-side — `AgentSession._runAgentPrompt`/`_promptUnserialized` are untouched and reached through a `runAgentPrompt` dep, so the drive loop is never duplicated. `AgentSession` constructs it with narrow accessor deps (the live agent, current model, the session/settings managers, the model registry, agent dir, the reflection abort signal, the base system prompt, the isolated-completion primitive, spawned-usage accounting, the event/telemetry emitters, and the recently-extracted `BackgroundLaneController.resolveLaneModel` / `ContextPipeline.resolveCurationModelIfFit`) and keeps a one-line delegation at every call-in: the routing prep + routed-turn entry in `_promptUnserialized`, the `beforeToolCall` mutating-tool escalation branch (`maybeEscalateToolCall`), the `message_end` cheap-turn buffering (`captureSessionMessage`), the retry-event suppression (`isRetryInFlight`), and the public `getModelRouterStatus` plus the autonomy-telemetry last-decision read. Behavior and event ordering are unchanged.
- The runtime build and the self-modification-safe extension reload moved out of `agent-session.ts` into `core/runtime-builder.ts` (new `RuntimeBuilder`): the tool-registry assembly (`refreshToolRegistry`), the base-tool-definition + `ExtensionRunner` build (`buildRuntime`), the crown-jewel `reload()` with its snapshot / doctor / commit-or-rollback sequence, and the single-extension live load/unload/reconcile operations now live in one module, owning the five tool-registry maps (base tool definitions, the wrapped tool registry, the definition registry, and the per-tool prompt snippet/guideline maps). The reload snapshot spans state owned by other collaborators — the extension runner and its ref, `agent.state.tools`/`agent.state.systemPrompt`, and `_baseSystemPrompt` — which stay host/agent-owned and are captured and restored through narrow get/set deps so save/restore mutate exactly the same fields as before (the `_extensionRunnerRef.current` update folds into `setExtensionRunner`, matching the host's field-then-ref pattern); only the tool-registry maps are owned by the builder. `_bindExtensionCore` stays host-side (it exposes the session's own public surface to the runner — host identity, not build logic) and is invoked from `buildRuntime` via a `bindExtensionCore` dep. `AgentSession` constructs it with narrow accessor deps (the live agent, cwd, the session/settings managers, the model registry, the resource loader, the extension-runner get/set, the base-system-prompt get/set, the custom-tools/base-override, the requested-active-tool-names request, the profile tool filter + its warning sink, memory subsystem accessors, the goal/context-gc/worker/model-fitness tool callbacks, the isolated-completion primitive and spawned-usage accounting, the doctor context-snapshot/context-usage probes, and the streaming/compacting refusal guards) and keeps byte-identical one-line delegations for the public `reload` / `loadExtensionLive` / `unloadExtensionLive` / `reconcileLoadedExtensions` API and for `getAllTools` / `getToolDefinition`, plus a private `_refreshToolRegistry` delegation for its internal callers. The preflight → doctor → commit/rollback sequence and refusal behavior are unchanged.
- The extension UI surface moved out of `interactive-mode.ts` into `modes/interactive/extension-ui-host.ts` (new `ExtensionUiHost`): the extension-provided dialogs (`select`/`confirm`/`input`, the multi-line editor, and the overlay-capable `custom` component), the above/below-editor widget mounting, extension status text, the custom footer/header swaps, the custom editor-component swap (`setCustomEditorComponent`, its early `editorContainer.clear()` preserved verbatim), keyboard-shortcut wiring, terminal-input listeners, the extension-error render, and the `ExtensionUIContext` handed to extensions now live in one module (22 methods). It owns exactly the state this cluster mutates (the live selector/input/editor dialog components, the above/below widget maps, the terminal-input unsubscribers, the custom footer/header, and the current custom-editor factory). `InteractiveMode` constructs it with narrow deps (a live session accessor plus a UI callback surface: the stable containers/TUI/overlay-host/footer passed directly, the mutable active editor and built-in header reached through get/set accessors, and the render-core / status operations that stay host-side — working indicator, hidden-thinking label, autocomplete rebuild, tools-expansion, terminal title, and shutdown/abort/reload — exposed as callbacks) and keeps one-line delegations at every call-in point: the session-invalidate reset and `handleReloadCommand`'s `resetExtensionUI`, `bindCurrentSessionExtensions`' context/error/shortcut wiring, the reload and live-refresh shortcut re-wiring, the branch-summary and `/import` confirm/selector/editor prompts, the initial widget render, `stop()`'s listener teardown, and the three `getCustomHeader()` header reads. The extension test suites are the lock — extensions see an identical `ExtensionUIContext`; behavior is unchanged.
- The residual command/flow/plumbing clusters moved out of `interactive-mode.ts` into thirteen new sibling modules, bringing the file under the 4,000-line cap (5,870 → 3,971): `session-flow-commands.ts` (tree/session/fork navigation and the model selectors), `settings-selector-flow.ts` (`/settings`), `local-model-commands.ts` (`/models` lifecycle and `/fitness`), `autonomy-commands.ts` (`/autonomy`, `/auto-learn`), `session-io-commands.ts` (import/export/share/copy/name), `resource-shell-commands.ts` (`/install-resources`, `/curate`, bash, `/compact`), `external-editor.ts` (`$EDITOR`/`$VISUAL` launch), `autocomplete-provider.ts` (base completion set), `startup-checks.ts` (changelog notice, update/tmux checks, notifications, install telemetry, trust warning), `signal-lifecycle.ts` (SIGTERM/SIGHUP/uncaught handlers, graceful+emergency shutdown, Ctrl+Z suspend), `key-handlers.ts` (editor/global key wiring), `clipboard-input.ts` (image paste + user-input assembly), and `compaction-queue.ts` (post-compaction queue flush). Each is a plain function module operating through a narrow structural `host` seam; `InteractiveMode` keeps thin wrappers that build the host from `this` at call time (with get/set accessors for the fields a flow mutates — e.g. `loadingAnimation`, `isShuttingDown`/`signalCleanupHandlers`, `isBashMode`, the clipboard queue/counter, `compactionQueuedMessages`) both because those members are private and because the existing prototype-based tests invoke the wrappers through `this`. The slash-command router, `handleEvent`, the streaming/status-loader lifecycle, `renderSessionContext`, and the render core stay host-side. Bodies are verbatim; behavior is unchanged.
- The residual autonomy/session/runtime clusters moved out of `agent-session.ts` into eight new `core/` collaborator classes, bringing the file under the 4,000-line cap (5,387 → 3,963): `reflection-controller.ts` (`ReflectionController` — the native end-of-loop reflection pass, the isolated-completion primitive, and the gated learning-apply/rollback path), `goal-loop-controller.ts` (`GoalLoopController` — the bounded goal auto-continuation loop), `session-analytics.ts` (`SessionAnalytics` — usage/cost/stats accounting, the /context window estimate, and HTML/JSONL export, owning the spawned-usage and daily-usage memo caches), `session-tree-navigator.ts` (`SessionTreeNavigator` — in-file branch switching + fork-selector reads), `model-selection-controller.ts` (`ModelSelectionController` — the manual model switch/cycle and thinking-level set/cycle/clamp, distinct from the per-turn `ModelRouterController`), `bash-execution-controller.ts` (`BashExecutionController` — the `/bash` path and its streaming-deferred pending-message queue), `profile-filter-controller.ts` (`ProfileFilterController` — resource-profile tool/extension gating and reload-time profile model re-apply), and `tool-gate-controller.ts` (`ToolGateController` — the agent `beforeToolCall`/`afterToolCall` hooks: router escalation, autonomy gating, extension tool hooks, and the untrusted-content output boundary). `AgentSession` constructs each with narrow lazy accessor deps and keeps same-signature public delegations at every call-in point, so callers, the constructor dep closures, and the drive loop are untouched (the `model`/`thinkingLevel` getters, the branch-summary abort controller read by `isCompacting`, and the bash-flush call sites all stay host-side). The drive loop (`_promptUnserialized`/`_handleAgentEvent`/`_handlePostAgentRun`), compaction, the retry bridge, and the extension-core wiring stay host-side. Bodies are verbatim; behavior is unchanged.

### Fixed
- Default compaction model selection now respects the Model Router cheap model when enabled, otherwise falls back to the active session model with low reasoning instead of picking the globally cheapest authed model (which could route summarization through `openrouter/auto`).
- `pi --version` resolved through the full application import graph (~1s to print a version string). A fast path in the CLI entry now answers `--version`/`-v` from already-loaded config (~150ms, −85%); any combined invocation still routes through the full parser unchanged.
- Auto-compaction could fail or skip invisibly: three bail paths (no model, summarizer auth failure, nothing to compact) ended with no result and no reason, and the TUI rendered nothing for that combination — indistinguishable from broken compaction. Every auto-compaction outcome now carries a `result`, an `errorMessage`, or a new `skipReason` on `compaction_end`, and the TUI renders all of them. The cheap summarizer model (#30) also falls back to the session model when its key resolution fails at request time instead of silently giving up.
- `pi --help` had regressed from ~160ms to ~400ms: `config.ts`'s `normalizePath` import (needed
  just to resolve `PI_PACKAGE_DIR`) went through `utils/paths.ts`, which re-exported from
  `@caupulican/pi-agent-core/node` — a barrel that also loads `SessionManager`, compaction,
  messages, and process-tree, none of which the help path needs. `utils/paths.ts` now imports from
  the kernel's new granular `@caupulican/pi-agent-core/paths` subpath instead, restoring `--help` to
  its ~160ms baseline; behavior and the re-exported surface are unchanged.
- Bash commands could previously race file-tool (`edit`/`write`) mutations: because a shell command
  cannot statically declare which files it touches, it wasn't serialized against them at all. The
  bash tool's foreground command execution now goes through a readers-writer barrier shared with
  `withFileMutationQueue`: file mutations are readers (still parallel with each other across
  different files), and bash is the sole writer — it waits for all in-flight/queued file mutations
  to drain, then runs exclusively while blocking new ones, and queues FIFO against other bash
  invocations. New `withExclusiveMutationBarrier` in `file-mutation-queue.ts`.
- `execCommand`'s kill path (used by aborted/timed-out commands, including extensions' `ctx.exec`)
  now actually escalates to SIGKILL: it previously gated escalation on `ChildProcess.killed`, which
  Node sets the moment a signal is *sent* rather than when the process dies, so a child trapping
  SIGTERM survived forever. The kill path now delegates to the reliability kernel's `killTree`
  (liveness-probed SIGTERM → SIGKILL escalation). Commands also spawn in their own process group on
  POSIX so aborting kills grandchildren, not just the direct child. Spawn failures (e.g. ENOENT) are
  now surfaced via a new `ExecResult.errorMessage` field instead of being silently swallowed as a
  bare `code: 1`.
- Model adoption ignored the fitness probe's own verdict. Two gates, both fixed:
  - `/models suggest` (and the manual `/fitness` picker) could probe a model, get zero successes on
    every one of the six surfaces, and still land it as judge model / Model Router settings because
    the post-probe role selector opened regardless of the result. `runFitnessAndAssign` — the single
    site both flows funnel through — now checks the new pure `isProbeAllFailed(report)` predicate
    (research/core/research/model-fitness.ts) and, on an all-lanes-failed probe, refuses adoption
    outright: no role assigned, no settings written, just a clear "failed the fitness probe on all
    surfaces — not configured" message pointing at manual `/model` as the opt-in override. A partial
    or full pass keeps the existing selector flow unchanged. The predicate itself had a latent
    vacuous-truth gap: when every lane surface was ungraded (`total: 0`) but the judge ran and
    failed, `gradedLanes.every(...)` was trivially true over the empty array, so a report with zero
    lane evidence could still be read as all-lanes-failed — it now requires at least one actually
    graded lane before returning that verdict.
  - Manual `/model <ref>` had no gate at all, so a model already known (from a stored fitness
    report) to fail on every surface, or a local Ollama model whose weights don't fit in RAM, could
    be set silently and 500 every subsequent turn (llama-server OOM). `AgentSession.setModel` is
    advisory-only here by design — a human's explicit choice is never blocked — but now emits a
    `warning` event (the same plain-text channel print/RPC modes already render, never a prompt)
    when the target has a recorded all-lanes-failed probe on this host, or is an Ollama model whose
    installed size exceeds ~90% of `os.totalmem()`. This advisory now also covers `cycleModel`
    (reachable via the `app.model.cycleForward`/`cycleBackward` keybindings and the RPC
    `cycleModel` call), which previously bypassed it entirely on both the scoped (`--models`) and
    all-available cycle paths, silently landing on a known-bad or OOM-prone model. The Ollama
    size/RAM lookup (and `/models remove`) also missed installed models referenced by a bare tag —
    Ollama's `/api/tags` always reports an explicit tag, defaulting to `:latest`, so an exact-string
    match silently skipped the check whenever a user typed a bare ref (e.g. `llama3` vs. the
    installed `llama3:latest`); both call sites now share one `matchesInstalledLocalModel` helper
    (`core/models/model-ref.ts`) that accounts for the bare/`:latest` pairing.
- `output-accumulator-io-errors.test.ts`'s `vi.mock("node:fs", ...)` factory returned only the three
  members the test overrides (`closeSync`, `openSync`, `writeSync`), so any other `node:fs` export
  accessed during the run — `existsSync`, read at import time by `@caupulican/pi-ai`'s
  `env-api-keys.ts` — threw inside vitest's mock proxy and surfaced as an unhandled rejection, even
  though the test's own assertions passed. The mock now spreads the real module
  (`importOriginal()`) and overrides only the three functions it needs, so unmocked exports stay
  real.
- `keyHandlersHost()` snapshotted `editor`, `session`, and `settingsManager` onto the key-handler
  host object at `setupKeyHandlers()`'s one-time init instead of reading them live off `this`. All
  three are swappable after init — `editor` via extension custom editors (`setEditor`, whose
  `onEscape` delegates back through the closures installed on `defaultEditor`), and
  `session`/`settingsManager` via `/reload`'s runtime-host swap — so Escape handling kept reading
  the stale pre-swap objects: Escape could fail to abort bash on a reloaded session, and the
  double-escape `/tree`/`/fork` trigger could read the wrong editor's text. `keyHandlersHost()` now
  exposes `editor`, `session`, and `settingsManager` as live getters over the instance (matching the
  existing `isBashMode`/`lastEscapeTime` accessor pattern); `defaultEditor` and `ui` stay plain
  properties since they're set once and never swapped.

## [0.80.103] - 2026-07-03

### Fixed

- Config-directory override environment variables are now POSIX-valid and actually usable. Because
  `piConfig.name` is `pi-adaptative`, the derived names were `PI-ADAPTATIVE_CODING_AGENT_DIR` and
  `PI-ADAPTATIVE_CODING_AGENT_SESSION_DIR` — but a hyphen is invalid in a shell variable name, so
  `export PI-ADAPTATIVE_CODING_AGENT_DIR=…` is a parse error and the documented override (shown in
  `pi --help`) silently could not be set. The names are now sanitized to
  `PI_ADAPTATIVE_CODING_AGENT_DIR` and `PI_ADAPTATIVE_CODING_AGENT_SESSION_DIR`.

## [0.80.102] - 2026-07-03

### Fixed

- Made the FFF lazy-install test suite environment-independent. Three tests asserted that
  `@ff-labs/fff-node` was not resolvable — which held locally (the package resolves only via the
  managed install) but failed in CI, where the declared dependency is installed by `npm ci`,
  blocking v0.80.101 from publishing. `loadAvailableFffNodePackage`/`ensureFffNodePackage` now take
  an optional injectable resolver-candidate list, and those tests pass an empty list to force the
  "not available" precondition deterministically regardless of environment. Test-only; no runtime
  behavior change. 0.80.102 republishes the 0.80.101 changes with this fix.

## [0.80.101] - 2026-07-03

### Added

- Skills may declare a `thinking` level in their frontmatter (parsed and validated on load, invalid
  values ignored), so a task-specific skill can carry its intended reasoning depth. The parsed value
  is available wherever `Skill` objects flow; turn-scoped application of an active skill's thinking
  is a follow-up (an extension can already apply it via the existing `ctx.setThinkingLevel()` hook).
  Complements profile-level thinking, which is applied to the session across CLI startup, SDK
  creation, `/profile` switch, and `/reload` (explicit `--thinking` still wins) — now covered by
  tests, including its composition with per-tier router thinking (the router override wins for the
  routed turn and restores the profile level after).
- Per-tier thinking level for the model router: `modelRouter` now accepts `cheapThinking`,
  `mediumThinking`, `expensiveThinking`, `executorThinking`, and `judgeThinking`. A routed turn
  applies the configured thinking level for its tier (clamped to the routed model), so a
  cheap/local tier can run at `low`/`off` while the expensive tier runs at `high` — thinking level
  is now a cost/speed lever independent of the model choice. Unset per-tier thinking reproduces
  today's inherit-and-clamp behavior exactly; the routing judge's own bounded completion uses
  `judgeThinking` (default `off`). Executor-direct routes are matched before the cheap tier so they
  read `executorThinking`, not `cheapThinking`. Each tier's thinking level is settable in the Model
  Router settings submenu (an "(inherit)" option clears it to the default behavior).
- `/models suggest` now opens an interactive picker over the validated local-model roster instead of
  printing a list to retype: choosing a model installs it, probes its six fitness surfaces on the
  actual hardware, and lands the role it was shaped for already pre-selected in the assignment step —
  so a suggested model goes from pick to installed-and-set in one flow. The suggestion's shaped
  `assignRole` (previously unused metadata) drives the pre-selection; non-tool-calling models carry
  curator/judge/lane roles and never pre-select the executor role.
- The model router now auto-manages the local ollama server: when a turn routes to a local (ollama)
  model, pi ensures the server is up first — reusing an already-running server and the user's own
  `~/.ollama` models (never pi's owned storage; a reuse-mode start omits the `OLLAMA_MODELS` override
  that `/models add` still uses) or booting one if needed — so a local-routed turn never fails just
  because the server wasn't started yet. A per-session "confirmed up" cache skips the health check on
  later turns (re-checked only after a connection error from the same model). If the local model
  can't be made ready (binary missing, or the server won't boot) the turn does not dead-end: a
  visible warning states why (install steps inline when the binary is missing) and which tier is now
  handling the turn, then it escalates to the next configured tier. The runtime is owned by
  `AgentSession`, so headless/SDK turns get the same behavior and `/models` shares the one instance.
- When a routed local model is missing only because the ollama binary itself isn't installed (not
  because its server is down), an interactive session now asks first: "Install Ollama?", noting it's
  a large one-time download, before doing anything. A "yes" downloads the pinned ollama release for
  the current platform straight into pi's own `runtimes/ollama` directory (never `curl | sh`, never
  outside pi's own directory) and extracts it — `.tar.zst` archives decompress via Node's own
  built-in zstd support when available, falling back to a system `zstd` binary, with an honest error
  if neither exists — then the turn proceeds on the original local model with no fallback needed. A
  "no", a timeout, an install that itself fails, or a headless/SDK session with no interactive prompt
  to ask through all fall straight through to the existing graceful tier-escalation warning above,
  worded to say so honestly (an install attempt that failed is reported as a failed install attempt,
  never re-labeled as if nothing was tried). The confirm dialog pauses the routing working-indicator
  while it's on screen and hands it back right after, so the spinner and the dialog never compete for
  the terminal at the same time.
- New `pi-adaptative doctor` command plus an update/startup preflight that verify required tooling and
  provision what pi owns. It checks FFF native search (managed — actually installs it if missing, via
  the same path as lazy first-use), ripgrep, ollama (binary + server status), and python, reporting
  each as present/missing with version/detail and, for tools pi doesn't own, guide-mode install steps
  (printed, never executed — no `curl | sh`, no `sudo`). The preflight runs automatically after a
  successful `pi-adaptative update` (best-effort, never fails the update), so an update actually
  provisions the managed tooling instead of leaving it to lazy first-use — closing the "ran update on
  another machine and FFF never got installed" gap. The interactive `doctor` shows install progress;
  the background preflight stays quiet.

### Fixed

- FFF native search now provisions itself even for ordinary searches. `find`/`grep` decide
  FFF-vs-fallback using their default result limit (1000/100), which exceeds the router's top-N
  threshold, so the decision is "fallback" and the tool returned *before* ever calling `getFinder()`
  — the call that triggers the lazy managed install of `@ff-labs/fff-node`. A machine that only ran
  default-limit searches therefore never installed FFF at all (rg/fd silently handled everything, so
  its speed was never available). Provisioning is now decoupled from the per-call routing outcome:
  `find`/`grep` kick off the finder unconditionally via a new `safeGetFinder` that can never reject
  (even if a custom backend's `getFinder` throws synchronously), reusing the same in-flight promise
  when the call does route to FFF. A genuine install failure is now retryable instead of permanently
  gating FFF out — the finder is always evicted so the next search re-enters — while a 30s cooldown
  throttles the npm spawn itself, so repeated searches during an outage don't respawn npm each time.
  An explicit `--offline`/`PI_OFFLINE` directive and unsupported platforms remain a stable no-retry
  fallback. The last install outcome is recorded (`getLastFffInstallOutcome`) for a future
  environment `doctor` check.
- The user's prompt now appears on screen immediately when submitted, instead of appearing to hang
  until the model router's routing judge finishes. The judge is a bounded LLM completion (seconds),
  and the turn previously built and emitted the user message only *after* awaiting it, so the prompt
  looked frozen right after Enter. `_promptUnserialized` now builds the user message and paints it (a
  synthetic `message_start`) before the judge await, then reuses that same object for the turn; the
  authoritative `message_start` emitted later is suppressed exactly once (reference-keyed via a Set),
  so the message is still shown and persisted a single time, and extensions still observe it at the
  real turn start (their visible behavior is unchanged).
- While the model router's routing/prep phase runs — the gap after the prompt paints and before the
  turn starts streaming, during which the routing judge makes a bounded LLM call — the interactive UI
  now shows the existing "working" indicator as general processing feedback, so that gap no longer
  looks frozen. It shows independently of the thinking level (this is routing feedback, not
  model-thinking) and respects the user's working-indicator toggle. New UI-only `routing_start` /
  `routing_end` session events bracket the phase and are emitted exactly once each — `routing_end`
  fires on both the success and failure paths, so the indicator never spins on after a turn that
  fails before it starts — and it hands off seamlessly into the normal streaming indicator.
- Hardened the hardening sweep after a max-effort review of the working diff found nine regressions
  and latent holes the first pass introduced or left open:
  - `endWriteStream` (newly awaited by the bash executor) hung forever when the stream had already
    errored or closed before the call — an errored stream never emits `finish`, so the `once`
    listeners attached after the events fired and never resolved, hanging the bash tool on any spill
    write error. It now resolves immediately for an already-finished/destroyed/closed/errored stream.
  - The git-filter spill branch created its temp-file stream with no error handler, so a failed spill
    write still advertised a "Full output:" path pointing at a partial or missing file. It now drops
    the path on write error, matching the main capture path.
  - The execution-time envelope path check resolved a target through `existsSync`, which reports
    false for a DANGLING symlink — so a dangling symlink placed inside an allowed root resolved
    lexically and escaped the envelope (the subsequent write follows the link). `safeRealpathSync`
    now dereferences a dangling leaf via `lstat`/`readlink` with a hop cap, closing the escape.
  - `applyWorkerActions` routed writes through an injectable fs seam while the scope check used the
    real filesystem, so the two could disagree. The test-only seam (its sole injector) is removed;
    scope check and write now share one filesystem of record.
  - The context-GC auto-digest was fenced at RENDER time, regenerating a random boundary nonce on
    every provider request (the GC transform re-runs per request) — a byte-unstable prompt prefix
    that broke prefix caching, and double-wrapped/mangled an already-fenced digest. Fencing now
    happens once at digest store time; GC renders it verbatim.
  - A reflection write the gate marked "apply" recorded an `action:"apply"` audit with a rollback
    plan even when the memory tool silently refused it (budget/drift/threat return `success:false`
    without throwing) — a phantom rollback target that then failed not-found. A refused apply now
    records an `apply_failed` audit with no rollback plan and is not rollback-eligible.
  - The `/context` "withheld by the active resource profile" line fired even with NO active profile,
    blaming a nonexistent profile for a plain user disable (and double-reporting alongside the
    disable-wins warning). The count is now profile-only and empty when no profile is active.
  - A durable `memory_replace`/`memory_remove` could never auto-apply even under a fully permissive
    policy, because the contradiction branch short-circuited before every eligibility check — an
    append-only incentive that degraded memory hygiene. A new `learningPolicy.autoApplySupersessions`
    (default false, TUI-toggleable) lets a supersession fall through to the normal eligibility bars.
  - Router-swapped turns restored the pre-turn tools/system-prompt unconditionally in `finally`,
    silently clobbering a mid-turn extension change (e.g. `setActiveToolsByName`) that legitimately
    replaced them. Restore now happens only when the live values are still exactly what the swap
    assigned.
  - The editor grant-widening guard was applied only to allow-framing: the block-framing all-enabled
    branch still widened a closed grant to `{allow:["*"]}` for a kind the profile omitted, and the
    editor let the literal `"*"` wildcard marker enter the working set as a fake resource id (so
    unchecking one item under a `{allow:["*"]}` grant persisted `{allow:[…,"*"]}`, and the disabled
    item kept loading). Both paths now gate on the same original-wildcard/grant-all check, and the
    marker never enters the item set.
- Fixed `executeBash` returning a full-output temp-file path before the file's write was flushed:
  the artifact write went through an async stream that was `.end()`-ed but never awaited, so a caller
  reading the path immediately could see partial or empty content (a load-dependent flake). The stream
  flush is now awaited across the normal, git-filter, cancel, and error paths, so the returned path
  always points at a complete file.
- Fixed the context-GC auto-digest (a machine paraphrase of possibly attacker-influenced tool output)
  being inlined into the prompt as bare prose: it is now wrapped in the standard untrusted-content
  fence, the same boundary memory recall pages use, so an injection payload in the digest is framed as
  data, not instructions.
- Fixed profile-denied context files (AGENTS.md/CLAUDE.md/GEMINI.md) being read and processed as
  content before the agents-kind profile filter: the loader now reads each candidate file's raw bytes
  once purely to discover any embedded `<resource-profile>` blocks (unavoidable — a profile can be
  defined in a file it then denies), and only sanitizes, threat-scans, and exposes files the profile
  allows. A denied file's instructional content is never loaded into the session, and the redundant
  double read of every context file is gone.
- Fixed the profile resource editor silently widening a closed grant to a wildcard: when every id in a
  kind's (possibly collapsed) universe was enabled, a no-change save re-encoded an enumerated grant
  like `{allow:[alpha,beta]}` as `{allow:["*"]}`, auto-granting every future resource of that kind. The
  save now preserves the enumerated list and only keeps `["*"]` when the grant was already a wildcard
  (or grant-all was chosen explicitly).
- Fixed skills, prompts, and extensions denied by the active resource profile being silently absent
  from `/context`: it now reports "N skill(s)/prompt(s)/extension(s) withheld by the active resource
  profile — grant the <kind> kind to restore them", the same visibility the withheld-AGENTS.md
  warning already gave context files.
- Fixed a silently-swallowed executor miss: when an executor-routed turn ran no toolkit command and
  the reflex brain could not refine the request into an explicit instruction, the turn ended with no
  retry and no explanation. It now surfaces a warning that the command did not run and no automatic
  escalation happened (the no-frontier-fallback policy is unchanged).
- Fixed router-swapped turns (G4) leaving the system prompt at the full tool surface: when a turn is
  routed to a smaller model its tool set is filtered, but the system prompt still carried guidelines
  and schemas for tools the routed model couldn't call — billed every request and confusing to a
  cheap/local model. The prompt is now rebuilt for the routed model's filtered surface and restored
  afterwards, including when the routed run throws.
- Fixed the learning gate's contradiction branch being unreachable dead code: the reflection call site
  hardcoded `contradictions: 0`, so a durable `memory_replace`/`memory_remove` — which overwrites or
  deletes an existing memory fact (the reflection engine's confront-before-write conflict signal) —
  could auto-apply and silently destroy prior knowledge. Such supersessions now route through the
  contradiction branch (approval-gated proposal, audited); purely additive writes are unaffected.
- Fixed a learning-policy cliff where enabling the policy with stock settings silently disabled
  learning entirely: a below-confidence-threshold cue with no evidence returned a silent no-op
  (reflectionSourceConfidence 50 < confidenceThreshold 90, reflection writes carry no evidence), so
  every durable write was dropped with no apply and no audit trail. Below-threshold cues now degrade
  to an approval-gated proposal that is audited and visible in `/autonomy diagnostics`, while staying
  fail-closed — nothing auto-applies below the threshold.

## [0.80.100] - 2026-07-02

### Added

- Added `/models suggest`: a curated roster of local models validated during pi's own small-model
  research, each with the role it was shaped for — qwen3:1.7b as the toolkit executor/reflex
  muscle, qwen3:0.6b as a minimal fast executor, and the Ternary-Bonsai family (1.7B search scout,
  4B context-curator/reflex-brain, 8B routing-judge for larger machines) marked as non-tool-calling
  lane/brain models. Each suggestion is a ready `/models add` ref; the roster is surfaced when no
  local models are installed. No per-model score is baked in — fitness is host-dependent, so
  `/models add` still auto-probes on the actual machine and the roster only encodes each model's
  validated role.

## [0.80.99] - 2026-07-02

### Added

- Added code-writing workers (G2 full): with `workerDelegation.writeEnabled` plus a `writePaths`
  scope, a delegated worker may emit structured file actions (write/edit) that the RUNNER applies
  through the capability envelope's path scope — an out-of-scope or denied path is refused with a
  reason and downgrades the result to blocked (a partial change can never look like clean success),
  and a write without the grant is ignored and flagged. `workerDelegation.maxConcurrent` (1-3)
  replaces the single-flight limit. The read-only scout contract is unchanged when writes are off.
- Added speculative muscle-retry on executor turns: when an executor-routed turn ends without a
  successful run_toolkit_script execution, pi retries once on the same executor with the brain's
  refined instruction injected (the brain warms while the muscle tries, so the retry costs only
  when the muscle actually missed); visible in the router decision as executor_speculative_retry.
- Added gate-outcome history (G8): a bounded 50-entry history of tool-gate outcomes replaces the
  latest-only record (getGateOutcomeHistory()), and the three remaining autonomy telemetry types
  (gateOutcome, workerRequest, approvalRequest) now emit at their honest sites.
- Added per-turn foreground capability envelopes (G7): each turn derives an observe-only envelope
  (capabilities mapped from active tools, path scope = cwd, usd bound from the cost guard),
  surfaced as a one-line /context observation and via getForegroundEnvelope().
- Added capability-scaled goal-continuation budgets (G9): lean-class models (16-32k) now cap
  autonomous continuation at 2 turns / 5 minutes; below 16k stays gated off, full class unchanged.

## [0.80.98] - 2026-07-02

### Added

- Added the executor lane (G16): configure `modelRouter.executorModel` (or assign it in one step
  from /fitness -> "Toolkit executor") and command-shaped prompts that score a deterministic
  Level-0 EXACT hit on the toolkit registry route the whole turn to the local executor — with the
  judge skipped (nothing to judge), the tool surface capability-filtered to the executor's own
  class, and `run_toolkit_script` exempted from the cheap-tier mutation escalation ONLY on these
  routes (its own danger gate still applies; any other mutating tool still escalates). Ambiguous
  requests never route here — they stay with the main model and the reflex brain.
- Added workspace research sources (G1): the autonomous research lane now grounds itself in the
  repo — a bounded ripgrep collector derives terms from the goal text and feeds pointer-first
  sources (repo-relative path, line, <=200-char excerpt; never file bodies) into the research
  prompt and the evidence bundle, with the synthesis anchors always preserved. Best-effort: no
  ripgrep or no matches reproduces the previous behavior exactly.
- Added real evidence strength to the learning gate (G6): a bounded persistent observation store
  counts how often the same lesson (layer + normalized summary) is re-observed across passes and
  sessions, so `minObservations` now gates on truth — the first observation proposals, repeated
  ones can auto-apply.
- Added autonomy telemetry emission (G3): route decisions, research/worker lane outcomes, and
  learning decisions now emit redacted, bounded events (ids/codes/numbers only — never prompt or
  memory text) as `autonomy-telemetry` session entries.
- Added execution-time capability-envelope path enforcement and worker request persistence (G2
  prerequisites): a tool wrapped in an envelope scope structurally refuses out-of-scope paths at
  the moment it runs (deny-wins, escape-proof), and every worker result persists its originating
  request (instructions, route, envelope) for audit.
- Added digest-served telemetry: the /context curation line now reports how many brain digests
  were actually rendered into GC stubs on real turns — the pays-for-itself number.

## [0.80.97] - 2026-07-02

## [0.80.96] - 2026-07-02

### Added

- Added Settings submenus for Learning Policy (enabled, auto-apply, confidence threshold, min
  observations; layer allow-list stays JSON-only) and Model Capability (auto/off/forced class),
  closing the last two settings surfaces that were configurable only by hand-editing JSON (G5).
- Added routed-turn capability tool filtering (G4): when the model router swaps a turn to a
  cheaper model, the tool surface now follows the ROUTED model's capability class for that turn
  (an 8k local model no longer inherits — and pays schema tokens for — background-autonomy tools
  it cannot drive), restored with the session model afterwards.
- Added the reflex brain to `run_toolkit_script`: when the deterministic Level-0 matcher is
  ambiguous ("prepare db" vs "update db"), a fitness-gated local interpreter model (validated
  10/10 on the hard registry) resolves the request into a registry pick with extracted args —
  confidence-gated, registry-validated, and advisory only: danger confirmation and the structural
  execution contract apply identically to brain-selected scripts, and an absent/unfit/unconfident
  brain keeps today's shortlist behavior byte-for-byte. Brain spend is usage-accounted
  ("toolkit-brain").

## [0.80.95] - 2026-07-02

### Added

- Added `/models`, the local model lifecycle (install -> spawn -> probe -> consume -> uninstall):
  `/models add <ref>` accepts an ollama tag, an `hf.co/org/repo[:quant]` GGUF ref, a full
  HuggingFace URL, or a pasted `ollama pull ...` install command (parsed for its reference, never
  executed as shell) — pi starts its own health-checked server with OWNED model storage under
  `<agentDir>/models/ollama` (hardened env; an already-running system server is used instead, with
  the storage tradeoff surfaced), pulls with streamed progress, registers the model in models.json
  so `ollama/<ref>` resolves everywhere (session, lanes, judge, curator) across sessions, and
  auto-runs the fitness probe with one-step role assignment. `/models list` shows installed models
  with real sizes and cached fitness summaries; `/models stop` stops the pi-managed server
  (resource hygiene, deletes nothing). Removal is an EXPLICIT user action only — `/models remove
  <ref>` first discloses exactly what gets deleted (weights + size, registration, fitness report)
  and requires the confirm token; pi never removes a model on its own. Hand-authored models.json
  files with comments are never rewritten (a manual snippet is offered instead).

## [0.80.94] - 2026-07-02

### Fixed

- Fixed pi crashing with an uncaught ReferenceError when opening Manage Library: the profile
  editor's universe builder referenced a helper before its initialization (TDZ). The editor path
  is now covered by a regression test that executes it end to end.
- Fixed the selected profile not surviving pi restarts: /profiles selection was applied
  runtime-only, so every new session started with no profile. Selecting a profile now persists it
  to global settings (like model/theme selections), and selecting "(none)" persists the clear so
  the old selection cannot resurrect on restart.

## [0.80.93] - 2026-07-02

## [0.80.92] - 2026-07-02

### Added

- Added the brain-curation compaction pre-digest (design surface 3, runtime-gated): when curation
  is enabled AND the curator model has proven itself in-session (>=5 jobs, <=5% parse failures on
  top of the digest fitness gate), old conversation chunks are digested locally before the frontier
  summarization call — digests plus the verbatim recent tail replace the full transcript. Any chunk
  whose digest fails passes through verbatim (partial assist, never partial loss), and each
  pre-digest persists an auditable session record with chars-before/after.
- Surfaced three silent profile situations in the /context dashboard: an extension loaded but fully
  inert (profile denies all its tools and commands), an explicit tool grant that binds to no
  registered tool (typo or ungranted owning extension), and profile grants overridden by the user's
  own disable list — with the precedence now documented: a user disable ALWAYS beats a profile grant.

## [0.80.91] - 2026-07-02

## [0.80.90] - 2026-07-02

### Fixed

- Fixed the profile editor's universe collapsing under strict UAC: the Skills/Prompts/Agents lists
  were built from the profile-NARROWED loaded getters, so while any restrictive profile was active
  you could not see — let alone grant — currently-blocked resources, including expanding the very
  profile you were running under. Discovery is now profile-independent (full pre-filter path sets,
  mirroring the existing extensions fix), and the editor's Tools list now includes registered
  extension tools.
- Fixed profile-editor saves silently corrupting profiles: grants referenced outside the currently
  visible universe were dropped on save, and a fully-granted kind re-encoded to an omitted kind —
  which under strict UAC means DENY-ALL. Selection encode/decode is now strict-UAC-coherent
  (unmentioned decodes as denied; grant-all encodes as an explicit allow:["*"]; profile-referenced
  ids outside the visible universe survive decode/encode round-trips).
- Surfaced the silent strict-UAC denial of AGENTS.md/CLAUDE.md context files: when the active
  profile does not mention the "agents" kind, the withheld files now produce a loader warning and
  a /context dashboard observation instead of instructions vanishing without a trace.
- Fixed profile tool grants never ACTIVATING: activation was only ever the requested defaults
  intersected with the profile allow-list, so a profile granting non-default tools (e.g. a
  search-only profile allowing grep/find) produced an empty or truncated "Available tools" set on
  load and across /reload. Explicitly named tools in an active profile's allow list now activate
  from the registry (a blanket "*" stays grant-only, deriving activation from the defaults).

## [0.80.89] - 2026-07-02

### Added

- Added the brain-assisted context curator (opt-in `contextPolicy.curation` settings + Settings ->
  Context Curation submenu): a local-model sidecar that (a) writes 1-2 line semantic digests into
  Context GC's packed stubs so the main model stops re-running tools to rediscover packed content,
  and (b) scores stale artifact-backed tool outputs against the current goal so the prompt-policy
  enforcement pilot can evict irrelevant content earlier. Advisories are asymmetric by design: a
  verdict can only ever shrink the prompt, never keep or stub protected content, and every consumer
  behaves identically when a result is absent. Curation jobs are queued/bounded/idempotent, drain
  off-turn through the isolated-completion path with spawned-usage accounting, and persist auditable
  session records. The curator refuses models that have not PASSED the new `digest` fitness surface
  on this host (visible skip reasons, never silent degradation).
- Added a `digest` surface to the `model_fitness` probe: chunks carry nonce identifiers, and a
  digest only scores as faithful when strict JSON parses AND the nonce survives verbatim — measuring
  extraction fidelity, not narration.
- Added `/context`, a user-facing context composition dashboard decomposing what rides on EVERY
  request: system prompt tokens, per-tool schema costs (heaviest first), per-extension contributions,
  message classes (raw vs GC-packed vs policy-stubbed vs memory recall pages), GC/enforcement/curation
  activity, spawned background spend, and provider-reported vs estimated deltas — plus actionable
  observations (e.g. an oversized tool schema riding on every request) for users building their own
  pi integrations.
- Added `/fitness [model] [trials]` as a first-class, discoverable command: with no arguments it
  opens the model picker, runs the probe on the selection, shows the six-surface report, and then
  offers ONE-STEP role assignment — context curator, router cheap/medium/expensive tier, routing
  judge, or learning model — writing the matching settings for you (with a hint when the model
  router itself is still disabled). With an explicit model it behaves like `/autonomy fitness`.

## [0.80.88] - 2026-07-02

## [0.80.87] - 2026-07-02

### Added

- Added an opt-in Context / Prompt Policy setting that stubs stale, artifact-backed grep/find tool output
  in the model-visible prompt only (never the transcript) once configured retention-window and character
  thresholds are exceeded. Configurable via the Context / Prompt Policy settings submenu; default disabled.
- Added an opt-in Context / Memory Retrieval setting that searches local Pi OKF memory documents each turn
  and can optionally surface a bounded, source-labeled evidence block in the model prompt (never the
  transcript). Configurable via the Context / Memory Retrieval settings submenu, including a separate
  "Include in prompt" toggle; both default disabled, and retrieval only ever queries the local provider.
- Extended `context_audit` with a compact Memory retrieval / Prompt inclusion diagnostic section reporting
  status and counts for the two settings above, without exposing any memory content, query text, or file
  paths.
- Added a `goal` tool that records the durable goal ledger (goal, requirements, evidence, and
  progress/stall events) as session-persisted snapshots. This is the producer that drives the bounded
  goal continuation loop and `/goal-continue`; without it the continuation runtime always read empty
  state and could not continue. The tool is active by default and maps to the `memory_write` capability.
- Added `/autonomy diagnostics`, an effectiveness dashboard summarizing recent model-router decisions,
  current/spawned/daily cost totals, and, when present, the latest research, worker-delegation,
  learning, and goal activity. It is additive to `/autonomy [status|off|safe|balanced|full]`.
- Added the autonomous research lane runtime: an opt-in, read-only background research pass that runs
  when the session goes idle with an active goal that has open requirements, executes one bounded
  isolated completion through the (unwired-until-now) research capability/budget gate, and persists a
  provenance-tagged evidence bundle plus a terminal lane record. Budgets cover cost per pass,
  wall-clock time, findings/sources caps, and idle runs per session; failures/skips are recorded with
  reason codes and never block or prompt the foreground. Research spend reports through spawned-usage
  accounting with an idempotent per-lane report id. Configurable via the new Research Lane settings
  submenu (default disabled; also requires autonomy mode on); `/autonomy research` triggers an
  explicit pass. Live lanes now feed the previously-unset `activeLaneCount` in `/autonomy status`
  snapshots, and `/autonomy diagnostics` shows research lane records, all evidence bundles, and the
  last skip reason.
- Added the bounded worker-delegation runtime piloting read-only scout workers: a new `delegate`
  tool (active by default, mapped to the `delegate` capability, refusing with a reason until the
  Worker Delegation setting is enabled) lets the foreground model hand one self-contained analysis
  task to a worker running as a bounded isolated completion on a cheap model lane under a stripped
  read-only envelope. Every result is validated through the existing `validateWorkerResult` parent
  gate before acceptance, persisted as a worker-result snapshot plus a terminal lane record, marked
  untrusted in the tool output, and cost-reported through spawned-usage accounting with an
  idempotent per-lane report id. Budgets cover cost per worker and wall-clock time; delegation
  lanes appear in `/autonomy diagnostics` and count toward the live `activeLaneCount`.
- Added the learning apply/audit/rollback policy runtime: reflection-sourced durable writes now
  route through the (previously unwired) learning gate, persist a `LearningDecision` snapshot per
  write, and leave an audit record with a concrete rollback plan for every applied or proposed
  change. With the new Learning Policy settings disabled (default) the legacy direct-apply
  behavior is preserved — now fully audited; when enabled, single-session reflection cues become
  proposals unless the configured confidence/observation thresholds and allowed layers
  (memory-only by default) permit auto-apply. `/autonomy rollback <auditId>` (and
  `AgentSession.rollbackLearningWrite`) executes the inverse memory operation or archives a
  promoted skill, exactly once per change, and records a linked rollback audit. Audit records
  appear in the `/autonomy diagnostics` learning family.
- Added model-capability auto-detection so small open models (including sub-1B local models) stay
  usable for chat: the harness derives a capability class from the model's own `contextWindow`
  metadata — full (≥32k, unchanged), lean (≥16k, background-autonomy tools like `delegate` and
  `context_audit` blocked), minimal (≥8k, tools reduced to read/bash/edit/write, background lanes
  disabled), and chat (<8k, no tools at all). Filtering happens in `setActiveToolsByName`, so the
  system prompt sheds the blocked tools' schemas and guidelines too; the unfiltered request is
  remembered and restored when switching back to a larger model, with a visible notice on
  downgrade. Idle goal auto-continuation and the research lane are gated off below 16k
  (`model_context_too_small` in diagnostics), and lane output-token budgets scale to the lane
  model's window. Metadata-first with defaults only when info is missing (unknown window keeps
  full behavior); configurable via `modelCapability.mode` (`auto` default, `off`, or a forced
  class).
- Changed background-lane model resolution to inherit the session model the lane was shipped
  from unless a lane-specific model is explicitly configured (the router's `cheapModel` no longer
  implicitly redirects lanes) — single-model setups, e.g. one local open model, now run research
  and scout workers on that same model.
- Changed active resource profiles to strict least-privilege grants: when one or more profiles are
  active, any authority-bearing resource kind (extensions, skills, prompts, tools, agents) that no
  active profile explicitly mentions is denied outright — a defaults profile no longer loads the
  full extension/tool surface. Grant-all must be explicit via `allow: ["*"]`; explicitly written
  block-framed filters keep meaning "all except the listed"; themes are exempt; behavior without
  an active profile is unchanged.
- Changed profile denial to gate the disk reads themselves: skill files and prompt templates a
  profile denies are never read from disk (extensions were already path-filtered before loading).
  While a restrictive profile is active, denied skills/prompts consequently no longer appear in
  resource listings; edit profiles with no restrictive profile active to see everything.
- Added profile-shipped subagents: research and worker lanes accept a `profile` setting whose
  model MUST be obeyed when set (unresolvable is a visible `no_lane_profile_model` skip, never a
  fallback), whose soul and thinking level ship with the lane, and whose tool grants are recorded
  on the lane's capability envelope. Generic lanes keep inheriting the session model.
- Added a level-0 subagent system-prompt core (<300 tokens of non-negotiable rules) that survives
  ANY prompt customization: lane settings (`systemPrompt`) and the delegate tool's new
  `systemPrompt` input can erase and replace everything above it — so a big session model can
  hand a small open model a minimal purpose-built prompt without shedding the safety floor.
- Added `run_toolkit_script` (active by default, mapped to the `run_shell` capability): the
  user's blessed daily-ops script registry (`settings.toolkit.scripts` — name, description,
  aliases, uv/powershell/bash runner, danger flag) executed with a structural reliability
  contract. Finding is a conservative registry lookup that NEVER guesses between near-neighbors
  ("prepare db" vs "update-db" returns a shortlist instead of executing); the harness owns
  invocation (fixed argv, no shell strings) and always returns exit code, stdout, and stderr —
  a failed script is an error result by construction and can never look like success; scripts
  flagged `danger` never run without an explicit `confirm: true`.
- Added the `model_fitness` probe (tool + `/autonomy fitness <model> [trials]`): runs the real
  research-lane, scout-worker, and routing-judge runners plus two heavy-lifter surfaces
  (search-plan formulation, tool-call emission) against any registered model — local Ollama
  models included — reporting parse/success rates, judge discrimination, mean latency,
  tokens-per-second, and probe cost. Probe spend is cost-accounted; the tool is registered but
  not default-active. An opt-in size-class bench (`PI_LOCAL_MODEL_BENCH=1`) asserts per-class
  minimum bars for locally installed models.
- Added a host-keyed fitness store (`<agentDir>/state/model-fitness.json`): every probe persists
  its report under a hardware fingerprint (CPU/cores/RAM), because fitness is a property of a
  model ON a host — role assignments stay per-machine and synced settings cannot carry one
  machine's speed numbers onto another. `AgentSession.getStoredFitnessReports()` exposes the
  current host's measured evidence for profile/role decisions.
- Added the routing judge: with the model router enabled, a bounded routing-only completion on the
  judge lane (`modelRouter.judgeModel`, else `mediumModel`; ≤128 output tokens, 10s wall clock,
  static cached prompt) decides the final cheap/medium/expensive tier over the regex baseline —
  never the learning tier. Core rule: planning/design prompts are never cheap unless the judge
  explicitly deems them trivial; the regex classifier now also floors prospective planning prompts
  at medium (`planning_min_medium`) while plain lookups like "show me the architecture" stay
  cheap. Judge failures fall back to the baseline with visible reasons, judge spend reports
  through spawned-usage accounting, and `modelRouter.judgeEnabled: false` restores byte-identical
  router behavior.

### Changed

- Changed bounded goal continuation to default to 20 turns and auto-inject continuation prompts after a
  prompt settles idle while an active goal remains open, with internal recursion suppression for
  continuation prompts. It now also respects new settings for wall-clock budget, idle delay, and turn limits,
  which can be configured via the Autonomy submenu in the settings TUI.
- Added a third positional argument `[maxMinutes]` to the `/goal-continue` command to support bounded wall-clock loop termination.

## [0.80.86] - 2026-06-29

### Added

- Added dynamic token estimation checks for model context windows, warning the user if the base configuration (system prompt and tools) uses more than 70% of the context window.

### Fixed

- Fixed adaptive scaling of compaction parameters (`reserveTokens` and `keepRecentTokens`) for models with small context windows to avoid immediate auto-compaction loops.
- Fixed a scope redeclaration issue with `activeProfileNames` in the resource loader.
- Fixed the semantic-memory context GC never packing the recall pages the bundled default memory
  provider emits: active providers' page markers are now merged into the GC marker list at runtime
  (and the generic `<memory_context` marker joined the settings default), so stale cross-session
  recall pages no longer accumulate raw — and re-bill — for the life of the session.
- Fixed internal tool-registry refreshes (extension `refreshTools`, memory init, `/reload`,
  live extension load/unload) permanently shrinking the restorable tool set: they re-derived from
  the capability/profile-filtered ACTIVE tools instead of the pre-filter request, so switching back
  to a larger model restored only the reduced set.
- Fixed the model router judge being consulted on internally generated continuation turns (one
  judge call per loop iteration) and enforced the planning floor in code: a cheap downgrade of a
  non-cheap baseline now requires the judge's explicit `trivial` verdict.
- Fixed `model_fitness` probes: per-surface calls are now wall-clock bounded (a hung local model
  can no longer hang the probe), tokens/sec is measured in the shipped session path, and an empty
  judge prompt set no longer yields NaN latency.
- Fixed reflection learning-audit ids colliding after no-op decisions (the rollback key now counts
  only stored snapshots), which could block or misdirect `learning rollback`.
- Fixed the lane tracker growing without bound in long sessions (terminal lanes beyond 100 are
  evicted from memory; the session log keeps full history) and lane ids being reused after resume.
- Fixed toolkit script execution discarding spawn-failure diagnostics: a missing runner
  (ENOENT/EACCES) now surfaces the real cause in stderr instead of an empty `exited null`, and an
  output-overflow kill is no longer mislabeled as a timeout. Repeated words in a request no longer
  multiply the Level-0 matcher score into a false confident match.
- Fixed NaN/invalid model `contextWindow` metadata leaking into capability profiles and lane
  budgets in `off`/forced modes.


## [0.80.85] - 2026-06-29

### Fixed

- Fixed proactive cost-guard estimates treating model prices as per-token instead of per-million,
  which could show impossible per-turn warnings in the footer.
- Fixed trusted external resource-root settings profiles not constraining startup tools, preventing
  simple prompts from activating every external extension tool schema.
- Fixed active resource profiles so blocked extensions are excluded from the extension runtime itself,
  preventing their commands, tools, handlers, shortcuts, and renderers from being visible or callable.
- Fixed the no-profile default runtime to expose only Pi's built-in default tools, with extension
  commands, handlers, tools, and provider registrations disabled until an explicit profile enables them.
- Fixed profile-gated extension runtimes to preserve allowed provider-only, handler-only, shortcut-only,
  and renderer-only extensions even when the active profile also restricts tools or slash commands.
- Fixed explicit empty active profile selections so they suppress trusted external-root profile fallback.
- Fixed no-profile extension gating to preserve explicitly supplied SDK inline extension factories while still suppressing configured/discovered extensions unless a profile selects them.

## [0.80.84] - 2026-06-29

### Added

- Added a configurable `autonomy.maxStallTurns` setting, defaulting to 20, that caps foreground
  goal-loop provider rounds and is editable from `/settings` → **Autonomy**.

## [0.80.83] - 2026-06-28

### Changed

- Model Router model selection now defaults to searchable pickers populated from authenticated/configured
  provider models, with manual entry only as an explicit fallback; profile creation now also prompts for
  a profile model from the same authenticated model list.

## [0.80.82] - 2026-06-28

### Added

- Added a configurable Model Router settings submenu for cheap/research, expensive/modify, and background
  learning/reflection model roles, including project/global save scope support and profile-file
  `modelRouter` overrides for situation-specific routing.

## [0.80.81] - 2026-06-28

### Added

- Added the opt-in model-router settings shape and deterministic prompt intent classifier foundation for
  cheap/expensive model routing. When explicitly enabled with authenticated router models, read-only turns
  temporarily use the configured cheap model and modifying turns use the configured expensive model without
  persisting transient model switches; routing remains disabled by default.
- Added transcript-safe model-router escalation: cheap/research-routed turns that attempt mutating tools
  discard the cheap attempt and retry the original turn on the configured expensive model instead of
  letting a low-cost model perform write or execution work.
- Added active-session daily cost visibility: the footer now includes a `day:$...` total derived from
  same-day session logs across default project directories, including spawned/background usage reports.
- Added a daily cost breakdown to the session info surface so users can see own/session cost,
  spawned/background report cost, scanned sessions, and spawned/background report counts.
- Added model-router status to the session info surface, including enabled state, configured cheap/
  expensive models, and the latest routed or escalated decision.
- Persisted model-router routing decisions as hidden custom session entries so `/session` can show a
  short recent-decision history after session reloads.
- Added model-router routing activity/skip status to `/session`, including disabled, unresolved model,
  unset model, and missing-auth reasons.
- Added latest model-router intent visibility to `/session` so users can audit whether the last prompt was
  classified as research or modify.
- Clarified model-router `/session` status so a skipped latest prompt no longer presents an older routed
  decision as the current latest decision.
- Added model-router discoverability in the interactive settings selector by showing enabled, cheap-model,
  and expensive-model configuration together.
- Added a read-only settings selector cue naming `modelRouter.enabled`, `modelRouter.cheapModel`, and
  `modelRouter.expensiveModel` as the editable config keys.
- Added startup diagnostics for enabled model-router configs with unset, unresolved, or unauthenticated
  cheap/expensive model settings.
- Added `/usage` as a unified token, cost, background-spend, context, Auto Learn, model-router, and
  manual optimization control summary.

### Fixed

- `/exit` now behaves as a quit alias in interactive mode, and `/quit`/`/exit` bypass active streaming or
  compaction queues instead of being sent to the model as normal prompts.
- The Resources submenu now handles keyboard input correctly, so Escape/Ctrl+C can cancel nested resource
  menus and the CLI resource selector shuts down through the normal TUI cleanup path.
- Active-profile resource edits now compare resource filters by value, preserving the live extension
  load/unload path for extension-only changes instead of falling back to an unnecessary full reload.
- Model-router classification now keeps educational question prompts such as "how do I add..." or
  "what does git commit do?" on the cheap research lane while preserving explicit change requests.
- Model-router cheap-turn escalation now permits allowlisted read-only shell commands such as
  `git status`, `git diff --stat`, `pwd`, and `npm view` without retrying on the expensive model.

## [0.80.80] - 2026-06-28

### Fixed

- Resource-profile editor now lists extensions installed under external resource roots. Previously these
  extensions were loaded and active but missing from the editor's "available" list, so it showed "(none
  available)" while they ran and they couldn't be blocked or allowed per profile. The editor's universe
  and the loaded set now come from a single discovery source, so they always match.

## [0.80.79] - 2026-06-28

### Changed

- The proactive cost guard is now ON by default in warn-only mode: an unusually expensive turn (projected
  over ~$2.50) surfaces a `⚠$X/turn` indicator in the footer. It never silently changes behavior —
  auto-downgrading reasoning remains opt-in (`costGuard.action: "downgrade"`); set `costGuard.maxTurnUsd: 0`
  to disable.
- The skill curator now auto-archives stale reflection-promoted skills at session start by default
  (restorable, announced, promoted-only). Archival runs under a lock so concurrent sessions sharing an
  agent directory can't race, and every auto-archive is announced with a `/curate restore` hint. Set
  `curator.autoArchive: false` to return to propose-only (`/curate`). Hand-authored skills are never
  touched, and skill consolidation remains a suggestion you approve.

## [0.80.78] - 2026-06-28

### Fixed

- Threat scanner no longer strips legitimate international text: the invisible-character filter now
  preserves the zero-width non-joiner/joiner and left/right-to-left marks (U+200C–U+200F) that are
  load-bearing in Persian, Arabic, Hebrew, and Hindi shaping and in emoji ZWJ sequences, while still
  removing the genuinely-dangerous zero-width and bidi-reordering controls used for hidden-instruction
  ("Trojan Source") attacks.

## [0.80.77] - 2026-06-28

### Added

- Skill curator (`/curate`): reflection-promoted skills are now usage-tracked and can be reviewed instead
  of accumulating forever. `/curate` lists stale/unused promoted skills proposed for (restorable)
  archival and overlapping pairs proposed for consolidation; `/curate archive <name>` and
  `/curate restore <name>` apply them. Propose-only — nothing is archived or merged automatically, and
  hand-authored skills are never touched.

## [0.80.76] - 2026-06-28

### Added

- Proactive per-turn cost guard (opt-in): set `costGuard.maxTurnUsd` to estimate the dollar cost of each
  turn before it is submitted and, when it exceeds the ceiling, surface a warning or (with
  `costGuard.action: "downgrade"`) automatically step reasoning effort down once to curb a runaway
  billing spike. Disabled by default.

### Changed

- Background reflection now uses a static system prompt with the variable memory/turn content moved to the
  user message, so repeated reflection passes reuse the provider prompt-cache prefix instead of re-billing
  it — and added guidance to avoid persisting transient/environment-specific noise as memory.

## [0.80.75] - 2026-06-28

### Changed

- Compaction cost guard (long-session savings): compaction now also triggers once context passes a
  configurable fraction of the model's window (`compaction.triggerPercent`, default 0.7) — not only when
  it's nearly full — so per-turn input cost stays bounded on large-window models, while an anti-thrashing
  gate skips an early compaction that would barely shrink the context. The summary is now produced by a
  cheap auxiliary model when one is available (`compaction.model`, default `"auto"` picks the cheapest
  authed model that can hold the context and is cheaper than the session model; falls back to the session
  model), instead of always using the main model.

### Fixed

- Hardened context/memory threat scanning: added detection and neutralization of invisible/bidirectional
  control characters (zero-width, bidi overrides/isolates — the "Trojan Source" vector), and a broader,
  scoped pattern set. Context-file and memory reads strip hidden characters and continue; high-privilege
  memory writes are scanned in a stricter scope (exfil/backdoor/persistence patterns) and rejected
  outright.

## [0.80.74] - 2026-06-28

### Fixed

- Background-reflection debounce now defers instead of dropping (peer review): a turn skipped by the
  debounce has its text buffered and folded into the next reflection pass, so corrective feedback from
  rapid multi-turn corrections is still learned rather than lost. The buffer is size-bounded.

## [0.80.73] - 2026-06-28

### Fixed

- Cross-session recall hardening: recalled past-session pages are now injected as a GC-managed
  `<memory_context>` block (instead of a plain user message), so stale recall pages pack down over long
  sessions instead of accumulating verbatim; oversize transcript logs are skipped before parsing; and
  recall is scoped to the current working directory so transcripts from other projects can't leak in.
- Memory injection cost guard: the persistent-memory block (`MEMORY.md`/`USER.md`) injected into the
  system prompt is now capped at read time as well as on write, so a memory file bloated by an external
  edit can no longer inflate every turn's context. The file on disk is untouched and truncation is noted.
- Background reflection debounce (cost guard): native end-of-turn reflection no longer launches
  overlapping or back-to-back passes during a rapid multi-turn correction session; a minimum interval and
  an in-flight guard prevent redundant background model calls. Skipped corrections are still reflected on
  the next eligible pass over the accumulated turn text.

## [0.80.72] - 2026-06-28

### Fixed

- Long-session performance: the footer's spawned-cost total is now cached by entry count instead of re-scanning all session entries on every render frame, fixing typing lag and CPU spikes in long sessions.
- Long-session stability: disposing a session now releases the hooks it installed on the shared agent (so the session and its history can be garbage-collected) and aborts any in-flight background reflection so it can't keep spending tokens or write memory/skills against a closed session.

## [0.80.71] - 2026-06-28

### Fixed

- Security (untrusted boundary): closed a fence-spoofing bypass — closing tags in case/whitespace variants (e.g. `</UNTRUSTED_CONTENT >`) are now neutralized — and widened the set of tool names treated as untrusted (download/exec/scrape/etc.).
- Security (cross-session recall): recalled past-session text is now fenced as untrusted data so an injected payload in old history can't be replayed as a current instruction; recall pages are no longer re-indexed into the recall corpus (no recirculation).
- Memory: a remembered fact can no longer overwrite Markdown section headers; the recall-effectiveness metric no longer unfairly penalizes long snippets; situational souls follow first-wins profile precedence instead of concatenating.
- Stability: the resource catalog no longer crashes on a circular symlink (cycle-guarded hashing) and never leaves a partially-copied resource on a failed install/backup (atomic swap); gateway re-registration stops the replaced provider (no listener leak).

## [0.80.70] - 2026-06-28

### Fixed

- Reflection cost de-duplication now works on the real turn path: the per-turn key was derived from a message id that doesn't exist at runtime, so a retried/duplicate reflection pass could double-count its cost. It now uses the turn's timestamp + size.

## [0.80.69] - 2026-06-28

### Added

- Configurable reflection model: the native reflection engine now uses the `autoLearn.model` / `autoLearn.thinkingLevel` settings (a `--model` pattern, e.g. a balanced or cheaper model) instead of always using the session model. The configured model is honored only when its provider is available (api key / logged in); otherwise it falls back to the session model.

## [0.80.68] - 2026-06-27

### Added

- Resource catalog (round resource management): point pi at a catalog directory of skills/extensions/agents/prompts/themes and install them into your pi user level. `update` hash-compares what you've installed against the catalog and re-syncs only the changed ones (and only what you chose on this machine); `backup` copies a user-level resource back into the catalog. Content-hash based, so it's portable across machines.

## [0.80.67] - 2026-06-27

### Added

- Untrusted-content boundary (security): output from attacker-controllable sources (web/search, subagents, recall, third-party tools) is now structurally fenced in `<untrusted_content>` tags with a random nonce and break-out neutralization, plus an always-on system-prompt rule that the agent must treat such content as data, never instructions — and that boundary actions always need human approval. First-party tools (read/grep/find/ls/edit/write/bash) are trusted and unwrapped.

## [0.80.66] - 2026-06-27

### Added

- Gateway & scheduler provider interfaces: pi now exposes `ChannelProvider` (transports) and `JobSchedulerProvider` (cron) contracts plus a registry, so a deployment/server wrapper can plug in channels and scheduled jobs without baking any transport into the core agent.

## [0.80.65] - 2026-06-27

### Added

- Memory-to-behavior: the reflection engine can now promote a recurring, multi-step procedure it learned into an executable skill (a generated SKILL.md under your skills directory), so lessons become reusable behavior instead of just remembered facts.

## [0.80.64] - 2026-06-27

### Added

- Situational profiles (souls): a resource profile can now define a `soul` — a situational identity injected into the system prompt while the profile is active — so switching a profile switches the agent's identity, capabilities, and model together as one "situation".

## [0.80.63] - 2026-06-27

### Changed

- Persistent memory no longer accumulates duplicate facts: when a remembered fact restates an existing one, it supersedes that line in place instead of piling up (anti append-rot).

## [0.80.62] - 2026-06-27

### Added

- Adaptive recall feedback: pi now tracks whether the cross-session context it recalled was actually used in its answer, and tunes how eagerly it recalls — leaning in when recall helps, backing off when it doesn't.

## [0.80.61] - 2026-06-27

### Added

- Cross-session memory recall: pi now indexes your recent past sessions (same project) and, when a turn is relevant, injects a small read-only recall page from that history — so it can draw on what you did before without you re-explaining. Local, dependency-free, and scoped to the current working directory; the current session and background-learning sessions are excluded.

## [0.80.60] - 2026-06-27

### Fixed

- Resource profiles are now the final authority everywhere: a profile-blocked skill, prompt, theme, or extension can no longer be selected or invoked by the user or the agent — including after a runtime profile switch. Skills/prompts/themes load fully (so the profile editor can show them) but are filtered at every use surface; extensions stay load-gated (a blocked extension is never loaded or allowed to run).
- The profile resource editor can now be cancelled/aborted (Ctrl+Q / Esc / interrupt) without saving; the footer advertises it.

### Added

- The system prompt now lists the agent's loaded capabilities — active skills, tools, and extensions (with names and descriptions) — so the agent can answer "list your capabilities" accurately. Extensions show a real name/description instead of `index.ts`.

## [0.80.59] - 2026-06-27

### Added

- Native reflection engine: when auto-learn is enabled, pi now learns in-process at the end of a turn (demand-gated, cheap model) and writes durable lessons via the `memory` tool, replacing the external continuous-learning subprocess. Set `PI_NATIVE_REFLECTION=0` to fall back to the legacy path.
- `AgentSession.runIsolatedCompletion(...)`: a one-shot LLM call fully isolated from the session (no history/log/tool mutation, no prompt-cache churn) — the primitive the reflection engine runs on.

## [0.80.58] - 2026-06-27

### Added

- Cost aggregation: the footer now rolls up the cost of spawned/subagent sessions into the displayed cost (e.g. `$0.842 (+$0.310 sub)`). Spawned usage is persisted per session and survives reload.
- Extension API `pi.reportSpawnedUsage(usage, opts?)` so extensions that spawn pi (subagents, learners) can report a child's cost up to the parent footer.
- Print mode emits a child's cumulative usage so a spawner can roll it up: a terminal `{type:"result", usage}` event in `--mode json`, and an opt-in `--print-usage` line (`__PI_USAGE__` prefix on stderr) in text mode.

## [0.80.57] - 2026-06-27

## [0.80.56] - 2026-06-27

## [0.80.55] - 2026-06-27

## [0.80.54] - 2026-06-27

## [0.80.53] - 2026-06-27

## [0.80.52] - 2026-06-26

## [0.80.51] - 2026-06-26

## [0.80.50] - 2026-06-26

### Fixed

- Resolved the active profile's model and thinking level at startup (both headless and interactive) when no explicit CLI `--model` or `--thinking` flags are passed.
- Handled profile model resolution failures gracefully by falling back to default/available models and issuing a warning rather than crashing.

## [0.80.49] - 2026-06-26

### Added

- Added Edit-in-$EDITOR action (key `e`) in the Manage Library browser to directly edit the highlighted resource's source file and reload upon return.
- Added consistent "Profile / Situation" labeling across all settings selectors.
- Added friendly empty-state messaging in kind tabs with no available resources.

## [0.80.48] - 2026-06-26

### Added

- Consolidated `/settings` profile and source configuration under a single `Resources` hub with a first-run catalog nudge.
- Implemented the unified `Manage Library` browser and editor featuring allow/block list toggling, fuzzy description search, missing items detection, and live reload on save.


## [0.80.47] - 2026-06-26

### Added

- Exposed effective external resource roots to extensions via `getExternalResourceRoots()` on `ExtensionAPI`.
- Added `/install-resources <dir> [--force]` slash command to copy resources from trusted directories to user local settings.
- Added `/config-backup [file]` and `/config-restore <file>` slash commands to package/restore profiles and resource settings.

## [0.80.46] - 2026-06-26

### Added

- Added support for configuring `externalResourceRoots` and `trustedResourceRoots` to scan and load external directories for skills, extensions, prompts, themes, and profiles.
- Added `/settings → Sources` UI to manage (add, trust, and remove) external resource roots.

## [0.80.45] - 2026-06-26

### Added

- Added an always-available "Create profile" flow in `/settings` that prompts for a new profile name, validates it, opens the resource editor, and persists the new profile to `~/.pi/agent/profiles/`.


## [0.80.44] - 2026-06-26

### Fixed

- Updated stale `auto-learn-spawn` and `system-prompt` tests that asserted pre-token-reduction prompt content and a hardcoded complex-task threshold, so they match the current condensed system prompt and the configurable `complexTaskToolCalls` setting. Unblocks the CI publish gate.

## [0.80.43] - 2026-06-26

### Added

- Added reusable runtime profile files under `~/.pi/agent/profiles/` and an interactive `/profiles` session switcher backed by the existing resource-profile filters.
- Added a profile resource editor and management UI under `/settings → Profiles`: per-kind allow/block tick-lists (tools, skills, extensions, agents, prompts, themes), persist the active profile to a chosen scope, and delete profiles.
- Added live per-extension load/unload: toggling an extension in the active profile loads/unloads it in-session without a full reload (with an `onDispose` hook, per-extension provider cleanup, module cache-bypass, and a full-reload fallback).
- Added bundled default skills (`skill-architect`, `pi-harness-learning`) shipped with the package at lowest precedence, discoverable and profile-filterable like user skills.
- Added a `skill_audit` tool that flags near-duplicate skills via a dependency-free Jaccard heuristic, and exported the `runSkillAudit`/`tokenize`/`jaccard` primitives from the package entry for extension reuse.
- Added `/skillify`, `/extensionify`, and `/learn` self-adaptation commands plus pure model-callable `skillify`/`extensionify` proposal tools (validate/audit or isolated smoke-test; persistent writes happen only at the main-session prompt layer behind explicit user confirmation).

## [0.80.42] - 2026-06-24

## [0.80.41] - 2026-06-24

### Changed

- Changed auto-compaction to honor a model-specific `autoCompactionTriggerTokens` threshold when set, compacting at the lower of that value and `contextWindow - reserveTokens`. Fugu and Fugu Ultra now auto-compact around 272000 tokens instead of effectively waiting for the 1,000,000 context window.

## [0.80.40] - 2026-06-24

### Fixed

- Fixed Auto Learn prompt construction in lightweight harnesses so self-modification source resolution falls back safely when no full session manager is present.

## [0.80.39] - 2026-06-24

### Changed

- Strengthened the adaptive core prompt with tool-first deterministic-work routing, evidence-backed correction handling, and current-information honesty.

## [0.80.38] - 2026-06-24

### Added

- Added Fugu provider selection, API-key setup docs, and default model routing.

## [0.80.34] - 2026-06-21

### Fixed

- Fixed release cleanliness by generating image model metadata in the same formatted shape enforced by CI, so binary publish jobs do not dirty `image-models.generated.ts`.

## [0.80.33] - 2026-06-21

### Fixed

- Fixed the hot-reload safety regression test to mutate agent streaming state through a typed test-only shim, allowing release CI type checks to pass while keeping runtime state readonly.

## [0.80.32] - 2026-06-21

### Added

- Added code-baked Auto Learn review triggers for corrective, self-improvement, and complex tool-use turns so reusable behavior is steered toward auditable skills/prompts/agents/extensions/source changes instead of memory-only drift.

### Fixed

- Made extension-triggered hot reload UI-safe: `ctx.reload()` now refuses to run while the agent is streaming, a tool call is active, or context compaction/branch summarization is in progress, preserving the current TUI/session instead of racing reload through an active turn.

## [0.80.31] - 2026-06-19

## [0.80.30] - 2026-06-19

### Added

- Added deterministic improvement-loop helpers for metric-based keep/discard decisions, sandbox worktree creation, sandbox measurement, patch export, and cleanup.
- Tightened adaptive self-evolution prompt guidance around sandbox-first mutation, validation, and durable evidence capture.

### Changed

- Optimized semantic context GC membership and planning, including marker-first semantic scans that avoid unnecessary string joins.

## [0.80.29] - 2026-06-18

### Added

- Added OpenRouter Fusion as a selectable OpenRouter model alias.

### Fixed

- Fixed large `bash` and filtered-git output handling to keep live previews, truncation snapshots, and terminal rendering bounded by the visible output budget instead of accumulated command history.
- Fixed bash full-output temp-file cleanup so disk/close failures do not leak file descriptors or mask the original command failure.
- Fixed OpenAI/Azure/Codex Responses providers to send system context through top-level `instructions` and require terminal response events before accepting streamed output.
- Fixed provider HTTP error reporting to include structured response bodies where available.
- Fixed streaming markdown code fences so partial closing fences do not temporarily render as shrinking code content.

## [0.80.28] - 2026-06-18

## [0.80.25] - 2026-06-14

### Fixed

- Fixed package repository metadata so npm provenance publishing matches the fork repository.

## [0.80.24] - 2026-06-14

### Added

- Added resource profiles for scoped loading of extensions, skills, prompt templates, themes, context agent files, and tools, including zero-footprint user-level directory overlays and one-shot profile definitions.
- Added embedded `<resource-profile>` blocks for extensions, prompt templates, skills, and context agent files; profile blocks are parsed as config and stripped from prompt-facing content.

### Changed

- Updated Pi Adaptative README copy to state the fork credit, purpose, and compatibility mode plainly.

## [0.80.23] - 2026-06-12

### Fixed

- Fixed JavaScript heap exhaustion in long-running sessions by bounding in-memory retention across the stack:
  - Session load now compacts oversized tool result details, so resuming or branching on top of large session files no longer pins their full payloads in memory.
  - Interactive scrollback components retain tool result details under a dedicated budget (512KB estimate per result), matching resumed-session semantics for pathological payloads while keeping designed display payloads (bash output window, diffs) intact.
  - Scrollback components share one built-in toolset per working directory instead of allocating a full toolset per tool call.
- Bounded subprocess output retention:
  - `pi.exec`/`execCommand` keeps a rolling tail per stream (default 16 MiB, configurable via `maxBuffer`) and reports `stdoutTruncated`/`stderrTruncated` on the result.
  - The git output filter spills oversized git output (default over 48 MiB, `PI_GIT_FILTER_MAX_RETAINED_BYTES` to tune) to a temp file, discloses the cap in the filtered output, and reuses the spill file as the full-output artifact instead of materializing extra in-memory copies.
  - Package manager command capture is bounded and fails loudly instead of accumulating unbounded output.
- Hot reload now unsubscribes the replaced extension generation's `pi.events` handlers from the shared event bus, so repeated reloads no longer pin old extension module graphs or double-process bus events.
- Fixed abort-listener accumulation in retry backoff sleeps (`utils/sleep.ts` and the openai-codex provider): each completed sleep now detaches its listener instead of leaving it on the signal for the signal's lifetime.
- Best-effort temp-file writes (bash full-output capture, git filter overflow spill) now handle stream errors instead of crashing the process with an uncaught `error` event on disk failures; the git overflow path discloses a failed spill in stderr instead of referencing a broken artifact.
- Session file rewrites (migration, branch operations) are now atomic (write-then-rename), removing the torn-file window when a crash or a second pi process appending to the same session interleaves with a truncate-in-place rewrite.
- Codex websocket debug stats and SSE-fallback flags are now cleared with the rest of the session resources on session replacement and dispose, instead of accumulating per session id for the process lifetime.
- User input during an auto-retry backoff now queues as steering and is incorporated into the retried turn, instead of starting a concurrent run that raced and cancelled the pending retry. `isRetrying` is true from the moment `auto_retry_start` is observable, and the interactive editor routes submissions during the retry window through the steering path.
- Oversized reads no longer spike the heap: the read tool streams line slices for files beyond 16 MiB (any region stays reachable in batches via offset continuation, with true line numbers), images beyond a 128 MiB pathology guard return guidance instead of loading, CLI `@file` attachments are bounded with a leading window plus a read-tool pointer, oversized SKILL.md files are skipped with a diagnostic, and the session loader skips lines too large to hold in a string instead of failing the whole resume.
- Delimiter-less streams can no longer grow line-assembly buffers without bound: RPC JSONL input, the Anthropic SSE parser, and the Codex SSE parser each cap their buffers (64 MiB) and discard or fail cleanly.
- Hot reload no longer freezes the UI: the chat scrollback rebuild is chunked with yields (also applies to resume, tree navigation, and display toggles). Plain Up arrow on an empty editor recalls queued messages for editing, and a `>>` prefix queues a follow-up message — both work in terminals that swallow the alt-chord bindings.

## [0.80.22] - 2026-06-12

### Added

- Added explicit `disabledResources` settings for reversible user/project resource unload filters across extensions, skills, prompts, and themes.
- Documented resource include/exclude patterns for extension and skill loading.

## [0.80.20] - 2026-06-10

### Fixed

- Fixed sluggish terminal rendering in long sessions caused by per-frame width measurement of the entire scrollback buffer.

## [0.80.19] - 2026-06-08

### Fixed

- Renamed internal package imports to the `@caupulican` scope and publish direct `@caupulican/*` dependencies instead of npm alias dependencies.
- Removed local release compatibility symlink creation now that package names match the published scope.

## [0.80.18] - 2026-06-08

### Fixed

- Queued steering without aborting active assistant output, so user steering and busy-session wake messages do not interrupt the current stream.
- Loaded extensions from linked global installs by resolving package aliases from both the symlinked loader path and the real source path.
- Added workspace and local-release compatibility links so both fork package names and upstream Pi import names resolve through `node_modules` during installation smoke tests.

## [0.80.17] - 2026-06-07

### Fixed

- Added background script result aliases from job id and name, so follow-up status/log calls reuse the original start panel even when the job's generated id differs from the friendly start name.

## [0.80.16] - 2026-06-07

### Fixed

- Reused active background script panels for same-turn repeated start/status/logs calls, so a model-issued status burst for one job still refreshes one TUI row instead of appending duplicates.
- Queued compaction messages with steering/follow-up behavior when auto-compaction finishes while the agent is still processing, avoiding the internal `streamingBehavior` error and duplicate restored queue display.

## [0.80.15] - 2026-06-08

### Fixed

- Reused background script job panels in place for repeated start/status/logs calls with the same job name/id, so long-running script status refreshes one persistent TUI line instead of appending repeated rows.

## [0.80.14] - 2026-06-08

### Fixed

- Folded overlapping Auto Learn and continuous-learning footer statuses into one compact `learn:<phase>` chip, preventing duplicate `(learning) (learning)` indicators while keeping phase context.

## [0.80.13] - 2026-06-08

### Fixed

- Reduced automatic Auto Learn TUI noise by hiding model/log-path startup status from routine learner launches, showing only a compact `(learning)` footer marker while active, clearing it when done, and spawning learners with `xhigh` thinking.

## [0.80.12] - 2026-06-07

## [0.80.11] - 2026-06-07

### Changed

- Made centralized TUI title badges use theme-balanced state colors for running, success, warning, persistent, failure, blocked, and muted states.
- Updated tool execution fallback labels to show status colors instead of forcing the neutral tool-title color.

## [0.80.8] - 2026-06-04

### Changed

- Restored skill prompt metadata so available skills include names and descriptions as well as lazy-load locations, making automatic skill selection effective again.
- Scoped Auto Learn learner concurrency and artifacts per session tenant, cleaned successful worker artifacts after exit, while keeping shared state for visibility, and made reload blockers ignore Auto Learn workers by default.
- Tightened Auto Learn instructions around memory-first, chunked/vectorized candidate validation using the benefit/uniqueness/agent-improvement tree.

## [0.80.7] - 2026-06-03

### Added

- Added provider-only CLI startup, friendly ChatGPT/Claude provider aliases, direct `/login [provider]` and `/logout [provider]` commands, and docs/tests for running concurrent Pi instances with different subscription providers.

## [0.80.6] - 2026-06-03

### Fixed

- Fixed Auto Learn background learner startup so prompt content is passed by file instead of argv, preventing null-byte turn digests from crashing interactive Pi, serialized shared learner state updates across sessions/tenants, hid internal Auto Learn sessions from resume/all session lists, and enforced 7-day retention for internal Auto Learn prompts/logs/session history plus processed provider/user history after indexed extraction and learning-outcome evidence.
- Changed image paste to use `alt+v` by default and made missing clipboard images a silent no-op so normal terminal text paste no longer raises a noisy “No image found” status.

## [0.80.5] - 2026-06-03

### Added

- Added reload-blocker helpers for extensions to describe active Pi auto-reload blockers with pid, cwd, and session-file details.

### Fixed

- Made Auto Learn background sessions use dedicated session ids/directories and surfaced active Pi auto-reload blockers in `/auto-learn status`.

## [0.80.4] - 2026-06-02

### Added

- Added terminal clipboard image paste attachment handling so pasted images are sent as model image inputs instead of temp-file path text.

## [0.80.3] - 2026-06-02

### Fixed

- Fixed startup fallback when optional built-in theme assets are unavailable or invalid.

## [0.80.2] - 2026-06-02

### Added

- Added the built-in `matrix-machine` green/blue machine theme.
- Added `ctx.mode` to extension contexts so extensions can distinguish `tui`, `print`, and `rpc` runtimes.

### Fixed

- Fixed footer branch refresh on WSL `/mnt/<drive>` repositories by polling `.git/HEAD` in addition to file watching.
- Fixed provider compatibility via inherited `@caupulican/pi-ai` OpenRouter and Amazon Bedrock request handling updates.

## [0.80.1] - 2026-06-01

### Changed

- Enabled grouped interactive tool panels by default for all tools, while preserving explicit cross-tool grouping and blank-string opt-out.

## [0.80.0] - 2026-06-01

### Added

- Added low-config autonomy presets via `autonomy.mode` and `/autonomy status|off|safe|balanced|full`; `full` now means standing autonomy with post-turn reflection whenever concurrency allows, plus grants for memory, skills, user/project extensions/tools, autonomy tuning, and authorized self-modification source edits while keeping publish/push/tag/release/credential/destructive actions foreground-approval gated.
- Added Auto Learn reflection review: when Auto Learn/autonomy is enabled, Pi can launch a bounded background learner after corrective or complex tool-heavy turns, with separate cooldown/status reporting and authority instructions derived from `autonomy.mode`.

### Security

- Added prompt-injection/exfiltration scanning for eagerly injected `AGENTS.md`, `CLAUDE.md`, and `GEMINI.md` context files; suspicious files are replaced with a blocked notice instead of entering the system prompt.

## [0.79.0] - 2026-06-01

### Added

- Added interactive `/settings` controls for Pi self-modification and Auto Learn, including global/project save scopes, source-path validation, configured-account model selection, `/auto-learn status`, `/auto-learn run`, and an idle background Auto Learn scheduler.

## [0.78.4] - 2026-06-01

### Changed

- Restored eager startup injection for `AGENTS.md`, `CLAUDE.md`, and `GEMINI.md` context files; lazy startup loading now applies to skills and agent resources only.

### Fixed

- Restored extension `context` handlers in the agent context transform pipeline after auto-compaction support.
- Updated package-command and pending-tool panel regression coverage for the Pi Adaptative command name and reusable tool-panel registry.

## [0.78.3] - 2026-06-01

### New Features

- **Lazy startup resources** - Skills and context files are listed by location only and loaded on demand, avoiding startup prompt pollution. See [Skills](docs/skills.md#how-skills-work) and [Context Files](docs/usage.md#context-files).
- **Cleaner interactive tool panels** - Repeated tool actions reuse session-scoped panels, related exploration calls can collapse into grouped summaries, and file tool titles prefer shortened relative paths.

### Added

- Added a built-in `llama-cpp/local` model profile for local llama.cpp servers, available without API-key setup.
- Added a `model_selector_open` extension event so extensions can refresh or register models before the interactive selector loads.
- Added raw prompt-template argument placeholders (`$ARGUMENTS_RAW` and `$RAW_ARGUMENTS`).
- Added optional session names for `/new <name>`, `/clone <name>`, and `/fork <name>`.
- Added `selfModification.enabled` and `selfModification.sourcePath` settings with system-prompt guardrails for Pi harness self-modification.
- Added `autoLearn` settings for autonomous, model-selected background learning on long sessions.
- Added session-scoped grouped tool panel helpers so compatible tools can collapse related actions into reusable TUI panels.
- Added lazy startup prompt listings for skill and context-file locations without injecting skill frontmatter or AGENTS/CLAUDE contents.

### Fixed

- Fixed session listing/resume metadata loading to stream large JSONL files instead of reading each file fully into memory.
- Fixed pre-prompt auto-compaction so it does not run an empty continuation before sending the user's pending prompt.
- Fixed default session directory encoding to avoid cwd collisions while still reading legacy session directories.
- Fixed extension overlay focus restoration so closing editor replacement UI does not steal focus from an active overlay.
- Fixed the footer to display model override names instead of always showing raw model IDs.
- Fixed extension tool fallback titles to prefer human-readable labels instead of raw internal tool names.
- Fixed repeated file/status tool rendering to reuse session-scoped panels for the latest distinct action instead of adding a new raw line each time.
- Fixed built-in file tool panels to prefer shortened cwd-relative path display, including `../../` parent traversals when shorter.
- Fixed OpenAI-compatible, Anthropic, and Amazon Bedrock provider fixes inherited from `@caupulican/pi-ai`.

## [0.78.1] - 2026-05-31

### Changed

- Changed OpenAI Codex Responses SSE response-header timeout default inherited from `@caupulican/pi-ai` from 10s to 20s.

## [0.78.0] - 2026-05-29

### New Features

- **Named startup sessions** - `--name` / `-n` sets the session display name before startup across interactive, print, JSON, and RPC modes. See [Naming Sessions](docs/sessions.md#naming-sessions) and [Session Options](docs/usage.md#session-options).
- **Clickable file tool paths** - built-in file tool titles render OSC 8 `file://` hyperlinks when the terminal supports them, including supported tmux clients.

### Added

- Exported `convertToPng` for extension authors ([#5167](https://github.com/earendil-works/pi-mono/pull/5167) by [@xl0](https://github.com/xl0)).
- Exported `parseArgs` and type `Args` for extension authors ([#5202](https://github.com/earendil-works/pi-mono/pull/5202) by [@xl0](https://github.com/xl0)).
- Added `--name` / `-n` to set the session display name at startup ([#5153](https://github.com/earendil-works/pi-mono/issues/5153)).
- Added a resume command hint when exiting interactive sessions ([#5176](https://github.com/earendil-works/pi-mono/pull/5176) by [@yzhg1983](https://github.com/yzhg1983)).
- Added OSC 8 `file://` hyperlinks to file paths shown in built-in file tool titles ([#5189](https://github.com/earendil-works/pi-mono/pull/5189) by [@mpazik](https://github.com/mpazik)).
- Added custom Amazon Bedrock request header support inherited from `@caupulican/pi-ai` ([#5178](https://github.com/earendil-works/pi-mono/pull/5178) by [@stephanmck](https://github.com/stephanmck)).

### Fixed

- Clarified the WezTerm/WSL IME hardware cursor docs to state that cursor visibility remains opt-in ([#5200](https://github.com/earendil-works/pi-mono/issues/5200)).
- Fixed the GitLab Duo custom provider example to use adaptive thinking for Claude models, expose xhigh thinking, and include newer verified model IDs ([#5201](https://github.com/earendil-works/pi-mono/issues/5201)).
- Fixed Bun release archive creation to install and copy the matching `@mariozechner/clipboard` base package and native sidecars ([#5184](https://github.com/earendil-works/pi-mono/issues/5184)).
- Fixed early interactive input typed before the prompt loop starts so it is buffered instead of dropped ([#5195](https://github.com/earendil-works/pi-mono/pull/5195) by [@yzhg1983](https://github.com/yzhg1983)).
- Fixed OpenRouter Moonshot Kimi K2.6 requests to use `system` instead of unsupported `developer` messages ([#5159](https://github.com/earendil-works/pi-mono/issues/5159)).
- Fixed OpenCode Go Kimi K2.6 thinking requests to send `thinking` objects instead of invalid string values, and fixed OpenCode Zen Grok Build thinking requests to omit unsupported `reasoning_effort` ([#5169](https://github.com/earendil-works/pi-mono/issues/5169)).
- Fixed OpenAI Codex Responses SSE streams to abort response body reads after terminal events.
- Fixed OpenCode Kimi K2.6 generated metadata to use Anthropic-style thinking metadata instead of invalid reasoning-effort parameters.
- Fixed OSC 8 hyperlinks to pass through tmux when the client supports them ([#5189](https://github.com/earendil-works/pi-mono/pull/5189) by [@mpazik](https://github.com/mpazik)).
- Fixed ANSI text wrapping to avoid stack overflows on very long wrapped lines ([#5185](https://github.com/earendil-works/pi-mono/issues/5185)).

## [0.77.0] - 2026-05-28

### New Features

- **Claude Opus 4.8 support** - Adds Anthropic Claude Opus 4.8 metadata and updates Opus adaptive-thinking coverage.
- **Selective tool disablement** - `--exclude-tools` / `-xt` disables specific built-in, extension, or custom tools while leaving the rest available. See [Tool Options](docs/usage.md#tool-options).
- **Headless Codex subscription login** - `/login` can use device-code auth for ChatGPT Plus/Pro Codex subscriptions. See [Subscriptions](docs/providers.md#subscriptions) and [OpenAI Codex](docs/providers.md#openai-codex).
- **Streaming-aware extension input** - extensions can distinguish idle prompts, mid-stream steers, and queued follow-ups with `InputEvent.streamingBehavior`. See [Input Events](docs/extensions.md#input-events).

### Added

- Added `--exclude-tools` / `-xt` to disable specific built-in, extension, or custom tools while leaving the rest available ([#5109](https://github.com/earendil-works/pi/issues/5109)).
- Added OpenAI Codex subscription device-code login as a selectable headless alternative while keeping browser login as the default ([#4911](https://github.com/earendil-works/pi/pull/4911) by [@vegarsti](https://github.com/vegarsti)).
- Added `streamingBehavior` to extension input events so extensions can distinguish idle prompts from mid-stream steers and queued follow-ups ([#5107](https://github.com/earendil-works/pi/pull/5107) by [@DanielThomas](https://github.com/DanielThomas)).
- Added Claude Opus 4.8 model metadata for Anthropic and updated Opus adaptive-thinking coverage to use it.

### Fixed

- Fixed startup timing output so `readPipedStdin` no longer includes `createAgentSessionRuntime` work ([#4829](https://github.com/earendil-works/pi/issues/4829)).
- Fixed OpenRouter DeepSeek V4 `xhigh` reasoning metadata to preserve OpenRouter's native effort instead of sending DeepSeek's `max` effort ([#4801](https://github.com/earendil-works/pi/issues/4801)).
- Fixed custom session directories so current-folder resume/continue lookups stay scoped to the active cwd while all-session listings cover the custom directory.
- Fixed SIGTERM/SIGHUP exits to run extension `session_shutdown` cleanup and restore the terminal: signal-triggered shutdown now emits `session_shutdown` before any terminal writes, and SIGHUP no longer hard-exits, so extension resources (e.g. sockets) are released even when the terminal is gone ([#5080](https://github.com/earendil-works/pi/issues/5080)).
- Fixed keyboard protocol negotiation to ignore mismatched or delayed terminal responses, avoiding false Kitty keyboard protocol detection ([#5091](https://github.com/earendil-works/pi/pull/5091) by [@mitsuhiko](https://github.com/mitsuhiko)).
- Fixed Windows startup crashes under MSYS2 ucrt64 Node.js by updating the native clipboard addon to napi-rs 3.x ([#5028](https://github.com/earendil-works/pi/issues/5028)).
- Fixed API key and header config resolution to treat plain strings as literals, support `$ENV_VAR` / `${ENV_VAR}` interpolation and `$!` bang escaping, and require explicit env syntax for config files, avoiding Windows case-insensitive env matches corrupting literal keys ([#5095](https://github.com/earendil-works/pi/issues/5095)).
- Fixed session disposal to abort in-flight agent, compaction, branch summary, retry, and bash work ([#5029](https://github.com/earendil-works/pi/pull/5029) by [@TerminallyChilI](https://github.com/TerminallyChilI)).
- Fixed `pi.getAllTools()` to expose each tool's `promptGuidelines` for extensions that need per-tool guideline attribution ([#4879](https://github.com/earendil-works/pi/issues/4879)).
- Fixed OpenAI Codex Responses replay after switching from Anthropic extended-thinking sessions by generating unique fallback message item IDs for converted thinking/text blocks ([#5148](https://github.com/earendil-works/pi/issues/5148)).
- Fixed Anthropic-compatible replay for providers that return empty thinking signatures by adding an opt-in `allowEmptySignature` compatibility flag ([#4464](https://github.com/earendil-works/pi/issues/4464)).
- Fixed OpenAI and OpenRouter GPT-5.5 Pro thinking level metadata to expose only supported medium, high, and xhigh efforts.
- Fixed OpenCode Go Kimi K2.6 thinking-off requests to send `thinking: "none"` ([#5078](https://github.com/earendil-works/pi/issues/5078)).
- Fixed Xiaomi Token Plan model metadata to omit unsupported `mimo-v2-flash` variants ([#5075](https://github.com/earendil-works/pi/issues/5075)).
- Fixed follow-up messages queued by `agent_end` extension handlers to drain before the agent becomes idle ([#5115](https://github.com/earendil-works/pi/pull/5115) by [@DanielThomas](https://github.com/DanielThomas)).
- Fixed extension input events to report `streamingBehavior` only for prompts actually queued during streaming ([#5107](https://github.com/earendil-works/pi/pull/5107) by [@DanielThomas](https://github.com/DanielThomas)).
- Fixed system prompt tool-selection guidance to avoid preferring unavailable file exploration tools ([#5132](https://github.com/earendil-works/pi/issues/5132)).
- Fixed fenced `diff` code blocks and other highlight.js scopes to keep theme-aware syntax colors after the `cli-highlight` replacement ([#5092](https://github.com/earendil-works/pi/issues/5092)).

## [0.76.2] - 2026-05-28

### Added

- Added richer built-in file-tool controls for `read`, `grep`, `find`, and `ls`, including line-numbered and tail reads, safe filtered reads, grouped search/list summaries, optional metadata, and clearer limit/truncation notices.
- Added conservative git output filtering for bash/RPC command paths, with explicit opt-outs for unfiltered git output.

### Fixed

- Fixed text file edits to refuse invalid UTF-8 inputs before mutating files and updated writes to preserve existing UTF-8 BOM and CRLF line endings where applicable.

## [0.76.1] - 2026-05-27

### Fixed

- Fixed Pi Adaptative update checks and Bun binary fallback instructions to use the `Caupulican/pi-adaptative` package/release locations instead of upstream Pi endpoints.

## [0.76.0] - 2026-05-27

### New Features

- **Explicit session IDs for automation** - `--session-id <id>` lets scripts create or resume an exact project-local session. See [Sessions](docs/usage.md#sessions).
- **RPC bash output can stay out of model context** - RPC clients can pass `excludeFromContext` to `bash` for commands whose output should not be sent with the next prompt. See [RPC mode](docs/rpc.md#bash).
- **More predictable provider retries and timeouts** - Codex WebSocket/SSE waits are bounded, and `retry.provider.maxRetries` controls provider retries instead of hidden SDK defaults. See [Retry settings](docs/settings.md#retry).
- **Better terminal editing across environments** - Apple Terminal Shift+Enter, Windows/JetBrains capability detection, and Unicode-aware word navigation improve interactive editing. See [Terminal setup](docs/terminal-setup.md) and [Keybindings](docs/keybindings.md).

### Added

- Added `--session-id` to let CLI callers use an exact project-local session ID, creating it if missing ([#4874](https://github.com/earendil-works/pi/issues/4874)).
- Added `excludeFromContext` flag to the `bash` RPC command for parity with the internal `executeBash` API ([#5039](https://github.com/earendil-works/pi/issues/5039)).

### Fixed

- Fixed user message transcript rendering to preserve user-authored ordered-list markers ([#5013](https://github.com/earendil-works/pi/issues/5013)).
- Fixed self-update commands to bypass npm, pnpm, and Bun minimum release age gates for explicit `pi update` runs ([#4929](https://github.com/earendil-works/pi/issues/4929)).
- Fixed context token estimates to count user image attachments consistently with tool result images ([#4983](https://github.com/earendil-works/pi/issues/4983)).
- Fixed `httpIdleTimeoutMs` to apply to OpenAI Codex Responses WebSocket idle waits, added `websocketConnectTimeoutMs` for bounded WebSocket connect waits, and added a 10s Codex SSE response-header timeout ([#4945](https://github.com/earendil-works/pi/issues/4945)).
- Fixed `RpcClient` to reject pending requests and consume stdin pipe errors when the child process exits unexpectedly ([#4764](https://github.com/earendil-works/pi/issues/4764)).
- Fixed managed npm extension updates to avoid package managers installing or resolving pi host packages as peer dependencies ([#4907](https://github.com/earendil-works/pi/issues/4907)).
- Fixed RPC mode raw stdout writes to retry transient backpressure errors and flush queued protocol output during shutdown ([#4897](https://github.com/earendil-works/pi/issues/4897)).
- Fixed OpenAI Codex Responses cache-affinity headers to send `session-id` instead of proxy-incompatible `session_id` ([#4967](https://github.com/earendil-works/pi/issues/4967)).
- Fixed `openai-codex/gpt-5.3-codex-spark` model metadata to use its 128k context window ([#4969](https://github.com/earendil-works/pi/issues/4969)).
- Fixed OpenRouter/Poolside context overflow detection for `maximum allowed input length` errors ([#4943](https://github.com/earendil-works/pi/issues/4943)).
- Fixed provider retry controls so `retry.provider.maxRetries` is honored, SDK retries default to `0`, and quota/billing 429s are not retried behind Pi's retry handling ([#4991](https://github.com/earendil-works/pi-mono/pull/4991) by [@mitsuhiko](https://github.com/mitsuhiko)).
- Fixed Apple Terminal `Shift+Enter` by detecting local macOS modifier state when Terminal.app sends plain Return.
- Fixed Windows Terminal capability detection to enable OSC 8 hyperlinks, preserving clickable long URLs across wrapped lines ([#4923](https://github.com/earendil-works/pi/issues/4923)).
- Fixed JetBrains terminal capability detection to enable truecolor while disabling unsupported OSC 8 hyperlinks ([#5037](https://github.com/earendil-works/pi-mono/pull/5037) by [@Perlence](https://github.com/Perlence)).
- Fixed editor and input word navigation/deletion to use Unicode word boundaries while preserving ASCII punctuation boundaries ([#5022](https://github.com/earendil-works/pi-mono/pull/5022) by [@haoqixu](https://github.com/haoqixu), [#5067](https://github.com/earendil-works/pi-mono/pull/5067) by [@haoqixu](https://github.com/haoqixu), [#5068](https://github.com/earendil-works/pi-mono/pull/5068) by [@haoqixu](https://github.com/haoqixu)).
- Fixed the development docs `AGENTS.md` link to point at the pi-mono guidelines ([#5041](https://github.com/earendil-works/pi/issues/5041)).

## [0.75.5] - 2026-05-23

### New Features

- **Cleaner read tool output** - Collapsed `read` tool cards now show only the read line by default, while `Ctrl+O` still expands the full file content.
- **Faster file tools on Windows** - Built-in file tools now use async filesystem operations during streaming, and image resizes run off the main TUI thread in a worker.
- **More reliable package updates** - `pi update` and git package installs now reconcile pinned git refs and keep package settings intact. See [Packages](docs/packages.md).
- **Custom Anthropic-compatible adaptive thinking** - Custom provider model configs can opt into adaptive-thinking Claude behavior with `compat.forceAdaptiveThinking`. See [Custom providers](docs/custom-provider.md) and [Models](docs/models.md).

### Added

- Added `compat.forceAdaptiveThinking` support to custom Anthropic-compatible model configuration docs and validation ([#4797](https://github.com/earendil-works/pi-mono/pull/4797) by [@mbazso](https://github.com/mbazso)).
- Added a standard unified patch to edit tool result details for SDK consumers ([#4821](https://github.com/earendil-works/pi/issues/4821)).
- Added a Codex subscription login method selector with device-code auth for headless environments.

### Changed

- Changed collapsed read tool cards to show only the read line until expanded ([#4916](https://github.com/earendil-works/pi/issues/4916)).
- Replaced the inherited optional `koffi` dependency for Windows VT input with a tiny vendored native helper, reducing install size while preserving Shift+Tab handling ([#4480](https://github.com/earendil-works/pi/issues/4480)).
- Changed the root development install documentation to use `npm install --ignore-scripts` ([#4868](https://github.com/earendil-works/pi/issues/4868)).

### Fixed

- Fixed `pi update` to reconcile git-pinned packages to their configured ref ([#4869](https://github.com/earendil-works/pi/issues/4869)).
- Fixed package/resource path handling for Windows and glob/pattern resolution ([#4873](https://github.com/earendil-works/pi-mono/pull/4873) by [@mitsuhiko](https://github.com/mitsuhiko)).
- Fixed config pattern matching to resolve patterns from the correct base directory ([#4898](https://github.com/earendil-works/pi-mono/pull/4898) by [@haoqixu](https://github.com/haoqixu)).
- Fixed theme pickers to list themes by their content name instead of file stem ([#4830](https://github.com/earendil-works/pi-mono/pull/4830) by [@Perlence](https://github.com/Perlence)).
- Fixed OpenCode Zen/Go requests to send per-session OpenCode routing headers ([#4847](https://github.com/earendil-works/pi/issues/4847)).
- Fixed Amazon Bedrock provider loading under strict package managers by inheriting the declared `@smithy/node-http-handler` dependency from `@caupulican/pi-ai` ([#4842](https://github.com/earendil-works/pi/issues/4842)).
- Fixed inherited Amazon Bedrock Claude requests to send the model output token cap by default, avoiding Bedrock's 4096-token default truncation ([#4848](https://github.com/earendil-works/pi/issues/4848)).
- Fixed exported session HTML to escape quote characters in attribute values ([#4832](https://github.com/earendil-works/pi/issues/4832)).
- Fixed GitHub Copilot device-code login to keep opening the verification URL in browser-capable environments while ignoring browser launch failures for headless use ([#4788](https://github.com/earendil-works/pi-mono/pull/4788) by [@vegarsti](https://github.com/vegarsti)).
- Fixed git package installs to reconcile existing checkouts to the requested ref and update package settings without losing filters ([#4870](https://github.com/earendil-works/pi/issues/4870)).
- Published a 0.74.2 rescue release that tells Node 20 users to upgrade Node before updating to newer Pi versions ([#4876](https://github.com/earendil-works/pi/issues/4876)).
- Fixed final bash tool cards to avoid rendering duplicate full-output truncation paths ([#4819](https://github.com/earendil-works/pi/issues/4819)).
- Fixed bash tool truncation line counts to ignore the trailing newline as an extra output line ([#4818](https://github.com/earendil-works/pi/issues/4818)).
- Fixed footer home-directory abbreviation to avoid shortening sibling paths that only share the same prefix ([#4878](https://github.com/earendil-works/pi/issues/4878)).
- Fixed macOS Bun release binaries to resolve the native clipboard sidecar so Ctrl+V image paste can load `@mariozechner/clipboard` ([#4307](https://github.com/earendil-works/pi/issues/4307)).
- Fixed coding-agent tools to avoid synchronous filesystem operations during streaming and moved image resizing off the main TUI thread ([#4756](https://github.com/earendil-works/pi-mono/pull/4756) by [@mitsuhiko](https://github.com/mitsuhiko)).

## [0.75.4] - 2026-05-20

### New Features

- **Hardened npm install and release path** - Pi now ships the CLI with a generated shrinkwrap for transitive dependencies, blocks accidental lockfile changes, verifies dependency pinning and lifecycle-script allowlists in checks, disables lifecycle scripts for self-update and local release installs where supported, and smoke-tests isolated npm and Bun installs before release. See [Supply-chain hardening](../../README.md#supply-chain-hardening).

### Added

- Added interactive update notes after `pi update` runs, so users can see the installed version's changelog before continuing ([#4724](https://github.com/earendil-works/pi-mono/pull/4724) by [@mitsuhiko](https://github.com/mitsuhiko)).
- Exported image resize utilities from the package root for SDK consumers ([#4775](https://github.com/earendil-works/pi-mono/pull/4775) by [@xl0](https://github.com/xl0)).

### Changed

- Changed source syntax to avoid TypeScript constructs that require JavaScript emit, keeping core sources compatible with Node.js strip-only TypeScript checks.
- Removed web UI workspace references from the CLI package and dropped the package-level development watch script.
- Published npm installs now include an `npm-shrinkwrap.json` to lock transitive dependencies for the CLI package.
- Improved terminal theme detection for light/dark and truecolor handling.
- Changed self-update package-manager commands to disable lifecycle scripts during reinstall.

### Fixed

- Fixed the system prompt to tell models to resolve pi docs and examples under the absolute package paths before reading topic-specific relative references ([#4752](https://github.com/earendil-works/pi/issues/4752)).
- Fixed extension `ctx.abort()` during tool-call preflight to stop later confirmations and restore queued interactive input like Escape ([#4276](https://github.com/earendil-works/pi/issues/4276)).
- Fixed AgentSession retry, compaction, and event settlement to use the awaited agent lifecycle instead of a separate event queue, and added `willRetry` to `agent_end` session events.
- Fixed forked session runtime state to keep the active session id aligned with the fork target ([#4799](https://github.com/earendil-works/pi-mono/pull/4799) by [@Perlence](https://github.com/Perlence)).
- Fixed the subagent extension's parallel mode to return useful per-task output and failed-task diagnostics to the parent model instead of 100-character previews ([#4710](https://github.com/earendil-works/pi/issues/4710)).
- Fixed Windows local bash execution to hide helper console windows when launched from background SDK processes ([#4699](https://github.com/earendil-works/pi/issues/4699)).
- Fixed managed npm extension folders to set cloud-sync ignore metadata where supported ([#4763](https://github.com/earendil-works/pi/issues/4763)).
- Fixed HTTP idle timeout configuration so long-running provider streams can avoid premature idle disconnects ([#4759](https://github.com/earendil-works/pi-mono/pull/4759) by [@mitsuhiko](https://github.com/mitsuhiko)).
- Fixed default system prompt boundaries to use explicit XML tags for clearer file separation ([#4709](https://github.com/earendil-works/pi-mono/pull/4709) by [@herrnel](https://github.com/herrnel)).
- Fixed HTML share/export sidebar clicks for shared tool entries to scroll to the rendered tool call ([#4664](https://github.com/earendil-works/pi-mono/pull/4664) by [@yzhg1983](https://github.com/yzhg1983)).
- Fixed theme palettes to set explicit text colors and avoid terminal-default color drift.
- Fixed truecolor detection to align terminal image rendering and interactive theme decisions.
- Fixed loader indicator startup inherited from `@caupulican/pi-tui` so initialization cannot run before frames are available.
- Fixed OpenAI-compatible default output token requests inherited from `@caupulican/pi-ai` to avoid reserving impossible context windows on servers such as vLLM ([#4675](https://github.com/earendil-works/pi/issues/4675)).
- Fixed OpenAI prompt cache keys inherited from `@caupulican/pi-ai` to stay within the 64-character provider limit ([#4720](https://github.com/earendil-works/pi/issues/4720)).
- Fixed Windows npm-family package commands for fnm-managed Node.js installs that expose both extensionless Unix scripts and `.cmd` shims ([#4793](https://github.com/earendil-works/pi/issues/4793)).

## [0.75.3] - 2026-05-18

### Fixed

- Fixed undici 8 HTTP/2 destroyed-session races crashing the Node CLI by preserving the previous HTTP/1.1-only fetch dispatcher behavior ([#4681](https://github.com/earendil-works/pi/issues/4681)).

## [0.75.2] - 2026-05-18

### Fixed

- Fixed Bun-compiled release binaries failing to start when Bun's built-in undici shim lacks npm undici's `install` export ([#4661](https://github.com/earendil-works/pi-mono/pull/4661) by [@dmasiero](https://github.com/dmasiero)).
- Fixed Xiaomi MiMo generated model metadata to replay assistant tool-call messages with `reasoning_content` for thinking-mode multi-turn requests, inherited from `@caupulican/pi-ai` ([#4678](https://github.com/earendil-works/pi/issues/4678)).
- Fixed Windows external editor handoff so vim/nvim can receive input after opening from the TUI ([#4612](https://github.com/earendil-works/pi/issues/4612)).
- Fixed Windows npm self-updates to move loaded native dependency packages out of the active install before reinstalling pi ([#4157](https://github.com/earendil-works/pi/issues/4157)).
- Fixed `pi update --self` detection for pnpm v11 global installs whose package path resolves through the pnpm store ([#4647](https://github.com/earendil-works/pi/issues/4647)).
- Fixed Windows pnpm self-updates to resolve pnpm command shims and run through pnpm instead of requiring manual updates ([#4157](https://github.com/earendil-works/pi/issues/4157)).
- Fixed Windows npm-family command execution to use cross-spawn instead of parsing `.cmd` shim internals ([#4665](https://github.com/earendil-works/pi/issues/4665)).

## [0.75.1] - 2026-05-18

### Fixed

- Fixed config selectors to scale their visible row count to terminal height ([#4243](https://github.com/earendil-works/pi-mono/pull/4243) by [@samjonester](https://github.com/samjonester)).
- Fixed Anthropic-compatible API-key requests to ignore unrelated `ANTHROPIC_AUTH_TOKEN` environment values, avoiding invalid bearer credentials for providers such as Xiaomi MiMo inherited from `@caupulican/pi-ai` ([#4342](https://github.com/earendil-works/pi/issues/4342)).
- Fixed Amazon Bedrock message conversion to skip unknown content blocks instead of failing the stream, inherited from `@caupulican/pi-ai` ([#4223](https://github.com/earendil-works/pi/issues/4223)).
- Fixed Azure OpenAI Responses and OpenAI Responses error formatting to prefix HTTP status codes onto `errorMessage`, so transient 5xx and 429 errors are correctly matched by the agent-level auto-retry classifier inherited from `@caupulican/pi-ai` ([#4232](https://github.com/earendil-works/pi/issues/4232)).
- Fixed OpenCode Go Kimi reasoning replay by normalizing streamed `reasoning` fields back to `reasoning_content` for OpenCode Go only, inherited from `@caupulican/pi-ai` ([#4251](https://github.com/earendil-works/pi/issues/4251)).
- Fixed Xiaomi MiMo model metadata to use the OpenAI-compatible endpoints and `openai-completions` API, restoring multi-turn thinking/tool-call sessions inherited from `@caupulican/pi-ai` ([#4505](https://github.com/earendil-works/pi/issues/4505)).
- Fixed JSON parse failures for compressed fetch responses under Node 26.0 by installing undici fetch globals alongside pi's global dispatcher ([#4650](https://github.com/earendil-works/pi/issues/4650), [#4652](https://github.com/earendil-works/pi/issues/4652), [#4653](https://github.com/earendil-works/pi/issues/4653)).
- Fixed npm-family package commands on Windows to avoid shell argument splitting when install prefixes contain spaces ([#4623](https://github.com/earendil-works/pi/issues/4623)).

### Removed

- Removed non-working OpenAI Codex fast model variants inherited from `@caupulican/pi-ai`.

## [0.75.0] - 2026-05-17

### Breaking Changes

- Raised the minimum supported Node.js version to 22.19.0.

### Fixed

- Fixed compaction summary calls to use custom agent stream functions, preserving proxy-backed LLM routing ([#4484](https://github.com/earendil-works/pi/issues/4484)).
- Fixed system prompt and context file boundaries to use explicit XML tags instead of Markdown headings, reducing inconsistent boundary ingestion by models ([#4541](https://github.com/earendil-works/pi-mono/pull/4541) by [@herrnel](https://github.com/herrnel)).
- Fixed OpenAI Codex generated model metadata to use the current upstream model list inherited from `@caupulican/pi-ai` ([#4603](https://github.com/earendil-works/pi-mono/pull/4603) by [@mattiacerutti](https://github.com/mattiacerutti)).
- Fixed GitHub Copilot GPT model thinking metadata inherited from `@caupulican/pi-ai` to map unsupported minimal thinking to low ([#4622](https://github.com/earendil-works/pi-mono/pull/4622) by [@mattiacerutti](https://github.com/mattiacerutti)).
- Fixed user-scoped npm pi packages to install under `~/.pi/agent/npm/` instead of npm's global package root, avoiding permission errors with system-managed Node installs ([#4587](https://github.com/earendil-works/pi/issues/4587)).
- Fixed Mistral requests failing after the global fetch proxy/timeout workaround by removing the custom fetch override and using undici 8 dispatcher support instead ([#4619](https://github.com/earendil-works/pi/issues/4619)).
- Fixed default output token requests for models whose advertised output limit is effectively their full context window, avoiding impossible provider requests inherited from `@caupulican/pi-ai` ([#4614](https://github.com/earendil-works/pi/issues/4614)).

## [0.74.1] - 2026-05-16

### New Features

- **Image generation support** - Added image generation APIs, generated image model metadata, and built-in OpenRouter image generation support inherited from `@caupulican/pi-ai`.
- **Together AI provider** - Added Together AI as a built-in provider with `/login` API-key auth, default model resolution, and setup docs. See [README.md#providers--models](README.md#providers--models) and [docs/providers.md](docs/providers.md).
- **Windows ARM64 standalone binaries** - Added standalone release artifacts for Windows ARM64.
- **Improved terminal and markdown rendering** - Added markdown list indentation, task-list checkbox rendering, large markdown robustness, and inline image placement fixes inherited from `@caupulican/pi-tui`.

### Added

- Added image generation support from `@caupulican/pi-ai`, including image generation APIs, image model metadata, and built-in OpenRouter image generation support ([#3887](https://github.com/earendil-works/pi-mono/pull/3887) by [@cristinaponcela](https://github.com/cristinaponcela)).
- Added Together AI to built-in provider setup, `/login` API-key auth, and default model resolution ([#3624](https://github.com/earendil-works/pi-mono/pull/3624) by [@Nutlope](https://github.com/Nutlope)).
- Added Windows ARM64 standalone binary release artifacts ([#4458](https://github.com/earendil-works/pi/pull/4458) by [@brianmichel](https://github.com/brianmichel)).

### Fixed

- Fixed Node 26 OpenAI-compatible streams timing out after five idle minutes by routing global fetch through pi's undici dispatcher ([#4519](https://github.com/earendil-works/pi/issues/4519)).
- Fixed pnpm global package installs by resolving the global package root from pnpm's layout.
- Fixed macOS clipboard access errors under sandboxed pasteboard denial so they do not abort the process ([#4492](https://github.com/earendil-works/pi/issues/4492)).
- Fixed the scoped model startup hint to show the configured model-cycle keybinding ([#4508](https://github.com/earendil-works/pi/issues/4508)).
- Fixed resource path display to disambiguate package/resource names that collide across package locations.
- Fixed `fd` auto-download on macOS x86_64 by pinning the last release that ships an Intel macOS binary ([#4559](https://github.com/earendil-works/pi/issues/4559)).
- Fixed skill diagnostics to stop warning when a skill name differs from its parent directory ([#4534](https://github.com/earendil-works/pi/issues/4534)).
- Fixed prompt template argument parsing to split unquoted multiline input on newlines ([#4553](https://github.com/earendil-works/pi/issues/4553)).
- Fixed `--resume` session listing to cap in-flight session metadata loads and avoid OOM on large session histories ([#4583](https://github.com/earendil-works/pi/issues/4583)).
- Fixed interactive error messages to render with trailing spacing so reload errors do not run into resource listings ([#4510](https://github.com/earendil-works/pi/issues/4510)).
- Fixed `.agents` package provenance metadata to survive package-manager scans.
- Fixed nested code fences in the Termux setup documentation so the example AGENTS.md renders correctly ([#4503](https://github.com/earendil-works/pi/issues/4503)).
- Fixed tool output expansion while extension confirmation dialogs are focused ([#4429](https://github.com/earendil-works/pi/issues/4429)).
- Fixed auto-retry for Anthropic streams that end before `message_stop` ([#4433](https://github.com/earendil-works/pi/issues/4433)).
- Fixed compaction summary calls to clamp requested output tokens to model limits.
- Fixed uncaught interactive-mode exceptions to restore the terminal before exiting ([#4426](https://github.com/earendil-works/pi-mono/pull/4426) by [@ofa1](https://github.com/ofa1)).
- Fixed ANSI stripping to match `strip-ansi` behavior after dependency removal.
- Fixed UUIDv7 sequence generation shared by session IDs after dependency removal.
- Fixed OpenRouter cached-token usage accounting, Fireworks caching compatibility, and OpenAI Codex WebSocket proxy handling inherited from `@caupulican/pi-ai`.
- Fixed markdown list wrapping, task-list checkboxes, large markdown rendering, WezTerm Kitty keyboard escape handling, and short-viewport inline image placement inherited from `@caupulican/pi-tui`.
- Fixed theme sharing across package scopes so extensions do not crash with `Theme not initialized` ([#4333](https://github.com/earendil-works/pi/issues/4333)).
- Fixed keybinding hints to show Option instead of Alt on macOS ([#4289](https://github.com/earendil-works/pi/issues/4289)).
- Fixed the interactive update notification to render the changelog as an OSC 8 hyperlink when the terminal supports hyperlinks ([#4280](https://github.com/earendil-works/pi/issues/4280)).

## [0.74.0] - 2026-05-07

### Changed

- Updated repository links and package references for the move to `earendil-works/pi-mono` and `@earendil-works/*` package scopes.

## [0.73.1] - 2026-05-07

### New Features

- **Self-update support for the npm scope migration**: `pi update --self` now supports the upcoming package rename from `@mariozechner/pi-coding-agent` to `@caupulican/pi-adaptative`. After the new package is published, existing global installs can update through the normal self-update flow; pi will uninstall the old global package and install the package name returned by the version check endpoint.
- **Interactive OAuth login selection**: OAuth providers can now present multiple login choices in `/login`, enabling provider-specific interactive authentication flows. See [Providers](docs/providers.md).
- **JSONC-style `models.json` parsing**: `models.json` now allows comments and trailing commas, making custom provider and model configuration easier to maintain. See [Providers](docs/providers.md) and [Custom Providers](docs/custom-provider.md).

### Added

- Added interactive login selection support so OAuth providers can present multiple login choices ([#4190](https://github.com/earendil-works/pi-mono/pull/4190) by [@mitsuhiko](https://github.com/mitsuhiko)).

### Changed

- Changed `pi update --self` to honor the active package name returned by the Pi version check endpoint, defaulting to the current package when omitted and uninstalling the old global package before installing a renamed package.
- Changed extension loading to use upstream `jiti` 2.7 instead of the `@mariozechner/jiti` fork ([#4244](https://github.com/earendil-works/pi-mono/pull/4244) by [@pi0](https://github.com/pi0)).
- Changed `models.json` parsing to allow comments and trailing commas ([#4162](https://github.com/earendil-works/pi-mono/pull/4162) by [@julien-c](https://github.com/julien-c)).

### Fixed

- Fixed `pi -p` treating prompts that start with YAML frontmatter as extension flags instead of user messages ([#4163](https://github.com/badlogic/pi-mono/issues/4163)).
- Fixed pending tool results not updating in the live TUI after toggling thinking block visibility while the tool is running ([#4167](https://github.com/badlogic/pi-mono/issues/4167)).
- Fixed `/copy` reporting success on Linux without writing the clipboard on Wayland-only compositors (Hyprland, Niri, ...) by skipping the X11-only native addon on Linux and routing through `wl-copy`/`xclip`/`xsel` instead ([#4177](https://github.com/badlogic/pi-mono/issues/4177)).
- Fixed HTML session exports to strip skill wrapper XML from rendered user messages ([#4234](https://github.com/earendil-works/pi-mono/pull/4234) by [@aliou](https://github.com/aliou)).
- Fixed OpenAI-compatible chat completion streams that interleave content and tool-call deltas in the same choice.
- Fixed OpenAI Codex OAuth refresh failures writing directly to stderr while the TUI is active ([#4141](https://github.com/badlogic/pi-mono/issues/4141)).
- Fixed OpenAI Codex Responses requests to send a non-empty system prompt ([#4184](https://github.com/earendil-works/pi-mono/issues/4184)).
- Fixed Kimi For Coding model resolution for the Kimi K2 P6 alias ([#4218](https://github.com/earendil-works/pi-mono/issues/4218)).
- Fixed Kitty inline image redraws to stay within TUI-owned terminal regions and avoid writing below the active viewport.
- Fixed Kitty inline image rendering by letting the terminal allocate image ids and bounding parsed image ids to valid values.
- Fixed inline image capability detection to disable inline images in cmux terminals.

## [0.73.0] - 2026-05-04

### New Features

- **Xiaomi MiMo API billing and regional Token Plan providers** - `xiaomi` now uses API billing, with separate `xiaomi-token-plan-{cn,ams,sgp}` providers. See [docs/providers.md#api-keys](docs/providers.md#api-keys) and [README.md#providers--models](README.md#providers--models). ([#4112](https://github.com/badlogic/pi-mono/pull/4112) by [@Phoen1xCode](https://github.com/Phoen1xCode))
- **Incremental bash output streaming** - Bash tool output now appears while commands run instead of only after completion. ([#4145](https://github.com/badlogic/pi-mono/issues/4145))
- **Compact read rendering** - Interactive `read` output for Pi docs, context files, and skills is collapsed by default and shows selected line ranges.

### Breaking Changes

- Switched the built-in `xiaomi` provider from Token Plan AMS to Xiaomi's API billing endpoint, and renamed its `/login` display from "Xiaomi MiMo Token Plan" to "Xiaomi MiMo". `XIAOMI_API_KEY` now refers to the API billing key from [platform.xiaomimimo.com](https://platform.xiaomimimo.com). Users on Token Plan should switch to the appropriate `xiaomi-token-plan-*` provider and set the corresponding env var ([#4112](https://github.com/badlogic/pi-mono/pull/4112) by [@Phoen1xCode](https://github.com/Phoen1xCode)).

### Added

- Added three Xiaomi MiMo Token Plan regional providers visible in `/login`: `xiaomi-token-plan-cn` (`XIAOMI_TOKEN_PLAN_CN_API_KEY`), `xiaomi-token-plan-ams` (`XIAOMI_TOKEN_PLAN_AMS_API_KEY`), `xiaomi-token-plan-sgp` (`XIAOMI_TOKEN_PLAN_SGP_API_KEY`). Each defaults to `mimo-v2.5-pro` ([#4112](https://github.com/badlogic/pi-mono/pull/4112) by [@Phoen1xCode](https://github.com/Phoen1xCode)).

### Changed

- Changed `read` tool rendering to collapse Pi documentation, AGENTS/CLAUDE context files, and `SKILL.md` contents by default in interactive output.

### Fixed

- Fixed generated OpenAI-compatible model metadata for Qwen 3.5/3.6 and MiniMax M2.7, so those models work through the built-in provider catalog ([#4110](https://github.com/badlogic/pi-mono/pull/4110) by [@jsynowiec](https://github.com/jsynowiec)).
- Fixed Bedrock Claude Opus 4.7 `xhigh` thinking requests by preserving the provider's native effort value.
- Fixed OpenAI Codex WebSocket transport to fall back to SSE when setup fails before streaming starts, and surface transport diagnostics in the assistant message ([#4133](https://github.com/badlogic/pi-mono/issues/4133)).
- Fixed OpenAI Codex WebSocket transport keeping `--print` and JSON mode processes alive after the response by closing cached WebSocket sessions during session shutdown ([#4103](https://github.com/badlogic/pi-mono/issues/4103)).
- Fixed compact `read` tool calls to render directly and include selected line ranges in interactive output.
- Fixed interactive sessions to exit when terminal input is lost instead of continuing in a broken state.
- Fixed bash tool output to stream incrementally while commands run instead of waiting for command completion ([#4145](https://github.com/badlogic/pi-mono/issues/4145)).
- Fixed selector and autocomplete fuzzy ranking to prioritize exact matches.

## [0.72.1] - 2026-05-02

## [0.72.0] - 2026-05-01

### New Features

- **Xiaomi MiMo Token Plan provider** - New Anthropic-compatible provider with `XIAOMI_API_KEY` auth, default model (`mimo-v2.5-pro`), and `/login` display. See [docs/providers.md](docs/providers.md). ([#4005](https://github.com/badlogic/pi-mono/pull/4005) by [@Phoen1xCode](https://github.com/Phoen1xCode)).
- **Model thinking level metadata** - Models can now declare which thinking levels they support via `thinkingLevelMap`, replacing the old `reasoningEffortMap`. See [docs/models.md#thinking-level-map](docs/models.md#thinking-level-map) and [docs/custom-provider.md](docs/custom-provider.md). ([#3208](https://github.com/badlogic/pi-mono/issues/3208)).
- **Custom provider base URL overrides** - `pi.registerProvider()` now respects per-model `baseUrl` settings. See [docs/custom-provider.md](docs/custom-provider.md). ([#4063](https://github.com/badlogic/pi-mono/issues/4063)).
- **Post-turn stop callback** - Agent loop can now exit gracefully after a completed turn via `shouldStopAfterTurn`. See [`packages/agent/README.md`](https://github.com/badlogic/pi-mono/blob/main/packages/agent/README.md).
- **Self-update detection fix** - `pi` now correctly identifies and applies available updates. ([#3942](https://github.com/badlogic/pi-mono/issues/3942), [#3980](https://github.com/badlogic/pi-mono/issues/3980), [#3922](https://github.com/badlogic/pi-mono/issues/3922)).

### Breaking Changes

- Replaced `compat.reasoningEffortMap` in `models.json` and `pi.registerProvider()` model definitions with model-level `thinkingLevelMap` ([#3208](https://github.com/badlogic/pi-mono/issues/3208)). Migration: move old mappings from `compat.reasoningEffortMap` to `thinkingLevelMap`. Use string values for provider-specific thinking values and `null` for unsupported pi levels that should be hidden and skipped by cycling. See `docs/models.md#thinking-level-map` and `docs/custom-provider.md`.

### Added

- Added Xiaomi MiMo Token Plan provider support with `XIAOMI_API_KEY`, default model resolution, `/login` display support, and provider documentation ([#4005](https://github.com/badlogic/pi-mono/pull/4005) by [@Phoen1xCode](https://github.com/Phoen1xCode)).
- Added model-level `thinkingLevelMap` support in `models.json` and `pi.registerProvider()`, allowing models to expose only the thinking levels they actually support ([#3208](https://github.com/badlogic/pi-mono/issues/3208)).
- Added `shouldStopAfterTurn` agent loop callback for post-turn stop control, inherited from `@mariozechner/pi-agent-core`. See [`packages/agent/README.md`](https://github.com/badlogic/pi-mono/blob/main/packages/agent/README.md).

### Fixed

- Fixed the default transport setting to use `auto`, allowing OpenAI Codex to use cached WebSocket context when available ([#4083](https://github.com/badlogic/pi-mono/issues/4083)).
- Fixed `pi.registerProvider()` to honor per-model `baseUrl` overrides ([#4063](https://github.com/badlogic/pi-mono/issues/4063)).
- Fixed self-update detection so `pi` correctly identifies when a newer version is available and applies updates ([#3942](https://github.com/badlogic/pi-mono/issues/3942), [#3980](https://github.com/badlogic/pi-mono/issues/3980), [#3922](https://github.com/badlogic/pi-mono/issues/3922)).

## [0.71.1] - 2026-05-01

### Added

- Added `websocket-cached` to the transport setting options for the OpenAI Codex provider used with ChatGPT subscription auth. This keeps the same WebSocket open for a session and, after the first request, sends only the new conversation items instead of resending the full chat history when possible.

## [0.71.0] - 2026-04-30

### Breaking Changes

- Removed built-in Google Gemini CLI and Google Antigravity support. Existing configurations using those providers must switch to another supported provider.

### New Features

- Cloudflare AI Gateway provider support with `CLOUDFLARE_API_KEY`/`CLOUDFLARE_ACCOUNT_ID`/`CLOUDFLARE_GATEWAY_ID`, default model resolution, and `/login` display. See [docs/providers.md#cloudflare-ai-gateway](docs/providers.md#cloudflare-ai-gateway). ([#3856](https://github.com/badlogic/pi-mono/pull/3856) by [@mchenco](https://github.com/mchenco)).
- Moonshot AI provider support with `MOONSHOT_API_KEY`, default model resolution, and `/login` display.
- Mistral Medium 3.5 built-in model support. See [docs/providers.md#api-keys](docs/providers.md#api-keys). ([#4009](https://github.com/badlogic/pi-mono/pull/4009) by [@technocidal](https://github.com/technocidal)).
- Extension APIs can replace finalized `message_end` messages, wrap custom editor factories via `ctx.ui.getEditorComponent()`, and observe thinking level changes. See [docs/extensions.md#message_start--message_update--message_end](docs/extensions.md#message_start--message_update--message_end), [docs/extensions.md#widgets-status-and-footer](docs/extensions.md#widgets-status-and-footer), and [docs/extensions.md#thinking_level_select](docs/extensions.md#thinking_level_select).
- `PI_CODING_AGENT_SESSION_DIR` configures session storage from the environment. See [docs/usage.md#environment-variables](docs/usage.md#environment-variables).

### Added

- Added Cloudflare AI Gateway as a built-in provider with `CLOUDFLARE_API_KEY`/`CLOUDFLARE_ACCOUNT_ID`/`CLOUDFLARE_GATEWAY_ID` setup, default model resolution, `/login` display support, and provider documentation ([#3856](https://github.com/badlogic/pi-mono/pull/3856) by [@mchenco](https://github.com/mchenco)).
- Added Moonshot AI as a built-in provider with `MOONSHOT_API_KEY` setup, default model resolution, and `/login` display support.
- Added Mistral Medium 3.5 built-in model support via `@mariozechner/pi-ai` ([#4009](https://github.com/badlogic/pi-mono/pull/4009) by [@technocidal](https://github.com/technocidal)).
- Added routed OpenAI-compatible response model metadata in assistant messages, so providers such as OpenRouter can expose the concrete model used ([#3968](https://github.com/badlogic/pi-mono/pull/3968) by [@purrgrammer](https://github.com/purrgrammer)).
- Added `PI_CODING_AGENT_SESSION_DIR` as an environment equivalent to `--session-dir` ([#4027](https://github.com/badlogic/pi-mono/issues/4027)).
- Added `message_end` extension result support for replacing finalized messages, enabling extensions to override assistant usage cost ([#3982](https://github.com/badlogic/pi-mono/issues/3982)).
- Added top-level `name` support to `pi.registerProvider()` so extension-registered providers can show a friendly name in `/login` ([#3956](https://github.com/badlogic/pi-mono/issues/3956)).
- Added `ctx.ui.getEditorComponent()` so extensions can wrap the currently configured custom editor factory ([#3935](https://github.com/badlogic/pi-mono/issues/3935)).
- Added a `thinking_level_select` extension event for observing thinking level changes ([#3888](https://github.com/badlogic/pi-mono/issues/3888)).

### Fixed

- Fixed WSL clipboard image paste by passing the PowerShell save path directly instead of through a custom environment variable ([#2469](https://github.com/badlogic/pi-mono/issues/2469)).
- Fixed Google Vertex Gemini 3 tool call replay for unsigned tool calls ([#4032](https://github.com/badlogic/pi-mono/issues/4032)).
- Fixed blocked `edit` tool results rendering the rejection reason twice after interactive extension confirmation ([#3830](https://github.com/badlogic/pi-mono/issues/3830)).
- Fixed extension-triggered thinking level changes refreshing the interactive editor border immediately ([#3888](https://github.com/badlogic/pi-mono/issues/3888)).
- Fixed the coding-agent README See Also link to point at `@mariozechner/pi-agent-core` ([#4023](https://github.com/badlogic/pi-mono/issues/4023)).
- Fixed `grep` and `find` tool argument injection for flag-like search patterns ([#4018](https://github.com/badlogic/pi-mono/issues/4018)).
- Fixed PowerShell shell command output on Windows by only spawning detached processes on Unix ([#4013](https://github.com/badlogic/pi-mono/pull/4013) by [@picasso250](https://github.com/picasso250)).
- Fixed Bun package manager `node_modules` discovery when `npmCommand` is configured to use Bun ([#3998](https://github.com/badlogic/pi-mono/pull/3998) by [@thirtythreeforty](https://github.com/thirtythreeforty)).
- Fixed edit and edit-preview access failures to report filesystem errors correctly ([#3955](https://github.com/badlogic/pi-mono/pull/3955) by [@rwachtler](https://github.com/rwachtler)).
- Fixed `ProcessTerminal` sizing to use `COLUMNS` and `LINES` before falling back to 80x24 ([#4004](https://github.com/badlogic/pi-mono/issues/4004)).
- Updated `@anthropic-ai/sdk` to clear GHSA-p7fg-763f-g4gf audit findings ([#3992](https://github.com/badlogic/pi-mono/issues/3992)).
- Updated `@mariozechner/clipboard` to an attested release so package managers with trust policies do not reject installs ([#3946](https://github.com/badlogic/pi-mono/issues/3946)).
- Fixed project context discovery to load `AGENTS.MD` files in addition to `AGENTS.md` ([#3949](https://github.com/badlogic/pi-mono/issues/3949)).
- Fixed `/handoff` to use compacted session context instead of pre-compaction raw messages ([#3945](https://github.com/badlogic/pi-mono/issues/3945)).
- Fixed DeepSeek V4 Flash `xhigh` thinking support so requests map to DeepSeek's `max` reasoning effort ([#3944](https://github.com/badlogic/pi-mono/issues/3944)).
- Fixed Anthropic streams that end before `message_stop` to be treated as errors instead of successful partial responses ([#3936](https://github.com/badlogic/pi-mono/issues/3936)).
- Fixed generated OpenAI-compatible DeepSeek V4 reasoning compatibility outside the direct DeepSeek provider ([#3940](https://github.com/badlogic/pi-mono/issues/3940)).
- Fixed idle follow-up submission to clear the editor like normal message submission ([#3926](https://github.com/badlogic/pi-mono/issues/3926)).
- Fixed editor rendering artifacts for Thai Sara Am and Lao AM vowel characters ([#3904](https://github.com/badlogic/pi-mono/issues/3904)).
- Fixed DeepSeek V4 Flash and V4 Pro pricing metadata to match current official rates ([#3910](https://github.com/badlogic/pi-mono/issues/3910)).
- Updated the sandbox extension example lockfile to resolve the vulnerable `lodash-es` transitive dependency ([#3901](https://github.com/badlogic/pi-mono/issues/3901)).
- Fixed DeepSeek prompt cache hits to be tracked from OpenAI-compatible usage responses ([#3880](https://github.com/badlogic/pi-mono/issues/3880)).

### Removed

- Removed the discontinued Qwen CLI OAuth custom provider extension example ([#3832](https://github.com/badlogic/pi-mono/pull/3832) by [@4h9fbZ](https://github.com/4h9fbZ)).
- Removed Google Gemini CLI and Google Antigravity built-in login, default model, documentation, and example extension support.

## [0.70.6] - 2026-04-28

### New Features

- Cloudflare Workers AI provider support with `CLOUDFLARE_API_KEY`/`CLOUDFLARE_ACCOUNT_ID` setup. See [docs/providers.md#api-keys](docs/providers.md#api-keys). ([#3851](https://github.com/badlogic/pi-mono/pull/3851) by [@mchenco](https://github.com/mchenco))
- Pi update checks now use `pi.dev` and identify Pi with a `pi/<version>` user agent. See [docs/packages.md](docs/packages.md). ([#3877](https://github.com/badlogic/pi-mono/pull/3877) by [@mitsuhiko](https://github.com/mitsuhiko))

### Added

- Added Cloudflare Workers AI as a built-in provider with `CLOUDFLARE_API_KEY`/`CLOUDFLARE_ACCOUNT_ID` setup, default model resolution, `/login` support, and provider documentation ([#3851](https://github.com/badlogic/pi-mono/pull/3851) by [@mchenco](https://github.com/mchenco)).

### Changed

- Changed Pi version checks to identify Pi with a `pi/<version>` user agent ([#3877](https://github.com/badlogic/pi-mono/pull/3877) by [@mitsuhiko](https://github.com/mitsuhiko)).

### Fixed

- Fixed config selector scroll indicators to show item counts instead of line counts ([#3820](https://github.com/badlogic/pi-mono/pull/3820) by [@aliou](https://github.com/aliou)).
- Fixed exported HTML to escape embedded image data and session metadata, preventing crafted session content from injecting markup ([#3819](https://github.com/badlogic/pi-mono/pull/3819) by [@justinpbarnett](https://github.com/justinpbarnett), [#3883](https://github.com/badlogic/pi-mono/pull/3883) by [@justinpbarnett](https://github.com/justinpbarnett)).
- Fixed Bun-based package manager startup by locating global `node_modules` relative to Bun's install layout ([#3861](https://github.com/badlogic/pi-mono/pull/3861) by [@thirtythreeforty](https://github.com/thirtythreeforty)).
- Fixed Bedrock inference profile capability checks by normalizing profile ARNs to the underlying model name.
- Fixed file discovery to fall back to `fdfind` when `fd` is unavailable.
- Fixed `pi update` to skip self-update reinstalls when the installed version is already current ([#3853](https://github.com/badlogic/pi-mono/issues/3853)).
- Fixed Cloudflare Workers AI attribution headers to honor the install telemetry setting.
- Fixed `pi update --self` detection and execution for Windows package-manager shim installs, including symlinked global package roots, and print the manual fallback command when self-update fails ([#3857](https://github.com/badlogic/pi-mono/issues/3857)).

## [0.70.5] - 2026-04-27

### Fixed

- Fixed HTML export preserving ANSI-renderer trailing padding as extra blank wrapped lines.

## [0.70.4] - 2026-04-27

### Fixed

- Fixed packaged `pi` startup failing because the session selector imported a source-only utility path.

## [0.70.3] - 2026-04-27

### New Features

- `pi update` can now update pi itself in addition to installed pi packages. See [docs/packages.md](docs/packages.md). ([#3680](https://github.com/badlogic/pi-mono/pull/3680) by [@mitsuhiko](https://github.com/mitsuhiko))
- Azure Cognitive Services endpoint support for Azure OpenAI Responses deployments. See [docs/providers.md#api-keys](docs/providers.md#api-keys). ([#3799](https://github.com/badlogic/pi-mono/pull/3799) by [@marcbloech](https://github.com/marcbloech))
- Suppressible Anthropic extra-usage billing warning via `warnings.anthropicExtraUsage` in `/settings`. See [docs/settings.md](docs/settings.md). ([#3808](https://github.com/badlogic/pi-mono/issues/3808))
- Extension-controlled working row visibility via `ctx.ui.setWorkingVisible()`, allowing extensions to hide the built-in loader row and render custom working state. See [docs/extensions.md](docs/extensions.md) and [examples/extensions/border-status-editor.ts](examples/extensions/border-status-editor.ts). ([#3674](https://github.com/badlogic/pi-mono/issues/3674))

### Added

- Added `pi update` support for updating pi itself in addition to installed pi packages ([#3680](https://github.com/badlogic/pi-mono/pull/3680) by [@mitsuhiko](https://github.com/mitsuhiko)).
- Added Azure Cognitive Services endpoint support for Azure OpenAI Responses base URLs ([#3799](https://github.com/badlogic/pi-mono/pull/3799) by [@marcbloech](https://github.com/marcbloech)).
- Added `warnings.anthropicExtraUsage` and a `/settings` warnings submenu to suppress the Anthropic extra usage billing warning ([#3808](https://github.com/badlogic/pi-mono/issues/3808))
- Added `ctx.ui.setWorkingVisible()` so extensions can hide the built-in interactive working loader row without reserving layout space, plus a border-status editor example that moves working state into a custom editor border ([#3674](https://github.com/badlogic/pi-mono/issues/3674))

### Fixed

- Fixed duplicate printable characters from Kitty keyboard protocol CSI-u plus raw character input on layouts such as Italian ([#3780](https://github.com/badlogic/pi-mono/issues/3780)).
- Fixed API-key environment discovery and Bun startup to fall back to `/proc/self/environ` when Bun's sandbox leaves `process.env` empty ([#3801](https://github.com/badlogic/pi-mono/pull/3801) by [@mdsjip](https://github.com/mdsjip)).
- Fixed Bun sandboxed package-manager commands when `process.env` is empty ([#3807](https://github.com/badlogic/pi-mono/pull/3807) by [@mdsjip](https://github.com/mdsjip)).
- Fixed symlinked packages, resources, skills, and sessions being duplicated in selectors and loaders ([#3818](https://github.com/badlogic/pi-mono/pull/3818) by [@aliou](https://github.com/aliou)).
- Fixed Bedrock prompt-caching and adaptive-thinking capability checks for inference profile ARNs ([#3527](https://github.com/badlogic/pi-mono/pull/3527) by [@anirudhmarc](https://github.com/anirudhmarc)).
- Fixed OpenAI Codex Responses default verbosity to `low` when no verbosity is specified.
- Stopped sending empty `tools` arrays to providers that reject them when tools are disabled ([#3650](https://github.com/badlogic/pi-mono/pull/3650) by [@HQidea](https://github.com/HQidea)).
- Fixed Anthropic SSE parsing to ignore unknown proxy events such as OpenAI-style `done` terminators ([#3708](https://github.com/badlogic/pi-mono/issues/3708)).
- Fixed provider registration with override-only `models.json` entries to preserve built-in model lists ([#3651](https://github.com/badlogic/pi-mono/issues/3651)).
- Fixed `/login` to show auth supplied by `models.json` provider definitions.
- Fixed HTML export whitespace around extension-rendered tool output and expandable output hints.
- Fixed bash executor temp output streams leaking file descriptors when output was truncated by line count ([#3786](https://github.com/badlogic/pi-mono/issues/3786))
- Fixed extension `pi.setSessionName()` updates to refresh the interactive terminal title immediately ([#3686](https://github.com/badlogic/pi-mono/issues/3686))
- Fixed `/tree` cancellation via `session_before_tree` leaving the session stuck in compaction state ([#3688](https://github.com/badlogic/pi-mono/issues/3688))
- Fixed Escape interrupt handling when extensions hide the built-in working loader row ([#3674](https://github.com/badlogic/pi-mono/issues/3674))
- Fixed coding-agent test expectations for current default models and missing-auth guidance.
- Fixed long local-LLM SSE streams aborting at 5 minutes with `UND_ERR_BODY_TIMEOUT` by disabling undici `bodyTimeout`/`headersTimeout` on the global dispatcher; provider SDKs continue to enforce their own deadlines via `retry.provider.timeoutMs` ([#3715](https://github.com/badlogic/pi-mono/issues/3715))

## [0.70.2] - 2026-04-24

### Fixed

- Fixed provider retry/timeout forwarding to omit undefined provider request controls, avoiding downstream SDK validation errors such as `timeout must be an integer` when `retry.provider.timeoutMs` is not configured ([#3627](https://github.com/badlogic/pi-mono/issues/3627))

## [0.70.1] - 2026-04-24

### New Features

- DeepSeek provider support with V4 Flash/Pro models and `DEEPSEEK_API_KEY` authentication. See [README.md#providers--models](README.md#providers--models) and [docs/providers.md#api-keys](docs/providers.md#api-keys).
- Provider request timeout/retry controls via `retry.provider.{timeoutMs,maxRetries,maxRetryDelayMs}`, useful for long-running local inference and provider SDK retry behavior. See [docs/settings.md#retry](docs/settings.md#retry). ([#3627](https://github.com/badlogic/pi-mono/issues/3627))

### Added

- Added DeepSeek to built-in provider setup, default model resolution, and provider documentation.

### Fixed

- Fixed `/copy` to avoid unbounded OSC 52 writes and clipboard races that could break terminal rendering or panic the native clipboard addon ([#3639](https://github.com/badlogic/pi-mono/issues/3639))
- Fixed extension flag docs to show `pi.getFlag()` using registered flag names without the CLI `--` prefix ([#3614](https://github.com/badlogic/pi-mono/issues/3614))
- Fixed provider retry/timeout settings wiring by adding `retry.provider.{timeoutMs,maxRetries,maxRetryDelayMs}`, migrating legacy `retry.maxDelayMs`, and forwarding provider controls into `streamSimple` request options ([#3627](https://github.com/badlogic/pi-mono/issues/3627))
- Fixed Windows git package installs to bypass `cmd.exe` for native git commands, so install paths containing spaces no longer break `pi install git:...` with `fatal: Too many arguments` ([#3642](https://github.com/badlogic/pi-mono/issues/3642))
- Fixed DeepSeek V4 session replay 400 errors by sending DeepSeek-compatible thinking controls and replayed assistant `reasoning_content` fields ([#3636](https://github.com/badlogic/pi-mono/issues/3636))
- Fixed GPT-5.5 generated context window metadata to use the observed 272k limit.
- Fixed CSI-u Ctrl+letter decoding inside bracketed paste, so pasted modified-key escape sequences no longer become literal editor text ([#3623](https://github.com/badlogic/pi-mono/pull/3623) by [@Exrun94](https://github.com/Exrun94))

## [0.70.0] - 2026-04-23

### New Features

- Searchable auth provider login flow: the `/login` provider selector now supports fuzzy search/filtering, making it faster to find providers when many are configured. See [docs/providers.md](docs/providers.md). ([#3572](https://github.com/badlogic/pi-mono/pull/3572) by [@mitsuhiko](https://github.com/mitsuhiko))
- GPT-5.5 Codex support: `openai-codex/gpt-5.5` is available as a model option, including `xhigh` reasoning support and corrected priority-tier pricing.
- Terminal progress indicators are now opt-in: OSC 9;4 progress reporting during streaming/compaction is off by default and can be toggled via `terminal.showTerminalProgress` in `/settings` ([#3588](https://github.com/badlogic/pi-mono/issues/3588))
- `--no-builtin-tools` / `createAgentSession({ noTools: "builtin" })` now correctly disables only built-in tools while keeping extension tools active. See [docs/extensions.md](docs/extensions.md) and [README.md](README.md) ([#3592](https://github.com/badlogic/pi-mono/issues/3592))

### Breaking Changes

- Disabled OSC 9;4 terminal progress indicators by default. Set `terminal.showTerminalProgress` to `true` in `/settings` to re-enable ([#3588](https://github.com/badlogic/pi-mono/issues/3588))

### Added

- Added searchable auth provider login flow with fuzzy filtering in the provider selector ([#3572](https://github.com/badlogic/pi-mono/pull/3572) by [@mitsuhiko](https://github.com/mitsuhiko))
- Added GPT-5.5 Codex model
- Added auth source labels in `/login` so provider entries can show when auth comes from `--api-key`, an environment variable, or custom provider fallback without exposing secrets.

### Changed

- Updated default model selection across providers to current recommended models.
- Improved stale extension context errors after session replacement or reload to tell extension authors to avoid captured `pi`/command `ctx` and use `withSession` for post-replacement work.

### Fixed

- Fixed `/model` selector cancellation to request render instead of incorrectly triggering login selector.
- Changed login, OAuth, and extension selectors for more consistent styling.
- Added Amazon Bedrock setup guidance to `/login` and updated `/model` copy to refer to configured providers instead of only API keys.
- Improved no-model and missing-auth warnings to point users to `/login` for OAuth or API key setup.
- Fixed `/quit` shutdown ordering to stop the TUI before extension UI teardown can repaint, preserving the final rendered frame while still emitting `session_shutdown` before process exit.
- Fixed `SettingsManager.inMemory()` initial settings being lost after reloads triggered by SDK resource loading ([#3616](https://github.com/badlogic/pi-mono/issues/3616))
- Fixed `models.json` provider compatibility to accept `compat.supportsLongCacheRetention`, allowing proxies to opt out of long-retention cache fields when needed while long retention is enabled by default when requested ([#3543](https://github.com/badlogic/pi-mono/issues/3543))
- Fixed `--thinking xhigh` for `openai-codex` `gpt-5.5` so it is no longer downgraded to `high`.
- Fixed git package installs with custom `npmCommand` values such as `pnpm` by avoiding npm-specific production flags in that compatibility path ([#3604](https://github.com/badlogic/pi-mono/issues/3604))
- Fixed first user messages rendering without spacing after existing notices such as compaction summaries or status messages ([#3613](https://github.com/badlogic/pi-mono/issues/3613))
- Fixed the handoff extension example to use the replacement-session context after creating a new session, avoiding stale `ctx` errors when it installs the generated prompt ([#3606](https://github.com/badlogic/pi-mono/issues/3606))
- Fixed session replacement and `/quit` teardown ordering to run host-owned extension UI cleanup synchronously after `session_shutdown` handlers complete but before invalidating the old extension context, preventing stale extension UI from rendering against a disposed session ([#3597](https://github.com/badlogic/pi-mono/pull/3597) by [@vegarsti](https://github.com/vegarsti))
- Fixed crash on `/quit` when an extension registers a custom footer whose `render()` accesses `ctx`, by tearing down extension-provided UI before invalidating the extension runner during shutdown ([#3595](https://github.com/badlogic/pi-mono/issues/3595))
- Fixed auto-retry to treat Bedrock/Smithy HTTP/2 transport failures like `http2 request did not get a response` as transient errors, so the agent retries automatically instead of waiting for a manual nudge ([#3594](https://github.com/badlogic/pi-mono/issues/3594))
- Fixed the CLI/SDK tool-selection split so `--no-builtin-tools` and `createAgentSession({ noTools: "builtin" })` disable only built-in default tools while keeping extension/custom tools enabled, instead of falling through to the same "disable everything" path as `--no-tools` ([#3592](https://github.com/badlogic/pi-mono/issues/3592))
- Fixed remaining hardcoded `pi` / `.pi` branding to route through `APP_NAME` and `CONFIG_DIR_NAME` extension points, so SDK rebrands get consistent naming in `/quit` description, `process.title`, and the project-local extensions directory ([#3583](https://github.com/badlogic/pi-mono/pull/3583) by [@jlaneve](https://github.com/jlaneve))
- Fixed `pi-coding-agent` shipping `uuid@11`, which triggered `npm audit` moderate vulnerability reports for downstream installs; the package now depends on `uuid@14` ([#3577](https://github.com/badlogic/pi-mono/issues/3577))
- Fixed `openai-completions` streamed tool-call assembly to coalesce deltas by stable tool index when OpenAI-compatible gateways mutate tool call IDs mid-stream, preventing malformed Kimi K2.6/OpenCode tool streams from splitting one call into multiple bogus tool calls ([#3576](https://github.com/badlogic/pi-mono/issues/3576))
- Fixed `ctx.ui.setWorkingMessage()` to persist across loader recreation, matching the behavior of `ctx.ui.setWorkingIndicator()` ([#3566](https://github.com/badlogic/pi-mono/issues/3566))
- Fixed coding-agent `fs.watch` error handling for theme and git-footer watchers to retry after transient watcher failures such as `EMFILE`, avoiding startup crashes in large repos ([#3564](https://github.com/badlogic/pi-mono/issues/3564))
- Fixed built-in `kimi-coding` model generation to attach the expected `User-Agent` header so direct Kimi Coding requests use the provider's expected client identity ([#3586](https://github.com/badlogic/pi-mono/issues/3586))
- Fixed extension shortcut conflict diagnostics to display at startup instead of only on reload, so extension authors discover reserved keybinding conflicts immediately rather than discovering them later through user feedback ([#3617](https://github.com/badlogic/pi-mono/issues/3617))
- Fixed `models.json` Anthropic-compatible provider configuration to accept `compat.supportsEagerToolInputStreaming`, allowing proxies that reject per-tool `eager_input_streaming` to use the legacy fine-grained tool streaming beta header instead ([#3575](https://github.com/badlogic/pi-mono/issues/3575))
- Fixed startup banner extension labels to strip trailing `index.js`/`index.ts` suffixes ([#3596](https://github.com/badlogic/pi-mono/pull/3596) by [@aliou](https://github.com/aliou))
- Fixed OSC 9;4 terminal progress updates to stay alive in terminals such as Ghostty during long-running agent work ([#3610](https://github.com/badlogic/pi-mono/issues/3610))
- Fixed OpenAI-compatible completion usage parsing to avoid double-counting reasoning tokens already included in `completion_tokens` ([#3581](https://github.com/badlogic/pi-mono/issues/3581))
- Fixed `openai-responses` compatibility for strict OpenAI-compatible proxies by allowing `models.json` to disable the underscore-containing `session_id` header with `compat.sendSessionIdHeader: false` ([#3579](https://github.com/badlogic/pi-mono/issues/3579))
- Fixed GPT-5.5 Codex capability handling to clamp unsupported minimal reasoning to `low` and apply the model's 2.5x priority service-tier pricing multiplier ([#3618](https://github.com/badlogic/pi-mono/pull/3618) by [@markusylisiurunen](https://github.com/markusylisiurunen))

## [0.69.0] - 2026-04-22

### New Features

- TypeBox 1.x migration for extensions and SDK integrations, including TypeBox-native tool argument validation that now works in eval-restricted runtimes such as Cloudflare Workers. See [docs/extensions.md](docs/extensions.md) and [docs/sdk.md](docs/sdk.md).
- Stacked extension autocomplete providers via `ctx.ui.addAutocompleteProvider(...)`, allowing extensions to layer custom completion logic on top of built-in slash and path completion. See [docs/extensions.md#autocomplete-providers](docs/extensions.md#autocomplete-providers) and [examples/extensions/github-issue-autocomplete.ts](examples/extensions/github-issue-autocomplete.ts).
- Terminating tool results via `terminate: true`, allowing custom tools to end on a final tool call without paying for an automatic follow-up LLM turn. See [docs/extensions.md](docs/extensions.md) and [examples/extensions/structured-output.ts](examples/extensions/structured-output.ts).
- OSC 9;4 terminal progress indicators during agent streaming and compaction for supporting terminals.

### Breaking Changes

- Migrated first-party coding-agent code, SDK/examples/docs, and package metadata from `@sinclair/typebox` 0.34.x to `typebox` 1.x. New extensions, SDK integrations, and pi packages should depend on and import from `typebox`. Legacy extension loading still aliases the root `@sinclair/typebox` package, but `@sinclair/typebox/compiler` is no longer shimmed. This migration also picks up the new `@mariozechner/pi-ai` TypeBox-native validator path, so tool argument validation now works in eval-restricted runtimes such as Cloudflare Workers instead of being skipped ([#3112](https://github.com/badlogic/pi-mono/issues/3112))
- Session-replacement commands now invalidate captured pre-replacement session-bound extension objects after `ctx.newSession()`, `ctx.fork()`, and `ctx.switchSession()`. Old `pi` and command `ctx` references now throw instead of silently targeting the replaced session. Migration: if code needs to keep working in the replacement session after one of those calls, pass `withSession` to that same method and do the post-switch work there. In practice, move post-switch `pi.sendUserMessage()`, `pi.sendMessage()`, and command-ctx/session-manager access into `withSession`, and use only the `ReplacedSessionContext` passed to that callback for session-bound operations. Footguns: `withSession` runs after the old extension instance has already received `session_shutdown`, old cleanup may already have invalidated captured state, captured old `pi` / old command `ctx` are stale, and previously extracted raw objects such as `const sm = ctx.sessionManager` remain the caller's responsibility and must not be reused after the switch.

### Added

- Added support for terminating tool results via `terminate: true`, allowing custom tools to end the current tool batch without an automatic follow-up LLM call, plus a `structured-output.ts` extension example and extension docs showing the pattern ([#3525](https://github.com/badlogic/pi-mono/issues/3525))
- Added OSC 9;4 terminal progress indicators during agent streaming and compaction, so terminals like iTerm2, WezTerm, Windows Terminal, and Kitty show activity in their tab bar
- Added `ctx.ui.addAutocompleteProvider(...)` for stacking extension autocomplete providers on top of the built-in slash/path provider, plus a `github-issue-autocomplete.ts` example and extension docs ([#2983](https://github.com/badlogic/pi-mono/issues/2983))

### Fixed

- Fixed exported session HTML to sanitize markdown link URLs before rendering them into anchor tags, blocking `javascript:`-style payloads while preserving safe links in shared/exported sessions ([#3532](https://github.com/badlogic/pi-mono/issues/3532))
- Fixed `ctx.getSystemPrompt()` inside `before_agent_start` to reflect chained system-prompt changes made by earlier `before_agent_start` handlers, and clarified the extension docs around provider-payload rewrites and what `ctx.getSystemPrompt()` does and does not report ([#3539](https://github.com/badlogic/pi-mono/issues/3539))
- Fixed built-in `google-gemini-cli` model lists and selector entries to include `gemini-3.1-flash-lite-preview`, so Cloud Code Assist users no longer need manual `--model` fallback selection to use it ([#3545](https://github.com/badlogic/pi-mono/issues/3545))
- Fixed extension session-replacement flows so `ctx.newSession()`, `ctx.fork()`, `ctx.switchSession()`, and imported-session replacements fully rebind before post-switch work runs, added `withSession` replacement callbacks with fresh `ReplacedSessionContext` helpers, and make stale pre-replacement `pi` / `ctx` session-bound accesses throw instead of silently targeting the wrong session ([#2860](https://github.com/badlogic/pi-mono/issues/2860))
- Fixed `models.json` built-in provider overrides to accept `headers` without requiring `baseUrl`, so request-header-only overrides now load and apply correctly ([#3538](https://github.com/badlogic/pi-mono/issues/3538))

## [0.68.1] - 2026-04-22

### New Features

- Fireworks provider support with built-in models and `FIREWORKS_API_KEY` auth. See [README.md#providers--models](README.md#providers--models) and [docs/providers.md](docs/providers.md).
- Configurable inline tool image width via `terminal.imageWidthCells` in `/settings`. See [docs/settings.md#terminal--images](docs/settings.md#terminal--images).

### Added

- Added built-in Fireworks provider support, including `FIREWORKS_API_KEY` setup/docs and the default Fireworks model `accounts/fireworks/models/kimi-k2p6` ([#3519](https://github.com/badlogic/pi-mono/issues/3519))

### Fixed

- Fixed interactive inline tool images to honor configurable `terminal.imageWidthCells` via `/settings`, so tool-output images are no longer hard-capped to 60 terminal cells ([#3508](https://github.com/badlogic/pi-mono/issues/3508))
- Fixed `sessionDir` in `settings.json` to expand `~`, so portable session-directory settings no longer require a shell wrapper ([#3514](https://github.com/badlogic/pi-mono/issues/3514))
- Fixed parallel tool-call rows to leave the pending state as soon as each tool is finalized, while still appending persisted tool results in assistant source order ([#3503](https://github.com/badlogic/pi-mono/issues/3503))
- Fixed exported session markdown to render Markdown while showing HTML-like message content such as `<file name="...">...</file>` verbatim, so shared sessions match the TUI instead of letting the browser interpret message text ([#3484](https://github.com/badlogic/pi-mono/issues/3484))
- Fixed exported session HTML to render `grep` and `find` output through their existing TUI renderers and `ls` output through a native template renderer, avoiding missing formatting and spacing artifacts in shared sessions ([#3491](https://github.com/badlogic/pi-mono/pull/3491) by [@aliou](https://github.com/aliou))
- Fixed `@` autocomplete fuzzy search to follow symlinked directories and include symlinked paths in results ([#3507](https://github.com/badlogic/pi-mono/issues/3507))
- Fixed proxied agent streams to preserve the proxy-safe serializable subset of stream options, including session, transport, retry-delay, metadata, header, cache-retention, and thinking-budget settings ([#3512](https://github.com/badlogic/pi-mono/issues/3512))
- Hardened Anthropic streaming against malformed tool-call JSON by owning SSE parsing with defensive JSON repair, replacing the deprecated `fine-grained-tool-streaming` beta header with per-tool `eager_input_streaming`, and updating stale test model references ([#3175](https://github.com/badlogic/pi-mono/issues/3175))
- Fixed Bedrock runtime endpoint resolution to stop pinning built-in regional endpoints over `AWS_REGION` / `AWS_PROFILE`, restoring `us.*` and `eu.*` inference profile support after v0.68.0 while preserving custom VPC/proxy endpoint overrides ([#3481](https://github.com/badlogic/pi-mono/issues/3481), [#3485](https://github.com/badlogic/pi-mono/issues/3485), [#3486](https://github.com/badlogic/pi-mono/issues/3486), [#3487](https://github.com/badlogic/pi-mono/issues/3487), [#3488](https://github.com/badlogic/pi-mono/issues/3488))

## [0.68.0] - 2026-04-20

### New Features

- Configurable streaming working indicator for extensions via `ctx.ui.setWorkingIndicator()`, including animated, static, and hidden indicators. See [docs/tui.md#working-indicator](docs/tui.md#working-indicator), [docs/extensions.md](docs/extensions.md), and [examples/extensions/working-indicator.ts](examples/extensions/working-indicator.ts).
- `before_agent_start` now exposes `systemPromptOptions` (`BuildSystemPromptOptions`) so extensions can inspect the structured system-prompt inputs without re-discovering resources. See [docs/extensions.md#before_agent_start](docs/extensions.md#before_agent_start) and [examples/extensions/prompt-customizer.ts](examples/extensions/prompt-customizer.ts).
- Configurable keybindings for scoped model selector actions and session-tree filter actions. See [docs/keybindings.md](docs/keybindings.md).
- `/clone` duplicates the current active branch into a new session, while extensions can choose whether to fork `before` or `at` an entry via `ctx.fork(..., { position })`. See [README.md](README.md), [docs/extensions.md](docs/extensions.md), and [docs/session.md](docs/session.md).

### Breaking Changes

- Changed SDK and CLI tool selection from cwd-bound built-in tool instances to tool-name allowlists. `createAgentSession({ tools })` now expects `string[]` names such as `"read"` and `"bash"` instead of `Tool[]`, `--tools` now allowlists built-in, extension, and custom tools by name, and `--no-tools` now disables all tools by default rather than only built-ins. Migrate SDK code from `tools: [readTool, bashTool]` to `tools: ["read", "bash"]` ([#2835](https://github.com/badlogic/pi-mono/issues/2835), [#3452](https://github.com/badlogic/pi-mono/issues/3452))
- Removed prebuilt cwd-bound tool and tool-definition exports from `@mariozechner/pi-coding-agent`, including `readTool`, `bashTool`, `editTool`, `writeTool`, `grepTool`, `findTool`, `lsTool`, `readOnlyTools`, `codingTools`, and the corresponding `*ToolDefinition` values. Use the explicit factory exports instead, for example `createReadTool(cwd)`, `createBashTool(cwd)`, `createCodingTools(cwd)`, and `createReadToolDefinition(cwd)` ([#3452](https://github.com/badlogic/pi-mono/issues/3452))
- Removed ambient `process.cwd()` / default agent-dir fallback behavior from public resource helpers. `DefaultResourceLoader`, `loadProjectContextFiles()`, and `loadSkills()` now require explicit cwd/agent-dir style inputs, and exported system-prompt option types now require an explicit `cwd`. Pass the session or project cwd explicitly instead of relying on process-global defaults ([#3452](https://github.com/badlogic/pi-mono/issues/3452))

### Added

- Added extension support for customizing the interactive streaming working indicator via `ctx.ui.setWorkingIndicator()`, including custom animated frames, static indicators, hidden indicators, a new `working-indicator.ts` example extension, and updated extension/TUI/RPC docs ([#3413](https://github.com/badlogic/pi-mono/issues/3413))
- Added `systemPromptOptions` (`BuildSystemPromptOptions`) to `before_agent_start` extension events, so extensions can inspect the structured inputs used to build the current system prompt ([#3473](https://github.com/badlogic/pi-mono/pull/3473) by [@dljsjr](https://github.com/dljsjr))
- Added `/clone` to duplicate the current active branch into a new session, while keeping `/fork` focused on forking from a previous user message ([#2962](https://github.com/badlogic/pi-mono/issues/2962))
- Added `ctx.fork()` support for `position: "before" | "at"` so extensions and integrations can branch before a user message or duplicate the current point in the conversation; the interactive clone/fork UX builds on that runtime support ([#3431](https://github.com/badlogic/pi-mono/pull/3431) by [@mitsuhiko](https://github.com/mitsuhiko))
- Added configurable keybinding ids for scoped model selector actions and tree filter actions, so those interactive shortcuts can be remapped in `keybindings.json` ([#3343](https://github.com/badlogic/pi-mono/pull/3343) by [@mpazik](https://github.com/mpazik))
- Added `PI_OAUTH_CALLBACK_HOST` support for built-in OAuth login flows, allowing local callback servers used by `pi auth` to bind to a custom interface instead of hardcoded `127.0.0.1` ([#3409](https://github.com/badlogic/pi-mono/pull/3409) by [@Michaelliv](https://github.com/Michaelliv))
- Added `reason` and `targetSessionFile` metadata to `session_shutdown` extension events, so extensions can distinguish quit, reload, new-session, resume, and fork teardown paths ([#2863](https://github.com/badlogic/pi-mono/issues/2863))

### Changed

- Changed `pi update` to batch npm package updates per scope and run git package updates with bounded parallelism, reducing multi-package update time while preserving skip behavior for pinned and already-current packages ([#2980](https://github.com/badlogic/pi-mono/issues/2980))
- Changed Bedrock session requests to omit `maxTokens` when model token limits are unknown and to omit `temperature` when unset, letting Bedrock use provider defaults and avoid unnecessary TPM quota reservation ([#3400](https://github.com/badlogic/pi-mono/pull/3400) by [@wirjo](https://github.com/wirjo))

### Fixed

- Fixed `AgentSession` system-prompt option initialization to avoid constructing an invalid empty `BuildSystemPromptOptions`, so `npm run check` passes after `cwd` became mandatory.
- Fixed shell-path resolution to stop consulting ambient `process.cwd()` state during bash execution, so session/project-specific `shellPath` settings now follow the active coding-agent session cwd instead of the launcher cwd ([#3452](https://github.com/badlogic/pi-mono/issues/3452))
- Fixed `ctx.ui.setWorkingIndicator()` custom frames to render verbatim instead of forcing the theme accent color, so extensions now own working-indicator coloring when they customize it ([#3467](https://github.com/badlogic/pi-mono/issues/3467))
- Fixed `pi update` reinstalling npm packages that are already at the latest published version by checking the installed package version before running `npm install <pkg>@latest` ([#3000](https://github.com/badlogic/pi-mono/issues/3000))
- Fixed `@` autocomplete plain queries to stop matching against the full cwd/base path, so path fragments in worktree names no longer crowd out intended results such as `@plan` ([#2778](https://github.com/badlogic/pi-mono/issues/2778))
- Fixed built-in tool wrapping to use the same extension-runner context path as extension tools, so built-in tools receive execution context and `read` can warn when the current model does not support images ([#3429](https://github.com/badlogic/pi-mono/issues/3429))
- Fixed `openai-completions` assistant replay to preserve `compat.requiresThinkingAsText` text-part serialization, avoiding same-model follow-up crashes when previous assistant messages mix thinking and text ([#3387](https://github.com/badlogic/pi-mono/issues/3387))
- Fixed direct OpenAI Chat Completions sessions to map `sessionId` and `cacheRetention` to prompt caching fields, sending `prompt_cache_key` when caching is enabled and `prompt_cache_retention: "24h"` for direct `api.openai.com` requests with long retention ([#3426](https://github.com/badlogic/pi-mono/issues/3426))
- Fixed OpenAI-compatible Chat Completions sessions to optionally send aligned `session_id`, `x-client-request-id`, and `x-session-affinity` headers from `sessionId` via `compat.sendSessionAffinityHeaders`, improving cache-affinity routing for backends such as Fireworks ([#3430](https://github.com/badlogic/pi-mono/issues/3430))
- Fixed threaded `/resume` session relationships and current-session detection to canonicalize symlinked session paths during selector comparisons, so shared session directories no longer break parent-child matching or active-session delete protection ([#3364](https://github.com/badlogic/pi-mono/issues/3364))
- Fixed `/session`, Sessions docs, and CLI help to consistently document that session reuse supports both file paths and session IDs, and that `/session` shows the current session ID ([#3390](https://github.com/badlogic/pi-mono/issues/3390))
- Fixed Windows pnpm global install detection to recognize `\\.pnpm\\` store paths, so update notices now suggest `pnpm install -g @mariozechner/pi-coding-agent` instead of falling back to npm ([#3378](https://github.com/badlogic/pi-mono/issues/3378))
- Fixed missing `@sinclair/typebox` runtime dependency in `@mariozechner/pi-coding-agent`, so strict pnpm installs no longer fail with `ERR_MODULE_NOT_FOUND` when starting `pi` ([#3434](https://github.com/badlogic/pi-mono/issues/3434))
- Fixed xterm uppercase typing in the interactive editor by decoding printable `modifyOtherKeys` input and normalizing shifted letter matching, so `Shift+letter` no longer disappears in `pi` ([#3436](https://github.com/badlogic/pi-mono/issues/3436))
- Fixed `/compact` to reuse the session thinking level for compaction summaries instead of forcing `high`, avoiding invalid reasoning-effort errors on `github-copilot/claude-opus-4.7` sessions configured for `medium` thinking ([#3438](https://github.com/badlogic/pi-mono/issues/3438))
- Fixed shared/exported plain-text tool output to preserve indentation instead of collapsing leading whitespace in the web share page ([#3440](https://github.com/badlogic/pi-mono/issues/3440))
- Fixed exported share pages to use browser-safe `T` and `O` shortcuts with clickable header toggles for thinking and tool visibility instead of browser-reserved `Ctrl+T` / `Ctrl+O` bindings ([#3374](https://github.com/badlogic/pi-mono/pull/3374) by [@vekexasia](https://github.com/vekexasia))
- Fixed skill resolution to dedupe symlinked aliases by canonical path, so `pi config` no longer shows duplicate skill entries when `~/.pi/agent/skills` points to `~/.agents/skills` ([#3417](https://github.com/badlogic/pi-mono/pull/3417) by [@rwachtler](https://github.com/rwachtler))
- Fixed OpenRouter request attribution to include Pi app headers (`HTTP-Referer: https://pi.dev`, `X-OpenRouter-Title: pi`, `X-OpenRouter-Categories: cli-agent`) when sessions are created through the coding-agent SDK and install telemetry is enabled ([#3414](https://github.com/badlogic/pi-mono/issues/3414))
- Fixed custom-model `compat` schema/docs to support `cacheControlFormat: "anthropic"` for OpenAI-compatible providers that expose Anthropic-style prompt caching via `cache_control` markers ([#3392](https://github.com/badlogic/pi-mono/issues/3392))
- Fixed Cloud Code Assist tool schemas to strip JSON Schema meta-declaration keys before provider translation, avoiding validation failures for tool-enabled sessions that use `$schema`, `$defs`, and related metadata ([#3412](https://github.com/badlogic/pi-mono/pull/3412) by [@vladlearns](https://github.com/vladlearns))
- Fixed direct Bedrock sessions to honor `model.baseUrl` as the runtime client endpoint, restoring support for custom Bedrock VPC or proxy routes ([#3402](https://github.com/badlogic/pi-mono/pull/3402) by [@wirjo](https://github.com/wirjo))
- Fixed the `edit` tool to coerce stringified `edits` JSON before validation, so models that send the array payload as a JSON string no longer fall back to ad-hoc shell edits ([#3370](https://github.com/badlogic/pi-mono/pull/3370) by [@dannote](https://github.com/dannote))
- Fixed package manifest positive glob entries to expand before loading packaged resources, restoring manifest patterns such as `skills/**/*.md` ([#3350](https://github.com/badlogic/pi-mono/pull/3350) by [@neonspectra](https://github.com/neonspectra))

## [0.67.68] - 2026-04-17

## [0.67.67] - 2026-04-17

### New Features

- Bedrock sessions can now authenticate with `AWS_BEARER_TOKEN_BEDROCK`, enabling Converse API access without local SigV4 credentials. See [docs/providers.md#amazon-bedrock](docs/providers.md#amazon-bedrock).

### Added

- Added Bedrock bearer-token authentication support via `AWS_BEARER_TOKEN_BEDROCK`, enabling coding-agent sessions to use Bedrock Converse without local SigV4 credentials ([#3125](https://github.com/badlogic/pi-mono/pull/3125) by [@wirjo](https://github.com/wirjo))

### Fixed

- Fixed `/scoped-models` Alt+Up/Down to stay a no-op in the implicit `all enabled` state instead of materializing a full explicit enabled-model list and marking the selector dirty ([#3331](https://github.com/badlogic/pi-mono/issues/3331))
- Fixed Mistral Small 4 default thinking requests to use the model's supported reasoning control, avoiding `400` errors when starting sessions on `mistral-small-2603` and `mistral-small-latest` ([#3338](https://github.com/badlogic/pi-mono/issues/3338))
- Fixed Qwen chat-template thinking replay to preserve prior thinking across turns, so affected OpenAI-compatible models keep multi-turn tool-call arguments instead of degrading to empty `{}` payloads ([#3325](https://github.com/badlogic/pi-mono/issues/3325))
- Fixed exported HTML transcripts so text selection no longer triggers click-based expand/collapse toggles ([#3332](https://github.com/badlogic/pi-mono/pull/3332) by [@xu0o0](https://github.com/xu0o0))
- Fixed flaky git package update notifications by waiting for captured git command stdio to fully drain before comparing local and remote commit SHAs ([#3027](https://github.com/badlogic/pi-mono/issues/3027))
- Fixed system prompt dates to use a stable `YYYY-MM-DD` format instead of locale-dependent output, keeping prompts deterministic across runtimes and locales ([#2814](https://github.com/badlogic/pi-mono/issues/2814))
- Fixed auto-retry transient error detection to treat `Network connection lost.` as retryable, so dropped provider connections retry instead of terminating the agent ([#3317](https://github.com/badlogic/pi-mono/issues/3317))
- Fixed compact interactive extension startup summaries to disambiguate package extensions and repeated local `index.ts` entries by using package-aware labels and the minimal parent path needed to make local entries unique ([#3308](https://github.com/badlogic/pi-mono/issues/3308))
- Fixed git package dependency installation to use production installs (`npm install --omit=dev`) during both install and update flows, so extension runtime dependencies must come from `dependencies` and not `devDependencies` ([#3009](https://github.com/badlogic/pi-mono/issues/3009))
- Fixed `tool_result` / `afterToolCall` extension handling for error results by forwarding `details` and `isError` overrides through `AgentSession` instead of dropping them when `isError` was already true ([#3051](https://github.com/badlogic/pi-mono/issues/3051))
- Fixed missing root exports for `RpcClient` and RPC protocol types from `@mariozechner/pi-coding-agent`, so ESM consumers can import them from the main package entrypoint ([#3275](https://github.com/badlogic/pi-mono/issues/3275))
- Fixed OpenAI Codex service-tier cost accounting to trust the explicitly requested tier when the API echoes the default tier in responses, keeping session cost displays aligned with the selected tier ([#3307](https://github.com/badlogic/pi-mono/pull/3307) by [@markusylisiurunen](https://github.com/markusylisiurunen))
- Fixed parallel tool-call finalization to convert `afterToolCall` hook throws into error tool results instead of aborting the remaining tool batch ([#3084](https://github.com/badlogic/pi-mono/issues/3084))
- Fixed Bun binary asset path resolution to honor `PI_PACKAGE_DIR` for built-in themes, HTML export templates, and interactive bundled assets ([#3074](https://github.com/badlogic/pi-mono/issues/3074))
- Fixed user-message turn spacing in interactive mode by restoring an inter-message spacer before user turns (except the first user message), preventing assistant and user blocks from rendering flush together.
- Fixed interactive `/import` handling to support quoted JSONL paths with spaces, route missing JSONL files through the non-fatal `SessionImportFileNotFoundError` path, and document the `importFromJsonl()` exceptions (`SessionImportFileNotFoundError`, `MissingSessionCwdError`).

## [0.67.6] - 2026-04-16

### New Features

- Prompt templates support an `argument-hint` frontmatter field that renders before the description in the `/` autocomplete dropdown, using `<angle>` for required and `[square]` for optional arguments. See [docs/prompt-templates.md#argument-hints](docs/prompt-templates.md#argument-hints).
- New `after_provider_response` extension hook lets extensions inspect provider HTTP status codes and headers immediately after each response is received and before stream consumption begins. See [docs/extensions.md](docs/extensions.md).
- Compact interactive startup header with a comma-separated view of loaded AGENTS.md files, prompt templates, skills, and extensions. Press `Ctrl+O` to toggle the expanded listing.
- Markdown links in assistant output now render as OSC 8 hyperlinks on terminals that advertise support; unknown terminals and tmux/screen default to plain text so URLs are never silently dropped.

### Added

- Added `argument-hint` frontmatter field for prompt templates, displayed before the description in the autocomplete dropdown ([#2780](https://github.com/badlogic/pi-mono/pull/2780) by [@andresvi94](https://github.com/andresvi94))
- Added `after_provider_response` extension hook so extensions can inspect provider HTTP status codes and headers after each provider response is received and before stream consumption begins ([#3128](https://github.com/badlogic/pi-mono/issues/3128))
- Added OSC 8 hyperlink rendering for markdown links when the terminal advertises support ([#3248](https://github.com/badlogic/pi-mono/pull/3248) by [@ofa1](https://github.com/ofa1))

### Changed

- Changed interactive startup header to a compact, comma-separated view of loaded AGENTS.md files, prompt templates, skills, and extensions, with `Ctrl+O` to toggle the expanded listing ([#3267](https://github.com/badlogic/pi-mono/pull/3267))
- Tightened hyperlink capability detection to default `hyperlinks: false` for unknown terminals and force it off under tmux/screen (including nested sessions), preventing markdown link URLs from disappearing on terminals that silently swallow OSC 8 sequences ([#3248](https://github.com/badlogic/pi-mono/pull/3248))

### Fixed

- Fixed interactive user message rendering to keep bottom padding visible in terminals affected by OSC 133 prompt markers without adding an extra blank line before the following assistant message ([#3090](https://github.com/badlogic/pi-mono/issues/3090))
- Fixed `--verbose` startup output to begin with expanded startup help and loaded resource listings after the compact startup header change ([#3147](https://github.com/badlogic/pi-mono/issues/3147))
- Fixed `find` tool returning no results for path-based glob patterns such as `src/**/*.spec.ts` or `some/parent/child/**` by switching fd into full-path mode and normalizing the pattern when it contains a `/` ([#3302](https://github.com/badlogic/pi-mono/issues/3302))
- Fixed `find` tool applying nested `.gitignore` rules across sibling directories (e.g. rules from `a/.gitignore` hiding matching files under `b/`) by dropping the manual `--ignore-file` collection and delegating to fd's hierarchical `.gitignore` handling via `--no-require-git` ([#3303](https://github.com/badlogic/pi-mono/issues/3303))
- Fixed OpenAI Responses prompt caching for non-`api.openai.com` base URLs (OpenAI-compatible proxies such as litellm, theclawbay) by sending the `session_id` and `x-client-request-id` cache-affinity headers unconditionally when a `sessionId` is provided, matching the official Codex CLI behavior ([#3264](https://github.com/badlogic/pi-mono/pull/3264) by [@vegarsti](https://github.com/vegarsti))
- Fixed the `preset` example extension to snapshot the active model, thinking level, and tool set on the first preset application and restore that state when cycling back to `(none)`, instead of falling back to a hardcoded default tool list ([#3272](https://github.com/badlogic/pi-mono/pull/3272) by [@stembi](https://github.com/stembi))

## [0.67.5] - 2026-04-16

### Fixed

- Fixed Opus 4.7 adaptive thinking configuration across Anthropic and Bedrock providers by recognizing Opus 4.7 adaptive-thinking support and mapping `xhigh` reasoning to provider-supported effort values ([#3286](https://github.com/badlogic/pi-mono/pull/3286) by [@markusylisiurunen](https://github.com/markusylisiurunen))
- Fixed Zellij `Shift+Enter` regressions by reverting the Zellij-specific Kitty keyboard query bypass and restoring the previous keyboard negotiation behavior ([#3259](https://github.com/badlogic/pi-mono/issues/3259))

## [0.67.4] - 2026-04-16

### New Features

- `--no-context-files` (`-nc`) disables automatic `AGENTS.md` / `CLAUDE.md` discovery when you need a clean run without project context injection. See [README.md#context-files](README.md#context-files).
- `loadProjectContextFiles()` is now exported as a standalone utility for extensions and SDK-style integrations that need to inspect the same context-file resolution order used by the CLI. See [README.md#context-files](README.md#context-files).
- New `after_provider_response` extension hook lets extensions inspect provider HTTP status codes and headers immediately after response creation and before stream consumption. See [docs/extensions.md](docs/extensions.md).

### Added

- Added `--no-context-files` (`-nc`) to disable `AGENTS.md` and `CLAUDE.md` context file discovery and loading ([#3253](https://github.com/badlogic/pi-mono/issues/3253))
- Exported `loadProjectContextFiles()` as a standalone utility so extensions can discover project context files without instantiating a full `DefaultResourceLoader` ([#3142](https://github.com/badlogic/pi-mono/issues/3142))
- Added `after_provider_response` extension hook so extensions can inspect provider HTTP status codes and headers after each provider response is received and before stream consumption begins ([#3128](https://github.com/badlogic/pi-mono/issues/3128))

### Changed

- Added `claude-opus-4-7` model for Anthropic.
- Changed Anthropic prompt caching to add a `cache_control` breakpoint on the last tool definition, so tool schemas can be cached independently from transcript updates while preserving existing cache retention behavior ([#3260](https://github.com/badlogic/pi-mono/issues/3260))

### Fixed

- Fixed markdown strikethrough parsing in interactive rendering and HTML export to require strict double-tilde delimiters (`~~text~~`) with non-whitespace boundaries.
- Fixed shutdown handling to kill tracked detached `bash` tool child processes on exit signals, preventing orphaned background processes.
- Fixed flaky `edit-tool-no-full-redraw` TUI tests by waiting for asynchronous preview and preflight error rendering instead of relying on fixed render ticks.
- Fixed `kimi-coding` default model selection to use `kimi-for-coding` instead of `kimi-k2-thinking` ([#3242](https://github.com/badlogic/pi-mono/issues/3242))
- Fixed `ctrl+z` on native Windows to avoid crashing interactive mode, disable the default suspend binding there, and show a status message when suspend is invoked manually ([#3191](https://github.com/badlogic/pi-mono/issues/3191))
- Fixed `find` tool cancellation and responsiveness on broad searches by making `.gitignore` discovery and `fd` execution fully abort-aware and non-blocking ([#3148](https://github.com/badlogic/pi-mono/issues/3148))
- Fixed `grep` broad-search stalls when `context=0` by formatting match lines from ripgrep JSON output instead of doing synchronous per-match file reads ([#3205](https://github.com/badlogic/pi-mono/issues/3205))

## [0.67.3] - 2026-04-15

### New Features

- `renderShell: "self"` for custom and built-in tool renderers so tools can own their outer shell instead of the default boxed shell. Useful for stable large previews such as edit diffs. See [docs/extensions.md#custom-rendering](docs/extensions.md#custom-rendering).
- Interactive auto-retry status now shows a live countdown during backoff instead of a static retry delay message.

### Added

- Added `renderShell: "self"` for custom and built-in tool renderers so tools can own their outer shell instead of using the default boxed shell. This is useful for stable large previews such as edit diffs ([#3134](https://github.com/badlogic/pi-mono/issues/3134))

### Fixed

- Fixed edit diff previews to stay visible during edit permission dialogs and session replay without reintroducing large-result redraw flicker ([#3134](https://github.com/badlogic/pi-mono/issues/3134))
- Fixed `/reload` to render a static reload status box instead of an animated spinner, avoiding redraw instability during interactive reloads.
- Fixed the `plan-mode` example extension to allow `eza` in the read-only bash allowlist instead of the deprecated `exa` command ([#3240](https://github.com/badlogic/pi-mono/pull/3240) by [@rwachtler](https://github.com/rwachtler))
- Fixed `google-vertex` API key resolution to treat `gcp-vertex-credentials` as an Application Default Credentials marker instead of a literal API key, so marker-based setups correctly fall back to ADC ([#3221](https://github.com/badlogic/pi-mono/pull/3221) by [@deepkilo](https://github.com/deepkilo))
- Fixed RPC `prompt` to wait for prompt preflight success before emitting its single authoritative response, while still treating handled and queued prompts as success ([#3049](https://github.com/badlogic/pi-mono/issues/3049))
- Fixed `/scoped-models` reordering to propagate into the `/model` scoped tab, preserving the user-defined scoped model order instead of re-sorting it ([#3217](https://github.com/badlogic/pi-mono/issues/3217))
- Fixed `session_shutdown` to fire on `SIGHUP` and `SIGTERM` in interactive, print, and RPC modes so extensions can run shutdown cleanup on those signal-driven exits ([#3212](https://github.com/badlogic/pi-mono/issues/3212))
- Fixed screenshot path parsing to handle lower case am/pm in macOS screenshot filenames ([#3194](https://github.com/badlogic/pi-mono/pull/3194) by [@jay-aye-see-kay](https://github.com/jay-aye-see-kay))
- Fixed interactive auto-retry status updates to show a live countdown during backoff instead of a static retry delay message ([#3187](https://github.com/badlogic/pi-mono/issues/3187))

## [0.67.2] - 2026-04-14

### New Features

- Support for multiple `--append-system-prompt` flags, each value is appended to the system prompt separated by double newlines. See [README.md#other-options](README.md#other-options).
- Support for passing inline extension factories to `main()` for embedded integrations and custom entrypoints.
- Interactive keybinding support for Kitty `super`-modified shortcuts such as `super+k`, `super+enter`, and `ctrl+super+k`. See [docs/keybindings.md](docs/keybindings.md).

### Added

- Added support for multiple `--append-system-prompt` flags, each value is appended to the system prompt separated by double newlines ([#3171](https://github.com/badlogic/pi-mono/pull/3171) by [@aliou](https://github.com/aliou))
- Added interactive keybinding support for Kitty `super`-modified shortcuts such as `super+k`, `super+enter`, and `ctrl+super+k` ([#3111](https://github.com/badlogic/pi-mono/pull/3111) by [@sudosubin](https://github.com/sudosubin))
- Added support for passing inline extension factories to `main()` for embedded integrations and custom entrypoints ([#3099](https://github.com/badlogic/pi-mono/pull/3099) by [@pmateusz](https://github.com/pmateusz))

### Fixed

- Fixed direct OpenAI Responses and Codex SSE requests to align `prompt_cache_key`, `session_id`, and `x-client-request-id` values with the same session-derived identifier, improving prompt cache affinity for append-only sessions ([#3018](https://github.com/badlogic/pi-mono/pull/3018) by [@steipete](https://github.com/steipete))
- Fixed streaming-only `partialJson` scratch buffers leaking into persisted OpenAI Responses tool calls, which could corrupt follow-up payloads on resumed conversations.
- Fixed Ctrl+Alt letter key matching in tmux by falling through from legacy ESC-prefixed handling to CSI-u and xterm `modifyOtherKeys` parsing when the legacy form does not match ([#2989](https://github.com/badlogic/pi-mono/pull/2989) by [@kaofelix](https://github.com/kaofelix))
- Fixed the shipped `subagent` example to avoid leaking Bun virtual filesystem script paths into subagent prompts ([#3002](https://github.com/badlogic/pi-mono/pull/3002) by [@nathyong](https://github.com/nathyong))
- Fixed bordered loaders to stop their animation timer when disposed, preventing stale loader updates after teardown.

## [0.67.1] - 2026-04-13

### Telemetry

Interactive mode now sends a lightweight anonymous install/update telemetry ping to `https://pi.dev/install?version=x.y.z` after it writes `lastChangelogVersion` in `settings.json`.

Why this exists:
- Pi needs a reliable per-version usage signal to understand whether releases are being adopted and to help justify funding continued development.
- npm download counts are not a reliable proxy for actual Pi usage.

How it works:
- It only runs in interactive mode.
- It does not run in RPC mode, print mode, JSON mode, or SDK mode.
- On a fresh interactive install, Pi writes `lastChangelogVersion`, then sends the ping.
- On later interactive startups, if the local changelog contains entries newer than the previously stored `lastChangelogVersion`, Pi writes the new `lastChangelogVersion`, then sends the ping.
- The request is fire-and-forget. Startup does not wait for it, and any errors are ignored.

What data is collected:
- Only the Pi version in the request path, for example `https://pi.dev/install?version=0.67.1`.
- The server stores only aggregate per-version counters such as `{ "0.67.1": 3 }`.
- It does not store IP addresses, client identifiers, prompts, paths, models, auth state, or any other per-user data. It literally only increments a counter for that version.

How to disable it:
- `/settings` → disable `Install telemetry`
- `settings.json` → set `enableInstallTelemetry` to `false`
- `PI_OFFLINE=1`
- `PI_TELEMETRY=0`

### New Features

- Full `openRouterRouting` support in `models.json`, including fallbacks, parameter requirements, data collection, ZDR, ignore lists, quantizations, provider sorting, max price, and preferred throughput and latency constraints. See [docs/models.md](docs/models.md).
- `PI_CODING_AGENT=true` environment variable set at startup so subprocesses can detect they are running inside the coding agent.
- Updated `antigravity-image-gen.ts` example extension to use User-Agent version `1.21.9` ([#2901](https://github.com/badlogic/pi-mono/pull/2901) by [@aadishv](https://github.com/aadishv))
- Fixed `--list-models` silently swallowing `models.json` load errors; errors are now printed to stderr ([#3072](https://github.com/badlogic/pi-mono/issues/3072))
- Fixed custom models for built-in providers (e.g. `openrouter`) being silently dropped from `--list-models` by inheriting `api`/`baseUrl` from built-in model definitions and no longer requiring `apiKey` for providers with existing auth ([#2921](https://github.com/badlogic/pi-mono/issues/2921) and [#3072](https://github.com/badlogic/pi-mono/issues/3072))
### Added

- Added full `openRouterRouting` field support in `models.json`, including fallbacks, parameter requirements, data collection, ZDR, ignore lists, quantizations, provider sorting, max price, and preferred throughput and latency constraints ([#2904](https://github.com/badlogic/pi-mono/pull/2904) by [@zmberber](https://github.com/zmberber))
- Set `PI_CODING_AGENT=true` environment variable at startup so sub-processes can detect they are running inside the coding agent ([#2868](https://github.com/badlogic/pi-mono/issues/2868))

### Fixed

- Fixed interactive changelog rendering for the telemetry notes by moving the section under a `### Telemetry` heading, so startup shows the full release notes instead of only the version header.
- Updated `antigravity-image-gen.ts` example extension to use User-Agent version `1.21.9` ([#2901](https://github.com/badlogic/pi-mono/pull/2901) by [@aadishv](https://github.com/aadishv))
- Bumped default Antigravity User-Agent version to `1.21.9` ([#2901](https://github.com/badlogic/pi-mono/pull/2901) by [@aadishv](https://github.com/aadishv))
- Fixed Gemma 4 thinking level mapping to route between `MINIMAL` and `HIGH`, and map Pi reasoning levels to the model's supported thinking levels ([#2903](https://github.com/badlogic/pi-mono/pull/2903) by [@aadishv](https://github.com/aadishv))
- Fixed Gemini 2.5 Flash Lite minimal thinking budget to use the model's supported 512-token minimum instead of the regular Flash 128-token minimum, avoiding invalid thinking budget errors ([#2861](https://github.com/badlogic/pi-mono/pull/2861) by [@JasonOA888](https://github.com/JasonOA888))
- Fixed OpenAI Codex Responses requests to forward configured `serviceTier` values, restoring service-tier selection for Codex sessions ([#2996](https://github.com/badlogic/pi-mono/pull/2996) by [@markusylisiurunen](https://github.com/markusylisiurunen))
- Fixed newly generated session IDs to use UUIDv7, improving time locality for session-based request routing ([#3018](https://github.com/badlogic/pi-mono/pull/3018) by [@steipete](https://github.com/steipete))
- Fixed `Container.render()` stack overflow on long sessions by replacing `Array.push(...spread)` with a loop-based push, preventing `RangeError: Maximum call stack size exceeded` when child output exceeds the V8 call stack argument limit ([#2651](https://github.com/badlogic/pi-mono/issues/2651))
- Fixed editor sticky-column tracking around paste markers so vertical cursor navigation restores the column from before the cursor entered a paste marker instead of jumping inside or past pasted content ([#3092](https://github.com/badlogic/pi-mono/pull/3092) by [@Perlence](https://github.com/Perlence))
- Fixed queued messages typed during `/tree` branch summarization to flush automatically after navigation completes, so they no longer remain stuck in the steering queue ([#3091](https://github.com/badlogic/pi-mono/pull/3091) by [@Perlence](https://github.com/Perlence))
- Fixed npm package update check to work with packages on non-default registries by using `npm view` instead of hardcoded `registry.npmjs.org` fetch ([#3164](https://github.com/badlogic/pi-mono/pull/3164) by [@aliou](https://github.com/aliou))

## [0.67.0] - 2026-04-13

See [0.67.1]. Version 0.67.0 shipped with a changelog formatting error that caused interactive startup to show only the version header instead of the full release notes.

## [0.66.1] - 2026-04-08

### Changed

- Changed the Earendil announcement from an automatic startup notice to the hidden `/dementedelves` slash command.

## [0.66.0] - 2026-04-08

### New Features

- Earendil startup announcement with bundled inline image rendering and a linked blog post for April 8 and 9, 2026.
- Interactive Anthropic subscription auth warning when Anthropic subscription auth is active, clarifying that Anthropic third-party usage draws from extra usage and is billed per token.

### Fixed

- Fixed bare `readline` import to use `node:readline` prefix for Deno compatibility ([#2885](https://github.com/badlogic/pi-mono/issues/2885) by [@milosv-vtool](https://github.com/milosv-vtool))
- Fixed auto-retry to treat stream failures like `request ended without sending any chunks` as transient errors ([#2892](https://github.com/badlogic/pi-mono/issues/2892))
- Fixed interactive startup notices to render after the initial resource listing, and added a bundled Earendil startup announcement with inline image rendering for April 8 and 9, 2026. Moved the blog link above the image to avoid overlap with terminal image rendering.
- Fixed interactive mode to warn when Anthropic subscription auth is active, so users know Anthropic third-party usage draws from extra usage and is billed per token.

## [0.65.2] - 2026-04-06

## [0.65.1] - 2026-04-05

### Fixed

- Fixed bash output truncation by line count to always persist full output to a temp file, preventing data loss when output exceeds 2000 lines but stays under the byte threshold ([#2852](https://github.com/badlogic/pi-mono/issues/2852))
- RpcClient now forwards subprocess stderr to parent process in real-time ([#2805](https://github.com/badlogic/pi-mono/issues/2805))
- Theme file watcher now handles async `fs.watch` error events instead of crashing the process ([#2791](https://github.com/badlogic/pi-mono/issues/2791))
- Fixed stored session cwd handling so resuming or importing a session whose original working directory no longer exists now prompts interactive users to continue in the current cwd, while non-interactive modes fail with a clear error.
- Fixed resource collision precedence so project and user skills, prompt templates, and themes override package resources consistently, and CLI-provided paths take precedence over discovered resources ([#2781](https://github.com/badlogic/pi-mono/issues/2781))
- Fixed OpenAI-compatible completions streaming usage accounting to preserve `prompt_tokens_details.cache_write_tokens` and normalize OpenRouter `cached_tokens`, preventing incorrect cache read/write token and cost reporting in pi ([#2802](https://github.com/badlogic/pi-mono/issues/2802))
- Fixed CLI extension paths like `git:gist.github.com/...` being incorrectly resolved against cwd instead of being passed through to the package manager ([#2845](https://github.com/badlogic/pi-mono/pull/2845) by [@aliou](https://github.com/aliou))
- Fixed piped stdin runs with `--mode json` to preserve JSONL output instead of falling back to plain text ([#2848](https://github.com/badlogic/pi-mono/pull/2848) by [@aliou](https://github.com/aliou))
- Fixed interactive command docs to stop listing removed `/exit` as a supported quit command ([#2850](https://github.com/badlogic/pi-mono/issues/2850))

## [0.65.0] - 2026-04-03

### New Features

- **Session runtime API**: `createAgentSessionRuntime()` and `AgentSessionRuntime` provide a closure-based runtime that recreates cwd-bound services and session config on every session switch. Startup, `/new`, `/resume`, `/fork`, and import all use the same creation path. See [docs/sdk.md](docs/sdk.md) and [examples/sdk/13-session-runtime.ts](examples/sdk/13-session-runtime.ts).
- **Label timestamps in `/tree`**: Toggle timestamps on tree entries with `Shift+T`, with smart date formatting and timestamp preservation through branching ([#2691](https://github.com/badlogic/pi-mono/pull/2691) by [@w-winter](https://github.com/w-winter))
- **`defineTool()` helper**: Create standalone custom tool definitions with full TypeScript parameter type inference, no manual casts needed ([#2746](https://github.com/badlogic/pi-mono/issues/2746)). See [docs/extensions.md](docs/extensions.md).
- **Unified diagnostics**: Arg parsing, service creation, session option resolution, and resource loading all return structured diagnostics (`info`/`warning`/`error`) instead of logging or exiting. The app layer decides presentation and exit behavior.

### Breaking Changes

- Removed extension post-transition events `session_switch` and `session_fork`. Use `session_start` with `event.reason` (`"startup" | "reload" | "new" | "resume" | "fork"`). For `"new"`, `"resume"`, and `"fork"`, `session_start` includes `previousSessionFile`.
- Removed session-replacement methods from `AgentSession`. Use `AgentSessionRuntime` for `newSession()`, `switchSession()`, `fork()`, and `importFromJsonl()`. Cross-cwd session replacement rebuilds all cwd-bound runtime state and replaces the live `AgentSession` instance.
- Removed `session_directory` from extension and settings APIs.
- Unknown single-dash CLI flags (e.g. `-s`) now produce an error instead of being silently ignored.

#### Migration: Extensions

Before:

```ts
pi.on("session_switch", async (event, ctx) => { ... });
pi.on("session_fork", async (_event, ctx) => { ... });
```

After:

```ts
pi.on("session_start", async (event, ctx) => {
  // event.reason: "startup" | "reload" | "new" | "resume" | "fork"
  // event.previousSessionFile: set for "new", "resume", "fork"
});
```

#### Migration: SDK session replacement

Before:

```ts
await session.newSession();
await session.switchSession("/path/to/session.jsonl");
```

After:

```ts
import {
  type CreateAgentSessionRuntimeFactory,
  createAgentSessionFromServices,
  createAgentSessionRuntime,
  createAgentSessionServices,
  getAgentDir,
  SessionManager,
} from "@mariozechner/pi-coding-agent";

const createRuntime: CreateAgentSessionRuntimeFactory = async ({ cwd, sessionManager, sessionStartEvent }) => {
  const services = await createAgentSessionServices({ cwd });
  return {
    ...(await createAgentSessionFromServices({ services, sessionManager, sessionStartEvent })),
    services,
    diagnostics: services.diagnostics,
  };
};

const runtime = await createAgentSessionRuntime(createRuntime, {
  cwd: process.cwd(),
  agentDir: getAgentDir(),
  sessionManager: SessionManager.create(process.cwd()),
});

await runtime.newSession();
await runtime.switchSession("/path/to/session.jsonl");
await runtime.fork("entry-id");

// After replacement, runtime.session is the new live session.
// Rebind any session-local subscriptions or extension bindings.
```

### Added

- Added `createAgentSessionRuntime()` and `AgentSessionRuntime` for runtime-backed session replacement. The runtime takes a `CreateAgentSessionRuntimeFactory` closure that closes over process-global fixed inputs and recreates cwd-bound services and session config for each effective cwd. Startup and later `/new`, `/resume`, `/fork`, import all use the same factory.
- Added unified diagnostics model (`info`/`warning`/`error`) for arg parsing, service creation, session option resolution, and resource loading. Creation logic no longer logs or exits. The app layer decides presentation and exit behavior.
- Added error diagnostics for missing explicit CLI resource paths (`-e`, `--skill`, `--prompt-template`, `--theme`)

- Added `defineTool()` so standalone and array-based custom tool definitions keep inferred parameter types without manual casts ([#2746](https://github.com/badlogic/pi-mono/issues/2746))

- Added label timestamps to the session tree with a `Shift+T` toggle in `/tree`, smart date formatting, and timestamp preservation through branching ([#2691](https://github.com/badlogic/pi-mono/pull/2691) by [@w-winter](https://github.com/w-winter))

### Fixed

- Fixed startup resource loading to reuse the initial `ResourceLoader` for the first runtime, so extensions are not loaded twice before session startup and `session_start` handlers still fire for singleton-style extensions ([#2766](https://github.com/badlogic/pi-mono/issues/2766))
- Fixed retry settlement so retried agent runs wait for the full retry cycle to complete before declaring idle, preventing stale state after transient errors
- Fixed theme `export` colors to resolve theme variables the same way as `colors`, so `/export` HTML backgrounds now honor entries like `pageBg: "base"` instead of requiring inline hex values ([#2707](https://github.com/badlogic/pi-mono/issues/2707))
- Fixed Bedrock throttling errors being misidentified as context overflow, causing unnecessary compaction instead of retry ([#2699](https://github.com/badlogic/pi-mono/pull/2699) by [@xu0o0](https://github.com/xu0o0))
- Added tool streaming support for newer Z.ai models ([#2732](https://github.com/badlogic/pi-mono/pull/2732) by [@kaofelix](https://github.com/kaofelix))

## [0.64.0] - 2026-03-29

### New Features

- Extensions and SDK callers can attach a `prepareArguments` hook to any tool definition, letting them normalize or migrate raw model arguments before schema validation. The built-in `edit` tool uses this to transparently support sessions created with the old single-edit schema. See [docs/extensions.md](docs/extensions.md)
- Extensions can customize the collapsed thinking block label via `ctx.ui.setHiddenThinkingLabel()`. See [examples/extensions/hidden-thinking-label.ts](examples/extensions/hidden-thinking-label.ts) ([#2673](https://github.com/badlogic/pi-mono/issues/2673))

### Breaking Changes

- `ModelRegistry` no longer has a public constructor. SDK callers and tests must use `ModelRegistry.create(authStorage, modelsJsonPath?)` for file-backed registries or `ModelRegistry.inMemory(authStorage)` for built-in-only registries. Direct `new ModelRegistry(...)` calls no longer compile.

### Added

- Added `ToolDefinition.prepareArguments` hook to prepare raw tool call arguments before schema validation, enabling compatibility shims for resumed sessions with outdated tool schemas
- Built-in `edit` tool now uses `prepareArguments` to silently fold legacy top-level `oldText`/`newText` into `edits[]` when resuming old sessions
- Added `ctx.ui.setHiddenThinkingLabel()` so extensions can customize the collapsed thinking label in interactive mode, with a no-op in RPC mode and a runnable example extension in `examples/extensions/hidden-thinking-label.ts` ([#2673](https://github.com/badlogic/pi-mono/issues/2673))

### Fixed

- Fixed extension-queued user messages to refresh the interactive pending-message list so messages submitted while a turn is active are no longer silently dropped ([#2674](https://github.com/badlogic/pi-mono/pull/2674) by [@mrexodia](https://github.com/mrexodia))
- Fixed monorepo `tsconfig.json` path mappings to resolve `@mariozechner/pi-ai` subpath exports to source files in development checkouts ([#2625](https://github.com/badlogic/pi-mono/pull/2625) by [@ferologics](https://github.com/ferologics))
- Fixed TUI cell size response handling to consume only exact `CSI 6 ; height ; width t` replies, so bare `Escape` is no longer swallowed while waiting for terminal image metadata ([#2661](https://github.com/badlogic/pi-mono/issues/2661))
- Fixed Kitty keyboard protocol keypad functional keys to normalize to logical digits, symbols, and navigation keys, so numpad input in terminals such as iTerm2 no longer inserts Private Use Area gibberish or gets ignored ([#2650](https://github.com/badlogic/pi-mono/issues/2650))

## [0.63.2] - 2026-03-29

### New Features

- Extension handlers can now use `ctx.signal` to forward cancellation into nested model calls, `fetch()`, and other abort-aware work. See [docs/extensions.md#ctxsignal](docs/extensions.md#ctxsignal) ([#2660](https://github.com/badlogic/pi-mono/issues/2660))
- Built-in `edit` tool input now uses `edits[]` as the only replacement shape, reducing invalid tool calls caused by mixed single-edit and multi-edit schemas ([#2639](https://github.com/badlogic/pi-mono/issues/2639))
- Large multi-edit results no longer trigger full-screen redraws in the interactive TUI when the final diff is rendered ([#2664](https://github.com/badlogic/pi-mono/issues/2664))

### Added

- Added `ctx.signal` to `ExtensionContext` and wired it to the active agent turn so extension handlers can forward cancellation into nested model calls, `fetch()`, and other abort-aware work ([#2660](https://github.com/badlogic/pi-mono/issues/2660))

### Fixed

- Fixed built-in `edit` tool input to use `edits[]` as the only replacement shape, eliminating the mixed single-edit and multi-edit modes that caused repeated invalid tool calls and retries ([#2639](https://github.com/badlogic/pi-mono/issues/2639))
- Fixed edit tool TUI rendering to defer large multi-edit diffs to the settled result, avoiding full-screen redraws when the tool completes ([#2664](https://github.com/badlogic/pi-mono/issues/2664))

## [0.63.1] - 2026-03-27

### Added

- Added `gemini-3.1-pro-preview-customtools` model availability for the `google-vertex` provider ([#2610](https://github.com/badlogic/pi-mono/pull/2610) by [@gordonhwc](https://github.com/gordonhwc))

### Fixed

- Documented `tool_call` input mutation as supported extension API behavior, clarified that post-mutation inputs are not re-validated, and added regression coverage for executing mutated tool arguments ([#2611](https://github.com/badlogic/pi-mono/issues/2611))
- Fixed repeated compactions dropping messages that were kept by an earlier compaction by re-summarizing from the previous kept boundary and recalculating `tokensBefore` from the rebuilt session context ([#2608](https://github.com/badlogic/pi-mono/issues/2608))
- Fixed interactive compaction UI updates so `ctx.compact()` rebuilds the chat through unified compaction events, manual compaction no longer duplicates the summary block, and the `trigger-compact` example only fires when context usage crosses its threshold ([#2617](https://github.com/badlogic/pi-mono/issues/2617))
- Fixed interactive compaction completion to append a synthetic compaction summary after rebuilding the chat so the latest compaction remains visible at the bottom
- Fixed skill discovery to stop recursing once a directory contains `SKILL.md`, and to ignore root `*.md` files in `.agents/skills` while keeping root markdown skill files supported in `~/.pi/agent/skills`, `.pi/skills`, and package `skills/` directories ([#2603](https://github.com/badlogic/pi-mono/issues/2603))
- Fixed edit tool diff rendering for multi-edit operations with large unchanged gaps so distant edits collapse intermediate context instead of dumping the full unchanged middle block
- Fixed edit tool error rendering to avoid repeating the same exact-match failure in both the preview and result blocks
- Fixed auto-compaction overflow recovery for Ollama models when the backend returns explicit `prompt too long; exceeded max context length ...` errors instead of silently truncating input ([#2626](https://github.com/badlogic/pi-mono/issues/2626))
- Fixed built-in tool overrides that reuse built-in parameter schemas to still honor custom `renderCall` and `renderResult` renderers in the interactive TUI, restoring the `minimal-mode` example ([#2595](https://github.com/badlogic/pi-mono/issues/2595))

## [0.63.0] - 2026-03-27

### Breaking Changes

- `ModelRegistry.getApiKey(model)` has been replaced by `getApiKeyAndHeaders(model)` because `models.json` auth and header values can now resolve dynamically on every request. Extensions and SDK integrations that previously fetched only an API key must now fetch request auth per call and forward both `apiKey` and `headers`. Use `getApiKeyForProvider(provider)` only when you explicitly want provider-level API key lookup without model headers or `authHeader` handling ([#1835](https://github.com/badlogic/pi-mono/issues/1835))
- Removed deprecated direct `minimax` and `minimax-cn` model IDs, keeping only `MiniMax-M2.7` and `MiniMax-M2.7-highspeed`. Update pinned model IDs to one of those supported direct MiniMax models, or use another provider route that still exposes the older IDs ([#2596](https://github.com/badlogic/pi-mono/pull/2596) by [@liyuan97](https://github.com/liyuan97))

#### Migration Notes

Before:

```ts
const apiKey = await ctx.modelRegistry.getApiKey(model);
return streamSimple(model, messages, { apiKey });
```

After:

```ts
const auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);
if (!auth.ok) throw new Error(auth.error);
return streamSimple(model, messages, {
  apiKey: auth.apiKey,
  headers: auth.headers,
});
```

### Added

- Added `sessionDir` setting support in global and project `settings.json` so session storage can be configured without passing `--session-dir` on every invocation ([#2598](https://github.com/badlogic/pi-mono/pull/2598) by [@smcllns](https://github.com/smcllns))
- Added a startup onboarding hint in the interactive header telling users pi can explain its own features and documentation ([#2620](https://github.com/badlogic/pi-mono/pull/2620) by [@ferologics](https://github.com/ferologics))
- Added `edit` tool multi-edit support so one call can update multiple separate, disjoint regions in the same file while matching all replacements against the original file content
- Added support for `PI_TUI_WRITE_LOG` directory paths, creating a unique log file (`tui-<timestamp>-<pid>.log`) per instance for easier debugging of multiple pi sessions ([#2508](https://github.com/badlogic/pi-mono/pull/2508) by [@mrexodia](https://github.com/mrexodia))

### Changed

### Fixed

- Fixed file mutation queue ordering so concurrent `edit` and `write` operations targeting the same file stay serialized in request order instead of being reordered during queue-key resolution
- Fixed `models.json` shell-command auth and headers to resolve at request time instead of being cached into long-lived model state. pi now leaves TTL, caching, and recovery policy to user-provided wrapper commands because arbitrary shell commands need provider-specific strategies ([#1835](https://github.com/badlogic/pi-mono/issues/1835))
- Fixed Google and Vertex cost calculation to subtract cached prompt tokens from billable input tokens instead of double-counting them when providers report `cachedContentTokenCount` ([#2588](https://github.com/badlogic/pi-mono/pull/2588) by [@sparkleMing](https://github.com/sparkleMing))
- Added missing `ajv` direct dependency; previously relied on transitive install via `@mariozechner/pi-ai` which broke standalone installs ([#2252](https://github.com/badlogic/pi-mono/issues/2252))
- Fixed `/export` HTML backgrounds to honor `theme.export.pageBg`, `cardBg`, and `infoBg` instead of always deriving them from `userMessageBg` ([#2565](https://github.com/badlogic/pi-mono/issues/2565))
- Fixed interactive bash execution collapsed previews to recompute visual line wrapping at render time, so previews respect the current terminal width after resizes and split-pane width changes ([#2569](https://github.com/badlogic/pi-mono/issues/2569))
- Fixed RPC `get_session_stats` to expose `contextUsage`, so headless clients can read actual current context-window usage instead of deriving it from token totals ([#2550](https://github.com/badlogic/pi-mono/issues/2550))
- Fixed `pi update` for git packages to fetch only the tracked target branch with `--no-tags`, reducing unrelated branch and tag noise while preserving force-push-safe updates ([#2548](https://github.com/badlogic/pi-mono/issues/2548))
- Fixed print and JSON modes to emit `session_shutdown` before exit, so extensions can release long-lived resources and non-interactive runs terminate cleanly ([#2576](https://github.com/badlogic/pi-mono/issues/2576))
- Fixed GitHub Copilot OpenAI Responses requests to omit the `reasoning` field entirely when no reasoning effort is requested, avoiding `400` errors from Copilot `gpt-5-mini` rejecting `reasoning: { effort: "none" }` during internal summary calls ([#2567](https://github.com/badlogic/pi-mono/issues/2567))
- Fixed blockquote text color breaking after inline links (and other inline elements) due to missing style restoration prefix
- Fixed slash-command Tab completion from immediately chaining into argument autocomplete after completing the command name, restoring flows like `/model` that submit into a selector dialog ([#2577](https://github.com/badlogic/pi-mono/issues/2577))
- Fixed stale content and incorrect viewport tracking after TUI content shrinks or transient components inflate the working area ([#2126](https://github.com/badlogic/pi-mono/pull/2126) by [@Perlence](https://github.com/Perlence))
- Fixed `@` autocomplete to debounce editor-triggered searches, cancel in-flight `fd` lookups cleanly, and keep suggestions visible while results refresh ([#1278](https://github.com/badlogic/pi-mono/issues/1278))

## [0.62.0] - 2026-03-23

### New Features

- Built-in tools as extensible ToolDefinitions. Extension authors can now override rendering of built-in read/write/edit/bash/grep/find/ls tools with custom `renderCall`/`renderResult` components. See [docs/extensions.md](docs/extensions.md).
- Unified source provenance via `sourceInfo`. All resources, commands, tools, skills, and prompt templates now carry structured `sourceInfo` with path, scope, and source metadata. Visible in autocomplete, RPC discovery, and SDK introspection. See [docs/extensions.md](docs/extensions.md).
- AWS Bedrock cost allocation tagging. New `requestMetadata` option on `BedrockOptions` forwards key-value pairs to the Bedrock Converse API for AWS Cost Explorer split cost allocation.

### Breaking Changes

- Changed `ToolDefinition.renderCall` and `renderResult` semantics. Fallback rendering now happens only when a renderer is not defined for that slot. If `renderCall` or `renderResult` is defined, it must return a `Component`.
- Changed slash command provenance to use `sourceInfo` consistently. RPC `get_commands`, `RpcSlashCommand`, and SDK `SlashCommandInfo` no longer expose `location` or `path`. Use `sourceInfo` instead ([#1734](https://github.com/badlogic/pi-mono/issues/1734))
- Removed legacy `source` fields from `Skill` and `PromptTemplate`. Use `sourceInfo.source` for provenance instead ([#1734](https://github.com/badlogic/pi-mono/issues/1734))
- Removed `ResourceLoader.getPathMetadata()`. Resource provenance is now attached directly to loaded resources via `sourceInfo` ([#1734](https://github.com/badlogic/pi-mono/issues/1734))
- Removed `extensionPath` from `RegisteredCommand` and `RegisteredTool`. Use `sourceInfo.path` for provenance instead ([#1734](https://github.com/badlogic/pi-mono/issues/1734))

#### Migration Notes

Resource, command, and tool provenance now use `sourceInfo` consistently.

Common updates:
- RPC `get_commands`: replace `path` and `location` with `sourceInfo.path`, `sourceInfo.scope`, and `sourceInfo.source`
- `SlashCommandInfo`: replace `command.path` and `command.location` with `command.sourceInfo`
- `Skill` and `PromptTemplate`: replace `.source` with `.sourceInfo.source`
- `RegisteredCommand` and `RegisteredTool`: replace `.extensionPath` with `.sourceInfo.path`
- Custom `ResourceLoader` implementations: remove `getPathMetadata()` and read provenance from loaded resources directly

Examples:
- `command.path` -> `command.sourceInfo.path`
- `command.location === "user"` -> `command.sourceInfo.scope === "user"`
- `skill.source` -> `skill.sourceInfo.source`
- `tool.extensionPath` -> `tool.sourceInfo.path`

### Changed

- Built-in tools now work like custom tools in extensions. To get built-in tool definitions, import `readToolDefinition` / `createReadToolDefinition()` and the equivalent `bash`, `edit`, `write`, `grep`, `find`, and `ls` exports from `@mariozechner/pi-coding-agent`.
- Cleaned up `buildSystemPrompt()` so built-in tool snippets and tool-local guidelines come from built-in `ToolDefinition` metadata, while cross-tool and global prompt rules stay in system prompt construction.
- Added structured `sourceInfo` to `pi.getAllTools()` results for built-in, SDK, and extension tools ([#1734](https://github.com/badlogic/pi-mono/issues/1734))

### Fixed

- Fixed extension command name conflicts so extensions with duplicate command names can load together. Conflicting extension commands now get numeric invocation suffixes in load order, for example `/review:1` and `/review:2` ([#1061](https://github.com/badlogic/pi-mono/issues/1061))
- Fixed slash command source attribution for extension commands, prompt templates, and skills in autocomplete and command discovery ([#1734](https://github.com/badlogic/pi-mono/issues/1734))
- Fixed auto-resized image handling to enforce the inline image size limit on the final base64 payload, return text-only fallbacks when resizing cannot produce a safe image, and avoid falling back to the original image in `read` and `@file` auto-resize paths ([#2055](https://github.com/badlogic/pi-mono/issues/2055))
- Fixed `pi update` for git packages to skip destructive reset, clean, and reinstall steps when the fetched target already matches the local checkout ([#2503](https://github.com/badlogic/pi-mono/issues/2503))
- Fixed print and JSON mode to take over stdout during non-interactive startup, keeping package-manager and other incidental chatter off protocol/output stdout ([#2482](https://github.com/badlogic/pi-mono/issues/2482))
- Fixed cli-highlight auto-detection for languageless code blocks that misidentified prose as programming languages and colored random English words as keywords
- Fixed Anthropic thinking disable handling to send `thinking: { type: "disabled" }` for reasoning-capable models when thinking is explicitly off ([#2022](https://github.com/badlogic/pi-mono/issues/2022))
- Fixed explicit thinking disable handling across Google, Google Vertex, Gemini CLI, OpenAI Responses, Azure OpenAI Responses, and OpenRouter-backed OpenAI-compatible completions ([#2490](https://github.com/badlogic/pi-mono/issues/2490))
- Fixed OpenAI Responses replay for foreign tool-call item IDs by hashing foreign IDs into bounded `fc_<hash>` IDs
- Fixed OpenAI-compatible completions streams to ignore null chunks instead of crashing ([#2466](https://github.com/badlogic/pi-mono/pull/2466) by [@Cheng-Zi-Qing](https://github.com/Cheng-Zi-Qing))
- Fixed `truncateToWidth()` performance for very large strings by streaming truncation ([#2447](https://github.com/badlogic/pi-mono/issues/2447))
- Fixed markdown heading styling being lost after inline code spans within headings

## [0.61.1] - 2026-03-20

### New Features

- Typed `tool_call` handler return values via `ToolCallEventResult` exports from the top-level package and core extension entry. See [docs/extensions.md](docs/extensions.md).
- Updated default models for `zai`, `cerebras`, `minimax`, and `minimax-cn`, and aligned MiniMax catalog coverage and limits with the current provider lineup. See [docs/models.md](docs/models.md) and [docs/providers.md](docs/providers.md).

### Added

- Added `ToolCallEventResult` to the `@mariozechner/pi-coding-agent` top-level and core extension exports so extension authors can type explicit `tool_call` handler return values ([#2458](https://github.com/badlogic/pi-mono/issues/2458))

### Changed

- Changed the default models for `zai`, `cerebras`, `minimax`, and `minimax-cn` to match the current provider lineup, and added missing `MiniMax-M2.1-highspeed` model entries with normalized MiniMax context limits ([#2445](https://github.com/badlogic/pi-mono/pull/2445) by [@1500256797](https://github.com/1500256797))

### Fixed

- Fixed `ctrl+z` suspend and `fg` resume reliability by keeping the process alive until the `SIGCONT` handler restores the TUI, avoiding immediate process exit in environments with no other live event-loop handles ([#2454](https://github.com/badlogic/pi-mono/issues/2454))
- Fixed `createAgentSession({ agentDir })` to derive the default persisted session path from the provided `agentDir`, keeping session storage aligned with settings, auth, models, and resource loading ([#2457](https://github.com/badlogic/pi-mono/issues/2457))
- Fixed shared keybinding resolution to stop user overrides from evicting unrelated default shortcuts such as selector confirm and editor cursor keys ([#2455](https://github.com/badlogic/pi-mono/issues/2455))
- Fixed Termux software keyboard height changes from forcing full-screen redraws and replaying TUI history on every toggle ([#2467](https://github.com/badlogic/pi-mono/issues/2467))
- Fixed project-local npm package updates to install npm `latest` instead of reusing stale saved dependency ranges, and added `Did you mean ...?` suggestions when `pi update <source>` omits the configured npm or git source prefix ([#2459](https://github.com/badlogic/pi-mono/issues/2459))

## [0.61.0] - 2026-03-20

### New Features

- Namespaced keybinding ids and a unified keybinding manager across the app and TUI. See [docs/keybindings.md](docs/keybindings.md) and [docs/extensions.md](docs/extensions.md).
- JSONL session export and import via `/export <path.jsonl>` and `/import <path.jsonl>`. See [README.md](README.md) and [docs/session.md](docs/session.md).
- Resizable sidebar in HTML share and export views. See [README.md](README.md).

### Breaking Changes

- Interactive keybinding ids are now namespaced, and `keybindings.json` now uses those same canonical namespaced ids. Older config files are migrated automatically on startup. Custom editors and extension UI components still receive an injected `keybindings: KeybindingsManager`. They do not call `getKeybindings()` or `setKeybindings()` themselves. Declaration merging applies to that injected type ([#2391](https://github.com/badlogic/pi-mono/issues/2391))
- Extension author migration: update `keyHint()`, `keyText()`, and injected `keybindings.matches(...)` calls from old built-in names like `"expandTools"`, `"selectConfirm"`, and `"interrupt"` to namespaced ids like `"app.tools.expand"`, `"tui.select.confirm"`, and `"app.interrupt"`. See [docs/keybindings.md](docs/keybindings.md) for the full list. `pi.registerShortcut("ctrl+shift+p", ...)` is unchanged because extension shortcuts still use raw key combos, not keybinding ids.

### Added

- Added `gpt-5.4-mini` to the `openai-codex` model catalog ([#2334](https://github.com/badlogic/pi-mono/pull/2334) by [@justram](https://github.com/justram))
- Added JSONL session export and import via `/export <path.jsonl>` and `/import <path.jsonl>` ([#2356](https://github.com/badlogic/pi-mono/pull/2356) by [@hjanuschka](https://github.com/hjanuschka))
- Added a resizable sidebar to HTML share and export views ([#2435](https://github.com/badlogic/pi-mono/pull/2435) by [@dmmulroy](https://github.com/dmmulroy))

### Fixed

- Tests for session-selector-rename and tree-selector are now keybinding-agnostic, resetting editor keybindings to defaults before each test so user `keybindings.json` cannot cause failures ([#2360](https://github.com/badlogic/pi-mono/issues/2360))
- Fixed custom `keybindings.json` overrides to shadow conflicting default shortcuts globally, so bindings such as `cursorUp: ["up", "ctrl+p"]` no longer leave default actions like model cycling active ([#2391](https://github.com/badlogic/pi-mono/issues/2391))
- Fixed concurrent `edit` and `write` mutations targeting the same file to run serially, preventing interleaved file writes from overwriting each other ([#2327](https://github.com/badlogic/pi-mono/issues/2327))
- Fixed RPC mode to redirect unexpected stdout writes to stderr so JSONL responses remain parseable ([#2388](https://github.com/badlogic/pi-mono/issues/2388))
- Fixed auto-retry with tool-using retry responses so `session.prompt()` waits for the full retry loop, including tool execution, before returning ([#2440](https://github.com/badlogic/pi-mono/pull/2440) by [@pasky](https://github.com/pasky))
- Fixed `/model` to refresh scoped model lists after `models.json` changes, avoiding stale selector contents ([#2408](https://github.com/badlogic/pi-mono/pull/2408) by [@Perlence](https://github.com/Perlence))
- Fixed `validateToolArguments()` to fall back gracefully when AJV schema compilation is blocked in restricted runtimes such as Cloudflare Workers, allowing tool execution to proceed without schema validation ([#2395](https://github.com/badlogic/pi-mono/issues/2395))
- Fixed CLI startup to suppress process warnings from leaking into terminal, print, and RPC output ([#2404](https://github.com/badlogic/pi-mono/issues/2404))
- Fixed bash tool rendering to show elapsed time at the bottom of the tool block ([#2406](https://github.com/badlogic/pi-mono/issues/2406))
- Fixed custom theme file watching to reload updated theme contents from disk instead of keeping stale cached theme data ([#2417](https://github.com/badlogic/pi-mono/issues/2417), [#2003](https://github.com/badlogic/pi-mono/issues/2003))
- Fixed footer Git branch refreshes to run asynchronously so branch watcher updates do not block the UI ([#2418](https://github.com/badlogic/pi-mono/issues/2418))
- Fixed invalid extension provider registrations to surface an extension error without preventing other providers from loading ([#2431](https://github.com/badlogic/pi-mono/issues/2431))
- Fixed Windows bash execution hanging for commands that spawn detached descendants inheriting stdout/stderr handles, which caused `agent-browser` and similar commands to spin forever ([#2389](https://github.com/badlogic/pi-mono/pull/2389) by [@mrexodia](https://github.com/mrexodia))
- Fixed `google-vertex` API key resolution to ignore placeholder auth markers like `<authenticated>` and fall back to ADC instead of sending them as literal API keys ([#2335](https://github.com/badlogic/pi-mono/issues/2335))
- Fixed desktop clipboard text copy to prefer native OS clipboard integration before shell fallbacks, improving reliability on macOS and Windows ([#2347](https://github.com/badlogic/pi-mono/issues/2347))
- Fixed Bun Bedrock provider registration to survive provider resets and session reloads in compiled binaries ([#2350](https://github.com/badlogic/pi-mono/pull/2350) by [@unexge](https://github.com/unexge))
- Fixed OpenRouter reasoning requests to use the provider's nested reasoning payload, restoring thinking level support for OpenRouter models and custom compat settings ([#2298](https://github.com/badlogic/pi-mono/pull/2298) by [@PriNova](https://github.com/PriNova))
- Fixed Bedrock application inference profiles to support prompt caching when `AWS_BEDROCK_FORCE_CACHE=1` is set, covering profile ARNs that do not expose the underlying Claude model name ([#2346](https://github.com/badlogic/pi-mono/pull/2346) by [@haoqixu](https://github.com/haoqixu))

## [0.60.0] - 2026-03-18

### New Features

- Fork existing sessions directly from the CLI with `--fork <path|id>`, which copies a source session into a new session in the current project. See [README.md](README.md).
- Extensions and SDK callers can reuse pi's built-in local bash backend via `createLocalBashOperations()` for `user_bash` interception and custom bash integrations. See [docs/extensions.md#user_bash](docs/extensions.md#user_bash).
- Startup no longer updates unpinned npm and git packages automatically. Use `pi update` explicitly, while interactive mode checks for updates in the background and notifies you when newer packages are available. See [README.md](README.md).

### Breaking Changes

- Changed package startup behavior so installed unpinned packages are no longer checked or updated during startup. Use `pi update` to apply npm/git package updates, while interactive mode now checks for available package updates in the background and notifies you when updates are available ([#1963](https://github.com/badlogic/pi-mono/issues/1963))

### Added

- Added `--fork <path|id>` CLI flag to fork an existing session file or partial session UUID directly into a new session ([#2290](https://github.com/badlogic/pi-mono/issues/2290))
- Added `createLocalBashOperations()` export so extensions and SDK callers can wrap pi's built-in local bash backend for `user_bash` handling and other custom bash integrations ([#2299](https://github.com/badlogic/pi-mono/issues/2299))

### Fixed

- Fixed active model selection to refresh immediately after dynamic provider registrations or updates change the available model set ([#2291](https://github.com/badlogic/pi-mono/issues/2291))
- Fixed tmux xterm `modifyOtherKeys` matching for `Backspace`, `Escape`, and `Space`, and resolved raw `\x08` backspace ambiguity by treating Windows Terminal sessions differently from legacy terminals ([#2293](https://github.com/badlogic/pi-mono/issues/2293))
- Fixed Gemini 3 and Antigravity image tool results to stay inline as multimodal tool responses instead of being rerouted through separate follow-up messages ([#2052](https://github.com/badlogic/pi-mono/issues/2052))
- Fixed bundled Bedrock Claude 4.6 model metadata to use the correct 200K context window instead of 1M ([#2305](https://github.com/badlogic/pi-mono/issues/2305))
- Fixed `/reload` to reload keybindings from disk so changes in `keybindings.json` apply immediately ([#2309](https://github.com/badlogic/pi-mono/issues/2309))
- Fixed lazy built-in provider registration so compiled Bun binaries can still load providers on first use without eagerly bundling provider SDKs ([#2314](https://github.com/badlogic/pi-mono/issues/2314))
- Fixed built-in OAuth login flows to use aligned callback handling across Anthropic, Gemini CLI, Antigravity, and OpenAI Codex, and fixed OpenAI Codex login to complete immediately once the browser callback succeeds ([#2316](https://github.com/badlogic/pi-mono/issues/2316))
- Fixed OpenAI-compatible z.ai `network_error` responses to trigger error handling and retries instead of being treated as successful assistant output ([#2313](https://github.com/badlogic/pi-mono/issues/2313))
- Fixed print mode to merge piped stdin into the initial prompt when both stdin and an explicit prompt are provided ([#2315](https://github.com/badlogic/pi-mono/issues/2315))
- Fixed OpenAI Responses replay in coding-agent to normalize oversized resumed tool call IDs before sending them back to OpenAI Codex and other Responses-compatible targets ([#2328](https://github.com/badlogic/pi-mono/issues/2328))
- Fixed tmux extended-keys warning to stay hidden when the tmux server is unreachable, avoiding false startup warnings in sandboxed environments ([#2311](https://github.com/badlogic/pi-mono/pull/2311) by [@kaffarell](https://github.com/kaffarell))

## [0.59.0] - 2026-03-17

### New Features

- Faster startup by lazy-loading `@mariozechner/pi-ai` provider SDKs on first use instead of import time ([#2297](https://github.com/badlogic/pi-mono/issues/2297))
- Better provider retry behavior when providers return error messages as responses ([#2264](https://github.com/badlogic/pi-mono/issues/2264))
- Better terminal integration via OSC 133 command-executed markers ([#2242](https://github.com/badlogic/pi-mono/issues/2242))
- Better Git footer branch detection for repositories using reftable storage ([#2300](https://github.com/badlogic/pi-mono/issues/2300))

### Breaking Changes

- Changed custom tool system prompt behavior so extension and SDK tools are included in the default `Available tools` section only when they provide `promptSnippet`. Omitting `promptSnippet` now leaves the tool out of that section instead of falling back to `description` ([#2285](https://github.com/badlogic/pi-mono/issues/2285))

### Changed

- Lazy-load built-in `@mariozechner/pi-ai` provider modules and root provider wrappers so coding-agent startup no longer eagerly loads provider SDKs before first use ([#2297](https://github.com/badlogic/pi-mono/issues/2297))

### Fixed

- Fixed session title handling in `/tree`, compaction, and branch summarization so empty title clears render correctly and `session_info` entries stay out of summaries ([#2304](https://github.com/badlogic/pi-mono/pull/2304) by [@aliou](https://github.com/aliou))
- Fixed footer branch detection for Git repositories using reftable storage so branch names still appear correctly in the footer ([#2300](https://github.com/badlogic/pi-mono/issues/2300))
- Fixed rendered user messages to emit an OSC 133 command-executed marker after command output, improving terminal prompt integration ([#2242](https://github.com/badlogic/pi-mono/issues/2242))
- Fixed provider retry handling to treat provider-returned error messages as retryable failures instead of successful responses ([#2264](https://github.com/badlogic/pi-mono/issues/2264))
- Fixed Claude 4.6 context window overrides in bundled model metadata so coding-agent sees the intended model limits after generated catalogs are rebuilt ([#2286](https://github.com/badlogic/pi-mono/issues/2286))

## [0.58.4] - 2026-03-16

### Fixed

- Fixed steering messages to wait until the current assistant message's tool-call batch fully finishes instead of skipping pending tool calls.

## [0.58.3] - 2026-03-15

## [0.58.2] - 2026-03-15

### Added

- Improved settings, theme, thinking, and show-images selector layouts by using configurable select-list primary column sizing ([#2154](https://github.com/badlogic/pi-mono/pull/2154) by [@markusylisiurunen](https://github.com/markusylisiurunen))

### Fixed

- Fixed fuzzy `edit` matching to normalize Unicode compatibility variants before comparison, reducing false "oldText not found" failures for text such as CJK and full-width characters ([#2044](https://github.com/badlogic/pi-mono/issues/2044))
- Fixed `/model <ref>` exact matching and picker search to recognize canonical `provider/model` references when model IDs themselves contain `/`, such as LM Studio models like `unsloth/qwen3.5-35b-a3b` ([#2174](https://github.com/badlogic/pi-mono/issues/2174))
- Fixed Anthropic OAuth manual login and token refresh by using the localhost callback URI for pasted redirect/code flows and omitting `scope` from refresh-token requests ([#2169](https://github.com/badlogic/pi-mono/issues/2169))
- Fixed stale scrollback remaining after session switches by clearing the screen before wiping scrollback ([#2155](https://github.com/badlogic/pi-mono/pull/2155) by [@Perlence](https://github.com/Perlence))
- Fixed extra blank lines after markdown block elements in rendered output ([#2152](https://github.com/badlogic/pi-mono/pull/2152) by [@markusylisiurunen](https://github.com/markusylisiurunen))

## [0.58.1] - 2026-03-14

### Added

- Added `pi uninstall` alias for `pi install --uninstall` convenience

### Fixed

- Fixed OpenAI Codex websocket protocol to include required headers and properly terminate SSE streams on connection close ([#1961](https://github.com/badlogic/pi-mono/issues/1961))
- Fixed WSL clipboard image fallback to properly handle missing clipboard utilities and permission errors ([#1722](https://github.com/badlogic/pi-mono/issues/1722))
- Fixed extension `session_start` hook firing before TUI was ready, causing UI operations in `session_start` handlers to fail ([#2035](https://github.com/badlogic/pi-mono/issues/2035))
- Fixed Windows shell and path handling for package manager operations and autocomplete to properly handle drive letters and mixed path separators
- Fixed Bedrock prompt caching being enabled for non-Claude models, causing API errors ([#2053](https://github.com/badlogic/pi-mono/issues/2053))
- Fixed Qwen models via OpenAI-compatible providers by adding `qwen-chat-template` compat mode that uses Qwen's native chat template format ([#2020](https://github.com/badlogic/pi-mono/issues/2020))
- Fixed Bedrock unsigned thinking replay to handle edge cases with empty or malformed thinking blocks ([#2063](https://github.com/badlogic/pi-mono/issues/2063))
- Fixed headless clipboard fallback logging spurious errors in non-interactive environments ([#2056](https://github.com/badlogic/pi-mono/issues/2056))
- Fixed `models.json` provider compat flags not being honored when loading custom model definitions ([#2062](https://github.com/badlogic/pi-mono/issues/2062))
- Fixed xhigh reasoning effort detection for Claude Opus 4.6 to match by model ID instead of requiring explicit capability flag ([#2040](https://github.com/badlogic/pi-mono/issues/2040))
- Fixed prompt cwd containing Windows backslashes breaking bash tool execution by normalizing to forward slashes ([#2080](https://github.com/badlogic/pi-mono/issues/2080))
- Fixed editor paste to preserve literal content instead of normalizing newlines, preventing content corruption for text with embedded escape sequences ([#2064](https://github.com/badlogic/pi-mono/issues/2064))
- Fixed skill discovery recursing past skill root directories when nested SKILL.md files exist ([#2075](https://github.com/badlogic/pi-mono/issues/2075))
- Fixed tab completion to preserve `./` prefix when completing relative paths ([#2087](https://github.com/badlogic/pi-mono/issues/2087))
- Fixed npm package installs and lookups being tied to the active repository Node version by adding `npmCommand` as an argv-style settings override for package manager operations ([#2072](https://github.com/badlogic/pi-mono/issues/2072))
- Fixed `ctx.ui.getEditorText()` in the extension API returning paste markers (e.g., `[paste #1 +24 lines]`) instead of the actual pasted content ([#2084](https://github.com/badlogic/pi-mono/issues/2084))
- Fixed startup crash when downloading `fd`/`ripgrep` on first run by using `pipeline()` instead of `finished(readable.pipe(writable))` so stream errors from timeouts are caught properly, and increased the download timeout from 10s to 120s ([#2066](https://github.com/badlogic/pi-mono/issues/2066))

## [0.58.0] - 2026-03-14

### New Features

- Claude Opus 4.6, Sonnet 4.6, and related Bedrock models now use a 1M token context window (up from 200K) ([#2135](https://github.com/badlogic/pi-mono/pull/2135) by [@mitsuhiko](https://github.com/mitsuhiko)).
- Extension tool calls now execute in parallel by default, with sequential `tool_call` preflight preserved for extension interception.
- `GOOGLE_CLOUD_API_KEY` environment variable support for the `google-vertex` provider as an alternative to Application Default Credentials ([#1976](https://github.com/badlogic/pi-mono/pull/1976) by [@gordonhwc](https://github.com/gordonhwc)).
- Extensions can supply deterministic session IDs via `newSession()` ([#2130](https://github.com/badlogic/pi-mono/pull/2130) by [@zhahaoyu](https://github.com/zhahaoyu)).

### Added

- Added `GOOGLE_CLOUD_API_KEY` environment variable support for the `google-vertex` provider as an alternative to Application Default Credentials ([#1976](https://github.com/badlogic/pi-mono/pull/1976) by [@gordonhwc](https://github.com/gordonhwc))
- Added custom session ID support in `newSession()` for extensions that need deterministic session paths ([#2130](https://github.com/badlogic/pi-mono/pull/2130) by [@zhahaoyu](https://github.com/zhahaoyu))

### Changed

- Changed extension tool interception to use agent-core `beforeToolCall` and `afterToolCall` hooks instead of wrapper-based interception. Tool calls now execute in parallel by default, extension `tool_call` preflight still runs sequentially, and final tool results are emitted in assistant source order.
- Raised Claude Opus 4.6, Sonnet 4.6, and related Bedrock model context windows from 200K to 1M tokens ([#2135](https://github.com/badlogic/pi-mono/pull/2135) by [@mitsuhiko](https://github.com/mitsuhiko))

### Fixed

- Fixed `tool_call` extension handlers observing stale `sessionManager` state during multi-tool turns by draining queued agent events before each `tool_call` preflight. In parallel tool mode this guarantees state through the current assistant tool-calling message, but not sibling tool results from the same assistant message.
- Fixed interactive input fields backed by the TUI `Input` component to scroll by visual column width for wide Unicode text (CJK, fullwidth characters), preventing rendered line overflow and TUI crashes in places like search and filter inputs ([#1982](https://github.com/badlogic/pi-mono/issues/1982))
- Fixed `shift+tab` and other modified Tab bindings in tmux when `extended-keys-format` is left at the default `xterm`
- Fixed EXIF orientation not being applied during image convert and resize, causing JPEG and WebP images from phone cameras to display rotated or mirrored ([#2105](https://github.com/badlogic/pi-mono/pull/2105) by [@melihmucuk](https://github.com/melihmucuk))
- Fixed the default coding-agent system prompt to include only the current date in ISO format, not the current time, so prompt prefixes stay cacheable across reloads and resumed sessions ([#2131](https://github.com/badlogic/pi-mono/issues/2131))
- Fixed retry regex to match `server_error` and `internal_error` error types from providers, improving automatic retry coverage ([#2117](https://github.com/badlogic/pi-mono/pull/2117) by [@MadKangYu](https://github.com/MadKangYu))
- Fixed example extensions to support `PI_CODING_AGENT_DIR` environment variable for custom agent directory paths ([#2009](https://github.com/badlogic/pi-mono/pull/2009) by [@smithbm2316](https://github.com/smithbm2316))
- Fixed tool result images not being sent in `function_call_output` items for OpenAI Responses API providers, causing image data to be silently dropped in tool results ([#2104](https://github.com/badlogic/pi-mono/issues/2104))
- Fixed assistant content being sent as structured content blocks instead of plain strings in the `openai-completions` provider, causing errors with some OpenAI-compatible backends ([#2008](https://github.com/badlogic/pi-mono/pull/2008) by [@geraldoaax](https://github.com/geraldoaax))
- Fixed error details in OpenAI Responses `response.failed` handler to include status code, error code, and message instead of a generic failure ([#1956](https://github.com/badlogic/pi-mono/pull/1956) by [@drewburr](https://github.com/drewburr))
- Fixed GitHub Copilot device-code login polling to respect OAuth slow-down intervals, wait before the first token poll, and include a clearer clock-drift hint in WSL/VM environments when repeated slow-downs lead to timeout
- Fixed usage statistics not being captured for OpenAI-compatible providers that return usage in `choice.usage` instead of the standard `chunk.usage` (e.g., Moonshot/Kimi) ([#2017](https://github.com/badlogic/pi-mono/issues/2017))
- Fixed editor scroll indicator rendering crash in narrow terminal widths ([#2103](https://github.com/badlogic/pi-mono/pull/2103) by [@haoqixu](https://github.com/haoqixu))
- Fixed tab characters in editor and input paste not being normalized to spaces ([#2027](https://github.com/badlogic/pi-mono/pull/2027), [#1975](https://github.com/badlogic/pi-mono/pull/1975) by [@haoqixu](https://github.com/haoqixu))
- Fixed `wordWrapLine` overflow when wide characters (CJK, fullwidth) fall exactly at the wrap boundary ([#2082](https://github.com/badlogic/pi-mono/pull/2082) by [@haoqixu](https://github.com/haoqixu))
- Fixed paste markers not being treated as atomic segments in editor word wrapping and cursor navigation ([#2111](https://github.com/badlogic/pi-mono/pull/2111) by [@haoqixu](https://github.com/haoqixu))

## [0.57.1] - 2026-03-07

### New Features
- Tree branch folding and segment-jump navigation in `/tree`, with `Ctrl+←`/`Ctrl+→` and `Alt+←`/`Alt+→` shortcuts while `←`/`→` and `Page Up`/`Page Down` remain available for paging. See [docs/tree.md](docs/tree.md) and [docs/keybindings.md](docs/keybindings.md).
- `session_directory` extension event for customizing session directory paths before session manager creation. See [docs/extensions.md](docs/extensions.md).
- Digit keybindings (`0-9`) in the TUI keybinding system, including modified combos like `ctrl+1`. See [docs/keybindings.md](docs/keybindings.md).

### Added
- Added `/tree` branch folding and segment-jump navigation with `Ctrl+←`/`Ctrl+→` and `Alt+←`/`Alt+→`, while keeping `←`/`→` and `Page Up`/`Page Down` for paging ([#1724](https://github.com/badlogic/pi-mono/pull/1724) by [@Perlence](https://github.com/Perlence))
- Added `session_directory` extension event that fires before session manager creation, allowing extensions to customize the session directory path based on cwd and other factors. CLI `--session-dir` flag takes precedence over extension-provided paths ([#1730](https://github.com/badlogic/pi-mono/pull/1730) by [@hjanuschka](https://github.com/hjanuschka)).
- Added digit keys (`0-9`) to the keybinding system, including Kitty CSI-u and xterm `modifyOtherKeys` support for bindings like `ctrl+1` ([#1905](https://github.com/badlogic/pi-mono/issues/1905))

### Fixed
- Fixed custom tool collapsed/expanded rendering in HTML exports. Custom tools that define different collapsed vs expanded displays now render correctly in exported HTML, with expandable sections when both states differ and direct display when only expanded exists ([#1934](https://github.com/badlogic/pi-mono/pull/1934) by [@aliou](https://github.com/aliou))
- Fixed tmux startup guidance and keyboard setup warnings for modified key handling, including Ghostty `shift+enter=text:\n` remap guidance and tmux `extended-keys-format` detection ([#1872](https://github.com/badlogic/pi-mono/issues/1872))
- Fixed z.ai context overflow recovery so `model_context_window_exceeded` errors trigger auto-compaction instead of surfacing as unhandled stop reason failures ([#1937](https://github.com/badlogic/pi-mono/issues/1937))
- Fixed autocomplete selection ignoring typed text: highlight now follows the first prefix match as the user types, and exact matches are always selected on Enter ([#1931](https://github.com/badlogic/pi-mono/pull/1931) by [@aliou](https://github.com/aliou))
- Fixed slash-command Tab completion to immediately open argument completions when available ([#1481](https://github.com/badlogic/pi-mono/pull/1481) by [@barapa](https://github.com/barapa))
- Fixed explicit `pi -e <path>` extensions losing command and tool conflicts to discovered extensions by giving CLI-loaded extensions higher precedence ([#1896](https://github.com/badlogic/pi-mono/issues/1896))
- Fixed Windows external editor launch for `Ctrl+G` and `ctx.ui.editor()` so shell-based commands like `EDITOR="code --wait"` work correctly ([#1925](https://github.com/badlogic/pi-mono/issues/1925))

## [0.57.0] - 2026-03-07

### New Features

- Extensions can intercept and modify provider request payloads via `before_provider_request`. See [docs/extensions.md#before_provider_request](docs/extensions.md#before_provider_request).
- Extension UIs can use non-capturing overlays with explicit focus control via `OverlayOptions.nonCapturing` and `OverlayHandle.focus()` / `unfocus()` / `isFocused()`. See [docs/extensions.md](docs/extensions.md) and [../tui/README.md](../tui/README.md).
- RPC mode now uses strict LF-only JSONL framing for robust payload handling. See [docs/rpc.md](docs/rpc.md).

### Breaking Changes

- RPC mode now uses strict LF-delimited JSONL framing. Clients must split records on `\n` only instead of using generic line readers such as Node `readline`, which also split on Unicode separators inside JSON payloads ([#1911](https://github.com/badlogic/pi-mono/issues/1911))

### Added

- Added `before_provider_request` extension hook so extensions can inspect or replace provider payloads before requests are sent, with an example in `examples/extensions/provider-payload.ts`
- Added non-capturing overlay focus control for extension UIs via `OverlayOptions.nonCapturing` and `OverlayHandle.focus()` / `unfocus()` / `isFocused()` ([#1916](https://github.com/badlogic/pi-mono/pull/1916) by [@nicobailon](https://github.com/nicobailon))

### Changed

- Overlay compositing in extension UIs now uses focus order so focused overlays render on top while preserving stack semantics for show/hide behavior ([#1916](https://github.com/badlogic/pi-mono/pull/1916) by [@nicobailon](https://github.com/nicobailon))

### Fixed

- Fixed RPC mode stdin/stdout framing to use strict LF-delimited JSONL instead of `readline`, so payloads containing `U+2028` or `U+2029` no longer corrupt command or event streams ([#1911](https://github.com/badlogic/pi-mono/issues/1911))
- Fixed automatic overlay focus restoration in extension UIs to skip non-capturing overlays, and fixed overlay hide behavior to only reassign focus when the hidden overlay had focus ([#1916](https://github.com/badlogic/pi-mono/pull/1916) by [@nicobailon](https://github.com/nicobailon))
- Fixed `pi config` misclassifying `~/.agents/skills` as project-scoped in non-git directories under `$HOME`, so toggling those skills no longer writes project overrides to `.pi/settings.json` ([#1915](https://github.com/badlogic/pi-mono/issues/1915))

## [0.56.3] - 2026-03-06

### New Features

- `claude-sonnet-4-6` model available via the `google-antigravity` provider ([#1859](https://github.com/badlogic/pi-mono/issues/1859))
- Custom editors can now define their own `onEscape`/`onCtrlD` handlers without being overwritten by app defaults, enabling vim-mode extensions ([#1838](https://github.com/badlogic/pi-mono/issues/1838))
- Shift+Enter and Ctrl+Enter now work inside tmux via xterm modifyOtherKeys fallback ([docs/tmux.md](docs/tmux.md), [#1872](https://github.com/badlogic/pi-mono/issues/1872))
- Auto-compaction is now resilient to persistent API errors (e.g. 529 overloaded) and no longer retriggers spuriously after compaction ([#1834](https://github.com/badlogic/pi-mono/issues/1834), [#1860](https://github.com/badlogic/pi-mono/issues/1860))

### Added

- Added `claude-sonnet-4-6` model for the `google-antigravity` provider ([#1859](https://github.com/badlogic/pi-mono/issues/1859)).
- Added [tmux setup documentation](docs/tmux.md) for modified enter key support ([#1872](https://github.com/badlogic/pi-mono/issues/1872))

### Fixed

- Fixed custom editors having their `onEscape`/`onCtrlD` handlers unconditionally overwritten by app-level defaults, making vim-style escape handling impossible ([#1838](https://github.com/badlogic/pi-mono/issues/1838))
- Fixed auto-compaction retriggering on the first prompt after compaction due to stale pre-compaction assistant usage ([#1860](https://github.com/badlogic/pi-mono/issues/1860) by [@joelhooks](https://github.com/joelhooks))
- Fixed sessions never auto-compacting when hitting persistent API errors (e.g. 529 overloaded) by estimating context size from the last successful response ([#1834](https://github.com/badlogic/pi-mono/issues/1834))
- Fixed compaction summarization requests exceeding context limits by truncating tool results to 2k chars ([#1796](https://github.com/badlogic/pi-mono/issues/1796))
- Fixed `/new` leaving startup header content, including the changelog, visible after starting a fresh session ([#1880](https://github.com/badlogic/pi-mono/issues/1880))
- Fixed misleading docs and example implying that returning `{ isError: true }` from a tool's `execute` function marks the execution as failed; errors must be signaled by throwing ([#1881](https://github.com/badlogic/pi-mono/issues/1881))
- Fixed model switches through non-reasoning models to preserve the saved default thinking level instead of persisting a capability-forced `off` clamp ([#1864](https://github.com/badlogic/pi-mono/issues/1864))
- Fixed parallel pi processes failing with false "No API key found" errors due to immediate lockfile contention on `auth.json` and `settings.json` ([#1871](https://github.com/badlogic/pi-mono/issues/1871))
- Fixed OpenAI Responses reasoning replay regression that broke multi-turn reasoning continuity ([#1878](https://github.com/badlogic/pi-mono/issues/1878))

## [0.56.2] - 2026-03-05

### New Features

- GPT-5.4 support across `openai`, `openai-codex`, `azure-openai-responses`, and `opencode`, with `gpt-5.4` now the default for `openai` and `openai-codex` ([README.md](README.md), [docs/providers.md](docs/providers.md)).
- `treeFilterMode` setting to choose the default `/tree` filter mode (`default`, `no-tools`, `user-only`, `labeled-only`, `all`) ([docs/settings.md](docs/settings.md), [#1852](https://github.com/badlogic/pi-mono/pull/1852) by [@lajarre](https://github.com/lajarre)).
- Mistral native conversations integration with SDK-backed provider behavior, preserving Mistral-specific thinking and replay semantics ([README.md](README.md), [docs/providers.md](docs/providers.md), [#1716](https://github.com/badlogic/pi-mono/issues/1716)).

### Added

- Added `gpt-5.4` model availability for `openai`, `openai-codex`, `azure-openai-responses`, and `opencode` providers.
- Added `gpt-5.3-codex` fallback model availability for `github-copilot` until upstream model catalogs include it ([#1853](https://github.com/badlogic/pi-mono/issues/1853)).
- Added `treeFilterMode` setting to choose the default `/tree` filter mode (`default`, `no-tools`, `user-only`, `labeled-only`, `all`) ([#1852](https://github.com/badlogic/pi-mono/pull/1852) by [@lajarre](https://github.com/lajarre)).

### Changed

- Updated the default models for the `openai` and `openai-codex` providers to `gpt-5.4`.

### Fixed

- Fixed GPT-5.3 Codex follow-up turns dropping OpenAI Responses assistant `phase` metadata by preserving replayable signatures in session history and forwarding `phase` back to the Responses API ([#1819](https://github.com/badlogic/pi-mono/issues/1819)).
- Fixed OpenAI Responses replay to omit empty thinking blocks, avoiding invalid no-op reasoning items in follow-up turns.
- Updated Mistral integration to use the native SDK-backed provider and conversations API, including coding-agent model/provider wiring and Mistral setup documentation ([#1716](https://github.com/badlogic/pi-mono/issues/1716)).
- Fixed Antigravity reliability: endpoint cascade on 403/404, added autopush sandbox fallback, removed extra fingerprint headers ([#1830](https://github.com/badlogic/pi-mono/issues/1830)).
- Fixed `@mariozechner/pi-ai/oauth` extension imports in published installs by resolving the subpath directly from built `dist` files instead of package-root wrapper shims ([#1856](https://github.com/badlogic/pi-mono/issues/1856)).
- Fixed Gemini 3 multi-turn tool use losing structured context by using `skip_thought_signature_validator` sentinel for unsigned function calls instead of text fallback ([#1829](https://github.com/badlogic/pi-mono/issues/1829)).
- Fixed model selector filter not accepting typed characters in VS Code 1.110+ due to missing Kitty CSI-u printable decoding in the `Input` component ([#1857](https://github.com/badlogic/pi-mono/issues/1857))
- Fixed editor/footer visibility drift during terminal resize by forcing full redraws when terminal width or height changes ([#1844](https://github.com/badlogic/pi-mono/pull/1844) by [@ghoulr](https://github.com/ghoulr)).
- Fixed footer width truncation for wide Unicode text (session name, model, provider) to prevent TUI crashes from rendered lines exceeding terminal width ([#1833](https://github.com/badlogic/pi-mono/issues/1833)).
- Fixed Windows write preview background artifacts by normalizing CRLF content (`\r\n`) to LF for display rendering in tool output previews ([#1854](https://github.com/badlogic/pi-mono/issues/1854)).

## [0.56.1] - 2026-03-05

### Fixed

- Fixed extension alias fallback resolution to use ESM-aware resolution for `jiti` aliases in global installs ([#1821](https://github.com/badlogic/pi-mono/pull/1821) by [@Perlence](https://github.com/Perlence))
- Fixed markdown blockquote rendering to isolate blockquote styling from default text style, preventing style leakage.

## [0.56.0] - 2026-03-04

### New Features

- Added OpenCode Go provider support with `opencode-go` model defaults and `OPENCODE_API_KEY` environment variable support ([docs/providers.md](docs/providers.md), [#1757](https://github.com/badlogic/pi-mono/issues/1757)).
- Added `branchSummary.skipPrompt` setting to skip branch summarization prompts during tree navigation ([docs/settings.md](docs/settings.md), [#1792](https://github.com/badlogic/pi-mono/issues/1792)).
- Added `gemini-3.1-flash-lite-preview` fallback model availability for Google provider catalogs when upstream model metadata lags ([README.md](README.md), [#1785](https://github.com/badlogic/pi-mono/issues/1785)).

### Breaking Changes

- Changed scoped model thinking semantics. Scoped entries without an explicit `:<thinking>` suffix now inherit the current session thinking level when selected, instead of applying a startup-captured default.
- Moved Node OAuth runtime exports off the top-level `@mariozechner/pi-ai` entry. OAuth login and refresh must be imported from `@mariozechner/pi-ai/oauth` ([#1814](https://github.com/badlogic/pi-mono/issues/1814)).

### Added

- Added `branchSummary.skipPrompt` setting to skip the summary prompt when navigating branches ([#1792](https://github.com/badlogic/pi-mono/issues/1792)).
- Added OpenCode Go provider support with `opencode-go` model defaults and `OPENCODE_API_KEY` environment variable support ([#1757](https://github.com/badlogic/pi-mono/issues/1757)).
- Added `gemini-3.1-flash-lite-preview` fallback model availability in provider catalogs when upstream catalogs lag ([#1785](https://github.com/badlogic/pi-mono/issues/1785)).

### Changed

- Updated Antigravity Gemini 3.1 model metadata and request headers to match upstream behavior.

### Fixed

- Fixed IME hardware cursor positioning in the custom extension editor (`ctx.ui.editor()` / extension editor dialog) by propagating focus to the internal `Editor`, preventing the terminal cursor from getting stuck at the bottom-right during composition.
- Added OSC 133 semantic zone markers around rendered user messages to support terminal navigation between prompts in iTerm2, WezTerm, Kitty, Ghostty, and other compatible terminals ([#1805](https://github.com/badlogic/pi-mono/issues/1805)).
- Fixed markdown blockquotes dropping nested list content in the TUI renderer ([#1787](https://github.com/badlogic/pi-mono/issues/1787)).
- Fixed TUI width handling for regional indicator symbols to prevent wrap drift and stale characters during streaming ([#1783](https://github.com/badlogic/pi-mono/issues/1783)).
- Fixed Kitty CSI-u handling to ignore unsupported modifiers so modifier-only events do not insert printable characters ([#1807](https://github.com/badlogic/pi-mono/issues/1807)).
- Fixed single-line paste handling to insert text atomically and avoid repeated `@` autocomplete scans on large pastes ([#1812](https://github.com/badlogic/pi-mono/issues/1812)).
- Fixed extension loading with the new `@mariozechner/pi-ai/oauth` export path by aliasing the oauth subpath in the extension loader and development path mapping ([#1814](https://github.com/badlogic/pi-mono/issues/1814)).
- Fixed browser-safe provider loading regressions by preloading the Bedrock provider module in compiled Bun binaries and rebuilding binaries against fresh workspace dependencies ([#1814](https://github.com/badlogic/pi-mono/issues/1814)).
- Fixed GNU screen terminal detection by downgrading theme output to 256-color mode for `screen*` TERM values ([#1809](https://github.com/badlogic/pi-mono/issues/1809)).
- Fixed branch summarization queue handling so messages typed while summaries are generated are processed correctly ([#1803](https://github.com/badlogic/pi-mono/issues/1803)).
- Fixed compaction summary requests to avoid reasoning output for non-reasoning models ([#1793](https://github.com/badlogic/pi-mono/issues/1793)).
- Fixed overflow auto-compaction cascades so a single overflow does not trigger repeated compaction loops.
- Fixed `models.json` to allow provider-scoped custom model ids and model-level `baseUrl` overrides ([#1759](https://github.com/badlogic/pi-mono/issues/1759), [#1777](https://github.com/badlogic/pi-mono/issues/1777)).
- Fixed session selector display sanitization by stripping control characters from session display text ([#1747](https://github.com/badlogic/pi-mono/issues/1747)).
- Fixed Groq Qwen3 reasoning effort mapping for OpenAI-compatible models ([#1745](https://github.com/badlogic/pi-mono/issues/1745)).
- Fixed Bedrock `AWS_PROFILE` region resolution by honoring profile `region` values ([#1800](https://github.com/badlogic/pi-mono/issues/1800)).
- Fixed Gemini 3.1 thinking-level detection for `google` and `google-vertex` providers ([#1785](https://github.com/badlogic/pi-mono/issues/1785)).
- Fixed browser bundling compatibility for `@mariozechner/pi-ai` by removing Node-only side effects from default browser import paths ([#1814](https://github.com/badlogic/pi-mono/issues/1814)).
## [0.55.4] - 2026-03-02

### New Features

- Runtime tool registration now applies immediately in active sessions. Tools registered via `pi.registerTool()` after startup are available to `pi.getAllTools()` and the LLM without `/reload` ([docs/extensions.md](docs/extensions.md), [examples/extensions/dynamic-tools.ts](examples/extensions/dynamic-tools.ts), [#1720](https://github.com/badlogic/pi-mono/issues/1720)).
- Tool definitions can customize the default system prompt with `promptSnippet` (`Available tools`) and `promptGuidelines` (`Guidelines`) while the tool is active ([docs/extensions.md](docs/extensions.md), [#1720](https://github.com/badlogic/pi-mono/issues/1720)).
- Custom tool renderers can suppress transcript output without leaving extra spacing or empty transcript footprint in interactive rendering ([docs/extensions.md](docs/extensions.md), [#1719](https://github.com/badlogic/pi-mono/pull/1719)).

### Added

- Added optional `promptSnippet` to `ToolDefinition` for one-line entries in the default system prompt's `Available tools` section. Active extension tools appear there when registered and active ([#1237](https://github.com/badlogic/pi-mono/pull/1237) by [@semtexzv](https://github.com/semtexzv)).
- Added optional `promptGuidelines` to `ToolDefinition` so active tools can append tool-specific bullets to the default system prompt `Guidelines` section ([#1720](https://github.com/badlogic/pi-mono/issues/1720)).

### Fixed

- Fixed `pi.registerTool()` dynamic registration after session initialization. Tools registered in `session_start` and later handlers now refresh immediately, become active, and are visible to the LLM without `/reload` ([#1720](https://github.com/badlogic/pi-mono/issues/1720))
- Fixed session message persistence ordering by serializing `AgentSession` event processing, preventing `toolResult` entries from being written before their corresponding assistant tool-call messages when extension handlers are asynchronous ([#1717](https://github.com/badlogic/pi-mono/issues/1717))
- Fixed spacing artifacts when custom tool renderers intentionally suppress per-call transcript output, including extra blank rows in interactive streaming and non-zero transcript footprint for empty custom renders ([#1719](https://github.com/badlogic/pi-mono/pull/1719) by [@alasano](https://github.com/alasano))
- Fixed `session.prompt()` returning before retry completion by creating the retry promise synchronously at `agent_end` dispatch, which closes a race when earlier queued event handlers are async ([#1726](https://github.com/badlogic/pi-mono/pull/1726) by [@pasky](https://github.com/pasky))

## [0.55.3] - 2026-02-27

### Fixed

- Changed the default image paste keybinding on Windows to `alt+v` to avoid `ctrl+v` conflicts with terminal paste behavior ([#1682](https://github.com/badlogic/pi-mono/pull/1682) by [@mrexodia](https://github.com/mrexodia)).

## [0.55.2] - 2026-02-27

### New Features

- Extensions can dynamically remove custom providers via `pi.unregisterProvider(name)`, restoring any built-in models that were overridden, without requiring `/reload` ([docs](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/docs/custom-provider.md)).
- `pi.registerProvider()` now takes effect immediately when called outside the initial extension load phase (e.g. from a command handler), removing the need for `/reload` after late registrations.

### Added

- `pi.unregisterProvider(name)` removes a dynamically registered provider and its models from the registry without requiring `/reload`. Built-in models that were overridden by the provider are restored ([#1669](https://github.com/badlogic/pi-mono/pull/1669) by [@aliou](https://github.com/aliou)).

### Fixed

- `pi.registerProvider()` now takes effect immediately when called after the initial extension load phase (e.g. from a command handler). Previously the registration sat in a pending queue that was never flushed until the next `/reload` ([#1669](https://github.com/badlogic/pi-mono/pull/1669) by [@aliou](https://github.com/aliou)).
- Fixed duplicate session headers when forking from a point before any assistant message. `createBranchedSession` now defers file creation to `_persist()` when the branched path has no assistant message, matching the `newSession()` contract ([#1672](https://github.com/badlogic/pi-mono/pull/1672) by [@w-winter](https://github.com/w-winter)).
- Fixed SIGINT being delivered to pi while the process is suspended (e.g. via `ctrl+z`), which could corrupt terminal state on resume ([#1668](https://github.com/badlogic/pi-mono/pull/1668) by [@aliou](https://github.com/aliou)).
- Fixed Z.ai thinking control using wrong parameter name, causing thinking to always be enabled and wasting tokens/latency ([#1674](https://github.com/badlogic/pi-mono/pull/1674) by [@okuyam2y](https://github.com/okuyam2y))
- Fixed `redacted_thinking` blocks being silently dropped during Anthropic streaming, and related issues with interleaved-thinking beta headers and temperature being sent alongside extended thinking ([#1665](https://github.com/badlogic/pi-mono/pull/1665) by [@tctev](https://github.com/tctev))
- Fixed `(external, cli)` user-agent flag causing 401 errors on Anthropic setup-token endpoint ([#1677](https://github.com/badlogic/pi-mono/pull/1677) by [@LazerLance777](https://github.com/LazerLance777))
- Fixed crash when OpenAI-compatible provider returns a chunk with no `choices` array ([#1671](https://github.com/badlogic/pi-mono/issues/1671))

## [0.55.1] - 2026-02-26

### New Features

- Added offline startup mode via `--offline` (or `PI_OFFLINE`) to disable startup network operations, with startup network timeouts to avoid hangs in restricted or offline environments.
- Added `gemini-3.1-pro-preview` model support to the `google-gemini-cli` provider ([#1599](https://github.com/badlogic/pi-mono/pull/1599) by [@audichuang](https://github.com/audichuang)).

### Fixed

- Fixed offline startup hangs by adding offline startup behavior and network timeouts during managed tool setup ([#1631](https://github.com/badlogic/pi-mono/pull/1631) by [@mcollina](https://github.com/mcollina))
- Fixed Windows VT input initialization in ESM by loading koffi via createRequire, avoiding runtime and bundling issues in end-user environments ([#1627](https://github.com/badlogic/pi-mono/pull/1627) by [@kaste](https://github.com/kaste))
- Fixed managed `fd`/`rg` bootstrap on Windows in Git Bash by using `extract-zip` for `.zip` archives, searching extracted layouts more robustly, and isolating extraction temp directories to avoid concurrent download races ([#1348](https://github.com/badlogic/pi-mono/issues/1348))
- Fixed extension loading on Windows when resolving `@sinclair/typebox` aliases so subpath imports like `@sinclair/typebox/compiler` resolve correctly.
- Fixed adaptive thinking for Claude Sonnet 4.6 in Anthropic and Bedrock providers, and clamped unsupported `xhigh` effort values to supported levels ([#1548](https://github.com/badlogic/pi-mono/pull/1548) by [@tctev](https://github.com/tctev))
- Fixed Vertex ADC credential detection race by avoiding caching a false negative during async import initialization ([#1550](https://github.com/badlogic/pi-mono/pull/1550) by [@jeremiahgaylord-web](https://github.com/jeremiahgaylord-web))
- Fixed subagent extension example to resolve user agents from the configured agent directory instead of hardcoded paths ([#1559](https://github.com/badlogic/pi-mono/pull/1559) by [@tianshuwang](https://github.com/tianshuwang))

## [0.55.0] - 2026-02-24

### Breaking Changes

- Resource precedence for extensions, skills, prompts, themes, and slash-command name collisions is now project-first (`cwd/.pi`) before user-global (`~/.pi/agent`). If you relied on global resources overriding project resources with the same names, rename or reorder your resources.
- Extension registration conflicts no longer unload the entire later extension. All extensions stay loaded, and conflicting command/tool/flag names are resolved by first registration in load order.

## [0.54.2] - 2026-02-23

### Fixed

- Fixed `.pi` folder being created unnecessarily when only reading settings. The folder is now only created when writing project-specific settings.
- Fixed extension-driven runtime theme changes to persist in settings so `/settings` reflects the active `currentTheme` after `ctx.ui.setTheme(...)` ([#1483](https://github.com/badlogic/pi-mono/pull/1483) by [@ferologics](https://github.com/ferologics))
- Fixed interactive mode freezes during large streaming `write` tool calls by using incremental syntax highlighting while partial arguments stream, with a final full re-highlight after tool-call arguments complete.

## [0.54.1] - 2026-02-22

### Fixed

- Externalized koffi from bun binary builds, reducing archive sizes by ~15MB per platform (e.g. darwin-arm64: 43MB -> 28MB). Koffi's Windows-only `.node` file is now shipped alongside the Windows binary only.

## [0.54.0] - 2026-02-19

### Added

- Added default skill auto-discovery for `.agents/skills` locations. Pi now discovers project skills from `.agents/skills` in `cwd` and ancestor directories (up to git repo root, or filesystem root when not in a repo), and global skills from `~/.agents/skills`, in addition to existing `.pi` skill paths.

## [0.53.1] - 2026-02-19

### Changed

- Added Gemini 3.1 model catalog entries for all built-in providers that currently expose it: `google`, `google-vertex`, `opencode`, `openrouter`, and `vercel-ai-gateway`.
- Added Claude Opus 4.6 Thinking to the `google-antigravity` model catalog.

## [0.53.0] - 2026-02-17

### Breaking Changes

- `SettingsManager` persistence semantics changed for SDK consumers. Setters now update in-memory state immediately and queue disk writes. Code that requires durable on-disk settings must call `await settingsManager.flush()`.
- `AuthStorage` constructor is no longer public. Use static factories (`AuthStorage.create(...)`, `AuthStorage.fromStorage(...)`, `AuthStorage.inMemory(...)`). This breaks code that used `new AuthStorage(...)` directly.

### Added

- Added `SettingsManager.drainErrors()` for caller-controlled settings I/O error handling without manager-side console output.
- Added auth storage backends (`FileAuthStorageBackend`, `InMemoryAuthStorageBackend`) and `AuthStorage.fromStorage(...)` for storage-first auth persistence wiring.
- Added Anthropic `claude-sonnet-4-6` model fallback entry to generated model definitions.

### Changed

- `SettingsManager` now uses scoped storage abstraction with per-scope locked read/merge/write persistence for global and project settings.

### Fixed

- Fixed project settings persistence to preserve unrelated external edits via merge-on-write, while still applying in-memory changes for modified keys.
- Fixed auth credential persistence to preserve unrelated external edits to `auth.json` via locked read/merge/write updates.
- Fixed auth load/persist error surfacing by buffering errors and exposing them via `AuthStorage.drainErrors()`.

## [0.52.12] - 2026-02-13

### Added

- Added `transport` setting (`"sse"`, `"websocket"`, `"auto"`) to `/settings` and `settings.json` for providers that support multiple transports (currently `openai-codex` via OpenAI Codex Responses).

### Changed

- Interactive mode now applies transport changes immediately to the active agent session.
- Settings migration now maps legacy `websockets: boolean` to the new `transport` setting.

## [0.52.11] - 2026-02-13

### Added

- Added MiniMax M2.5 model entries for `minimax`, `minimax-cn`, `openrouter`, and `vercel-ai-gateway` providers, plus `minimax-m2.5-free` for `opencode`.

## [0.52.10] - 2026-02-12

### New Features

- Extension terminal input interception via `terminal_input`, allowing extensions to consume or transform raw input before normal TUI handling. See [docs/extensions.md](docs/extensions.md).
- Expanded CLI model selection: `--model` now supports `provider/id`, fuzzy matching, and `:<thinking>` suffixes. See [README.md](README.md) and [docs/models.md](docs/models.md).
- Safer package source handling with stricter git source parsing and improved local path normalization. See [docs/packages.md](docs/packages.md).
- New built-in model definition `gpt-5.3-codex-spark` for OpenAI and OpenAI Codex providers.
- Improved OpenAI stream robustness for malformed trailing tool-call JSON in partial chunks.
- Added built-in GLM-5 model support via z.ai and OpenRouter provider catalogs.

### Breaking Changes

- `ContextUsage.tokens` and `ContextUsage.percent` are now `number | null`. After compaction, context token count is unknown until the next LLM response, so these fields return `null`. Extensions that read `ContextUsage` must handle the `null` case. Removed `usageTokens`, `trailingTokens`, and `lastUsageIndex` fields from `ContextUsage` (implementation details that should not have been public) ([#1382](https://github.com/badlogic/pi-mono/pull/1382) by [@ferologics](https://github.com/ferologics))
- Git source parsing is now strict without `git:` prefix: only protocol URLs are treated as git (`https://`, `http://`, `ssh://`, `git://`). Shorthand sources like `github.com/org/repo` and `git@github.com:org/repo` now require the `git:` prefix. ([#1426](https://github.com/badlogic/pi-mono/issues/1426))

### Added

- Added extension event forwarding for message and tool execution lifecycles (`message_start`, `message_update`, `message_end`, `tool_execution_start`, `tool_execution_update`, `tool_execution_end`) ([#1375](https://github.com/badlogic/pi-mono/pull/1375) by [@sumeet](https://github.com/sumeet))
- Added `terminal_input` extension event to intercept, consume, or transform raw terminal input before normal TUI handling.
- Added `gpt-5.3-codex-spark` model definition for OpenAI and OpenAI Codex providers (research preview).

### Changed

- Routed GitHub Copilot Claude 4.x models through Anthropic Messages API, with updated Copilot header handling for Claude model requests.

### Fixed

- Fixed context usage percentage in footer showing stale pre-compaction values. After compaction the footer now shows `?/200k` until the next LLM response provides accurate usage ([#1382](https://github.com/badlogic/pi-mono/pull/1382) by [@ferologics](https://github.com/ferologics))
- Fixed `_checkCompaction()` using the first compaction entry instead of the latest, which could cause incorrect overflow detection with multiple compactions ([#1382](https://github.com/badlogic/pi-mono/pull/1382) by [@ferologics](https://github.com/ferologics))
- `--model` now works without `--provider`, supports `provider/id` syntax, fuzzy matching, and `:<thinking>` suffix (e.g., `--model sonnet:high`, `--model openai/gpt-4o`) ([#1350](https://github.com/badlogic/pi-mono/pull/1350) by [@mitsuhiko](https://github.com/mitsuhiko))
- Fixed local package path normalization for extension sources while tightening git source parsing rules ([#1426](https://github.com/badlogic/pi-mono/issues/1426))
- Fixed extension terminal input listeners not being cleared during session resets, which could leave stale handlers active.
- Fixed Termux bootstrap package name for `fd` installation ([#1433](https://github.com/badlogic/pi-mono/pull/1433))
- Fixed `@` file autocomplete fuzzy matching to prioritize path-prefix and segment matches for nested paths ([#1423](https://github.com/badlogic/pi-mono/issues/1423))
- Fixed OpenAI streaming tool-call parsing to tolerate malformed trailing JSON in partial chunks ([#1424](https://github.com/badlogic/pi-mono/issues/1424))

## [0.52.9] - 2026-02-08

### New Features

- Extensions can trigger a full runtime reload via `ctx.reload()`, useful for hot-reloading configuration or restarting the agent. See [docs/extensions.md](docs/extensions.md) and the [`reload-runtime` example](examples/extensions/reload-runtime.ts) ([#1371](https://github.com/badlogic/pi-mono/issues/1371))
- Short CLI disable aliases: `-ne` (`--no-extensions`), `-ns` (`--no-skills`), and `-np` (`--no-prompt-templates`) for faster interactive usage and scripting.
- `/export` HTML now includes collapsible tool input schemas (parameter names, types, and descriptions), improving session review and sharing workflows ([#1416](https://github.com/badlogic/pi-mono/pull/1416) by [@marchellodev](https://github.com/marchellodev)).
- `pi.getAllTools()` now exposes tool parameters in addition to name and description, enabling richer extension integrations ([#1416](https://github.com/badlogic/pi-mono/pull/1416) by [@marchellodev](https://github.com/marchellodev)).

### Added

- Added `ctx.reload()` to the extension API for programmatic runtime reload ([#1371](https://github.com/badlogic/pi-mono/issues/1371))
- Added short aliases for disable flags: `-ne` for `--no-extensions`, `-ns` for `--no-skills`, `-np` for `--no-prompt-templates`
- `/export` HTML now includes tool input schema (parameter names, types, descriptions) in a collapsible section under each tool ([#1416](https://github.com/badlogic/pi-mono/pull/1416) by [@marchellodev](https://github.com/marchellodev))
- `pi.getAllTools()` now returns tool parameters in addition to name and description ([#1416](https://github.com/badlogic/pi-mono/pull/1416) by [@marchellodev](https://github.com/marchellodev))

### Fixed

- Fixed extension source parsing so dot-prefixed local paths (for example `.pi/extensions/foo.ts`) are treated as local paths instead of git URLs
- Fixed fd/rg download failing on Windows due to `unzip` not being available; now uses `tar` for both `.tar.gz` and `.zip` extraction, with proper error reporting ([#1348](https://github.com/badlogic/pi-mono/issues/1348))
- Fixed RPC mode documentation incorrectly stating `ctx.hasUI` is `false`; it is `true` because dialog and fire-and-forget UI methods work via the RPC sub-protocol. Also documented missing unsupported/degraded methods (`pasteToEditor`, `getAllThemes`, `getTheme`, `setTheme`) ([#1411](https://github.com/badlogic/pi-mono/pull/1411) by [@aliou](https://github.com/aliou))
- Fixed `rg` not available in bash tool by downloading it at startup alongside `fd` ([#1348](https://github.com/badlogic/pi-mono/issues/1348))
- Fixed `custom-compaction` example to use `ModelRegistry` ([#1387](https://github.com/badlogic/pi-mono/issues/1387))
- Google providers now support full JSON Schema in tool declarations (anyOf, oneOf, const, etc.) ([#1398](https://github.com/badlogic/pi-mono/issues/1398) by [@jarib](https://github.com/jarib))
- Reverted incorrect Antigravity model change: `claude-opus-4-6-thinking` back to `claude-opus-4-5-thinking` (model does not exist on Antigravity endpoint)
- Updated the Antigravity system instruction to a more compact version for Google Gemini CLI compatibility
- Corrected opencode context windows for Claude Sonnet 4 and 4.5 ([#1383](https://github.com/badlogic/pi-mono/issues/1383))
- Fixed subagent example unknown-agent errors to include available agent names ([#1414](https://github.com/badlogic/pi-mono/pull/1414) by [@dnouri](https://github.com/dnouri))

## [0.52.8] - 2026-02-07

### New Features

- Emacs-style kill ring (`ctrl+k`/`ctrl+y`/`alt+y`) and undo (`ctrl+z`) in the editor input ([#1373](https://github.com/badlogic/pi-mono/pull/1373) by [@Perlence](https://github.com/Perlence))
- OpenRouter `auto` model alias (`openrouter:auto`) for automatic model routing ([#1361](https://github.com/badlogic/pi-mono/pull/1361) by [@yogasanas](https://github.com/yogasanas))
- Extensions can programmatically paste content into the editor via `pasteToEditor` in the extension UI context. See [docs/extensions.md](docs/extensions.md) ([#1351](https://github.com/badlogic/pi-mono/pull/1351) by [@kaofelix](https://github.com/kaofelix))
- `pi <package> --help` and invalid subcommands now show helpful output instead of failing silently ([#1347](https://github.com/badlogic/pi-mono/pull/1347) by [@ferologics](https://github.com/ferologics))

### Added

- Added `pasteToEditor` to extension UI context for programmatic editor paste ([#1351](https://github.com/badlogic/pi-mono/pull/1351) by [@kaofelix](https://github.com/kaofelix))
- Added package subcommand help and friendly error messages for invalid commands ([#1347](https://github.com/badlogic/pi-mono/pull/1347) by [@ferologics](https://github.com/ferologics))
- Added OpenRouter `auto` model alias for automatic model routing ([#1361](https://github.com/badlogic/pi-mono/pull/1361) by [@yogasanas](https://github.com/yogasanas))
- Added kill ring (ctrl+k/ctrl+y/alt+y) and undo (ctrl+z) support to the editor input ([#1373](https://github.com/badlogic/pi-mono/pull/1373) by [@Perlence](https://github.com/Perlence))

### Changed

- Replaced Claude Opus 4.5 with Opus 4.6 as default model ([#1345](https://github.com/badlogic/pi-mono/pull/1345) by [@calvin-hpnet](https://github.com/calvin-hpnet))

### Fixed

- Fixed temporary git package caches (`-e <git-url>`) to refresh on cache hits for unpinned sources, including detached/no-upstream checkouts
- Fixed aborting retries when an extension customizes the editor ([#1364](https://github.com/badlogic/pi-mono/pull/1364) by [@Perlence](https://github.com/Perlence))
- Fixed autocomplete not propagating to custom editors created by extensions ([#1372](https://github.com/badlogic/pi-mono/pull/1372) by [@Perlence](https://github.com/Perlence))
- Fixed extension shutdown to use clean TUI shutdown path, preventing orphaned processes

## [0.52.7] - 2026-02-06

### New Features

- Per-model overrides in `models.json` via `modelOverrides`, allowing customization of built-in provider models without replacing provider model lists. See [docs/models.md#per-model-overrides](docs/models.md#per-model-overrides).
- `models.json` provider `models` now merge with built-in models by `id`, so custom models can be added or replace matching built-ins without full provider replacement. See [docs/models.md#overriding-built-in-providers](docs/models.md#overriding-built-in-providers).
- Bedrock proxy support for unauthenticated endpoints via `AWS_BEDROCK_SKIP_AUTH` and `AWS_BEDROCK_FORCE_HTTP1`. See [docs/providers.md](docs/providers.md).

### Breaking Changes

- Changed `models.json` provider `models` behavior from full replacement to merge-by-id with built-in models. Built-in models are now kept by default, and custom models upsert by `id`.

### Added

- Added `modelOverrides` in `models.json` to customize individual built-in models per provider without full provider replacement ([#1332](https://github.com/badlogic/pi-mono/pull/1332) by [@charles-cooper](https://github.com/charles-cooper))
- Added `AWS_BEDROCK_SKIP_AUTH` and `AWS_BEDROCK_FORCE_HTTP1` environment variables for connecting to unauthenticated Bedrock proxies ([#1320](https://github.com/badlogic/pi-mono/pull/1320) by [@virtuald](https://github.com/virtuald))

### Fixed

- Fixed extra spacing between thinking-only assistant content and subsequent tool execution blocks when assistant messages contain no text
- Fixed queued steering/follow-up/custom messages remaining stuck after threshold auto-compaction by resuming the agent loop when Agent-level queues still contain pending messages ([#1312](https://github.com/badlogic/pi-mono/pull/1312) by [@ferologics](https://github.com/ferologics))
- Fixed `tool_result` extension handlers to chain result patches across handlers instead of last-handler-wins behavior ([#1280](https://github.com/badlogic/pi-mono/issues/1280))
- Fixed compromised auth lock files being handled gracefully instead of crashing auth storage initialization ([#1322](https://github.com/badlogic/pi-mono/issues/1322))
- Fixed Bedrock adaptive thinking handling for Claude Opus 4.6 with interleaved thinking beta responses ([#1323](https://github.com/badlogic/pi-mono/pull/1323) by [@markusylisiurunen](https://github.com/markusylisiurunen))
- Fixed OpenAI Responses API requests to use `store: false` by default to avoid server-side history logging ([#1308](https://github.com/badlogic/pi-mono/issues/1308))
- Fixed interactive mode startup by initializing autocomplete after resources are loaded ([#1328](https://github.com/badlogic/pi-mono/issues/1328))
- Fixed `modelOverrides` merge behavior for nested objects and documented usage details ([#1062](https://github.com/badlogic/pi-mono/issues/1062))

## [0.52.6] - 2026-02-05

### Breaking Changes

- Removed `/exit` command handling. Use `/quit` to exit ([#1303](https://github.com/badlogic/pi-mono/issues/1303))

### Fixed

- Fixed `/quit` being shadowed by fuzzy slash command autocomplete matches from skills by adding `/quit` to built-in command autocomplete ([#1303](https://github.com/badlogic/pi-mono/issues/1303))
- Fixed local package source parsing and settings normalization regression that misclassified relative paths as git URLs and prevented globally installed local packages from loading after restart ([#1304](https://github.com/badlogic/pi-mono/issues/1304))

## [0.52.5] - 2026-02-05

### Fixed

- Fixed thinking level capability detection so Anthropic Opus 4.6 models expose `xhigh` in selectors and cycling

## [0.52.4] - 2026-02-05

### Fixed

- Fixed extensions setting not respecting `package.json` `pi.extensions` manifest when directory is specified directly ([#1302](https://github.com/badlogic/pi-mono/pull/1302) by [@hjanuschka](https://github.com/hjanuschka))

## [0.52.3] - 2026-02-05

### Fixed

- Fixed git package parsing fallback for unknown hosts so enterprise git sources like `git:github.tools.sap/org/repo` are treated as git packages instead of local paths
- Fixed git package `@ref` parsing for shorthand, HTTPS, and SSH source formats, including branch refs with slashes
- Fixed Bedrock default model ID from `us.anthropic.claude-opus-4-6-v1:0` to `us.anthropic.claude-opus-4-6-v1`
- Fixed Bedrock Opus 4.6 model metadata (IDs, cache pricing) and added missing EU profile
- Fixed Claude Opus 4.6 context window metadata to 200000 for Anthropic and OpenCode providers

## [0.52.2] - 2026-02-05

### Changed

- Updated default model for `anthropic` provider to `claude-opus-4-6`
- Updated default model for `openai-codex` provider to `gpt-5.3-codex`
- Updated default model for `amazon-bedrock` provider to `us.anthropic.claude-opus-4-6-v1:0`
- Updated default model for `vercel-ai-gateway` provider to `anthropic/claude-opus-4-6`
- Updated default model for `opencode` provider to `claude-opus-4-6`

## [0.52.1] - 2026-02-05

## [0.52.0] - 2026-02-05

### New Features

- Claude Opus 4.6 model support.
- GPT-5.3 Codex model support (OpenAI Codex provider only).
- SSH URL support for git packages. See [docs/packages.md](docs/packages.md).
- `auth.json` API keys now support shell command resolution (`!command`) and environment variable lookup. See [docs/providers.md](docs/providers.md).
- Model selectors now display the selected model name.

### Added

- API keys in `auth.json` now support shell command resolution (`!command`) and environment variable lookup, matching the behavior in `models.json`
- Added `minimal-mode.ts` example extension demonstrating how to override built-in tool rendering for a minimal display mode
- Added Claude Opus 4.6 model to the model catalog
- Added GPT-5.3 Codex model to the model catalog (OpenAI Codex provider only)
- Added SSH URL support for git packages ([#1287](https://github.com/badlogic/pi-mono/pull/1287) by [@markusn](https://github.com/markusn))
- Model selectors now display the selected model name ([#1275](https://github.com/badlogic/pi-mono/pull/1275) by [@haoqixu](https://github.com/haoqixu))

### Fixed

- Fixed HTML export losing indentation in ANSI-rendered tool output (e.g. JSON code blocks in custom tool results) ([#1269](https://github.com/badlogic/pi-mono/pull/1269) by [@aliou](https://github.com/aliou))
- Fixed images being silently dropped when `prompt()` is called with both `images` and `streamingBehavior` during streaming. `steer()`, `followUp()`, and the corresponding RPC commands now accept optional images. ([#1271](https://github.com/badlogic/pi-mono/pull/1271) by [@aliou](https://github.com/aliou))
- CLI `--help`, `--version`, `--list-models`, and `--export` now exit even if extensions keep the event loop alive ([#1285](https://github.com/badlogic/pi-mono/pull/1285) by [@ferologics](https://github.com/ferologics))
- Fixed crash when models send malformed tool arguments (objects instead of strings) ([#1259](https://github.com/badlogic/pi-mono/issues/1259))
- Fixed custom message expand state not being respected ([#1258](https://github.com/badlogic/pi-mono/pull/1258) by [@Gurpartap](https://github.com/Gurpartap))
- Fixed skill loader to respect .gitignore, .ignore, and .fdignore when scanning directories

## [0.51.6] - 2026-02-04

### New Features

- Configurable resume keybinding action for opening the session resume selector. See [docs/keybindings.md](docs/keybindings.md). ([#1249](https://github.com/badlogic/pi-mono/pull/1249) by [@juanibiapina](https://github.com/juanibiapina))

### Added

- Added `resume` as a configurable keybinding action, allowing users to bind a key to open the session resume selector (like `newSession`, `tree`, and `fork`) ([#1249](https://github.com/badlogic/pi-mono/pull/1249) by [@juanibiapina](https://github.com/juanibiapina))

### Changed

- Slash command menu now triggers on the first line even when other lines have content, allowing commands to be prepended to existing text ([#1227](https://github.com/badlogic/pi-mono/pull/1227) by [@aliou](https://github.com/aliou))

### Fixed

- Ignored unknown skill frontmatter fields when loading skills
- Fixed `/reload` not picking up changes in global settings.json ([#1241](https://github.com/badlogic/pi-mono/issues/1241))
- Fixed forked sessions to persist the user message after forking
- Fixed forked sessions to write to new session files instead of the parent ([#1242](https://github.com/badlogic/pi-mono/issues/1242))
- Fixed local package removal to normalize paths before comparison ([#1243](https://github.com/badlogic/pi-mono/issues/1243))
- Fixed OpenAI Codex Responses provider to respect configured baseUrl ([#1244](https://github.com/badlogic/pi-mono/issues/1244))
- Fixed `/settings` crashing in narrow terminals by handling small widths in the settings list ([#1246](https://github.com/badlogic/pi-mono/pull/1246) by [@haoqixu](https://github.com/haoqixu))
- Fixed Unix bash detection to fall back to PATH lookup when `/bin/bash` is unavailable, including Termux setups ([#1230](https://github.com/badlogic/pi-mono/pull/1230) by [@VaclavSynacek](https://github.com/VaclavSynacek))

## [0.51.5] - 2026-02-04

### Changed

- Changed Bedrock model generation to drop legacy workarounds now handled upstream ([#1239](https://github.com/badlogic/pi-mono/pull/1239) by [@unexge](https://github.com/unexge))

### Fixed

- Fixed Windows package installs regression by using shell execution instead of `.cmd` resolution ([#1220](https://github.com/badlogic/pi-mono/issues/1220))

## [0.51.4] - 2026-02-03

### New Features

- Share URLs now default to pi.dev, graciously donated by exe.dev.

### Changed

- Share URLs now use pi.dev by default while pi.dev and buildwithpi.ai continue to work.

### Fixed

- Fixed input scrolling to avoid splitting emoji sequences ([#1228](https://github.com/badlogic/pi-mono/pull/1228) by [@haoqixu](https://github.com/haoqixu))

## [0.51.3] - 2026-02-03

### New Features

- Command discovery for extensions via `ExtensionAPI.getCommands()`, with `commands.ts` example for invocation patterns. See [docs/extensions.md#pigetcommands](docs/extensions.md#pigetcommands) and [examples/extensions/commands.ts](examples/extensions/commands.ts).
- Local path support for `pi install` and `pi remove`, with relative path resolution against the settings file. See [docs/packages.md#local-paths](docs/packages.md#local-paths).

### Breaking Changes

- RPC `get_commands` response and `SlashCommandSource` type: renamed `"template"` to `"prompt"` for consistency with the rest of the codebase

### Added

- Added `ExtensionAPI.getCommands()` to let extensions list available slash commands (extensions, prompt templates, skills) for invocation via `prompt` ([#1210](https://github.com/badlogic/pi-mono/pull/1210) by [@w-winter](https://github.com/w-winter))
- Added `commands.ts` example extension and exported `SlashCommandInfo` types for command discovery integrations ([#1210](https://github.com/badlogic/pi-mono/pull/1210) by [@w-winter](https://github.com/w-winter))
- Added local path support for `pi install` and `pi remove` with relative paths stored against the target settings file ([#1216](https://github.com/badlogic/pi-mono/issues/1216))

### Fixed

- Fixed default thinking level persistence so settings-derived defaults are saved and restored correctly
- Fixed Windows package installs by resolving `npm.cmd` when `npm` is not directly executable ([#1220](https://github.com/badlogic/pi-mono/issues/1220))
- Fixed xhigh thinking level support check to accept gpt-5.2 model IDs ([#1209](https://github.com/badlogic/pi-mono/issues/1209))

## [0.51.2] - 2026-02-03

### New Features

- Extension tool output expansion controls via ExtensionUIContext getToolsExpanded and setToolsExpanded. See [docs/extensions.md](docs/extensions.md) and [docs/rpc.md](docs/rpc.md).

### Added

- Added ExtensionUIContext getToolsExpanded and setToolsExpanded for controlling tool output expansion ([#1199](https://github.com/badlogic/pi-mono/pull/1199) by [@academo](https://github.com/academo))
- Added install method detection to show package manager specific update instructions ([#1203](https://github.com/badlogic/pi-mono/pull/1203) by [@Itsnotaka](https://github.com/Itsnotaka))

### Fixed

- Fixed Kitty key release events leaking to parent shell over slow SSH connections by draining stdin for up to 1s on exit ([#1204](https://github.com/badlogic/pi-mono/issues/1204))
- Fixed legacy newline handling in the editor to preserve previous newline behavior
- Fixed @ autocomplete to include hidden paths
- Fixed submit fallback to honor configured keybindings
- Fixed extension commands conflicting with built-in commands by skipping them ([#1196](https://github.com/badlogic/pi-mono/pull/1196) by [@haoqixu](https://github.com/haoqixu))
- Fixed @-prefixed tool paths failing to resolve by stripping the prefix ([#1206](https://github.com/badlogic/pi-mono/issues/1206))
- Fixed install method detection to avoid stale cached results

## [0.51.1] - 2026-02-02

### New Features

- **Extension API switchSession**: Extensions can now programmatically switch sessions via `ctx.switchSession(sessionPath)`. See [docs/extensions.md](docs/extensions.md). ([#1187](https://github.com/badlogic/pi-mono/issues/1187))
- **Clear on shrink setting**: New `terminal.clearOnShrink` setting keeps the editor and footer pinned to the bottom of the terminal when content shrinks. May cause some flicker due to redraws. Disabled by default. Enable via `/settings` or `PI_CLEAR_ON_SHRINK=1` env var.

### Fixed

- Fixed scoped models not finding valid credentials after logout ([#1194](https://github.com/badlogic/pi-mono/pull/1194) by [@terrorobe](https://github.com/terrorobe))
- Fixed Ctrl+D exit closing the parent SSH session due to stdin buffer race condition ([#1185](https://github.com/badlogic/pi-mono/issues/1185))
- Fixed emoji cursor positioning in editor input ([#1183](https://github.com/badlogic/pi-mono/pull/1183) by [@haoqixu](https://github.com/haoqixu))

## [0.51.0] - 2026-02-01

### Breaking Changes

- **Extension tool signature change**: `ToolDefinition.execute` now uses `(toolCallId, params, signal, onUpdate, ctx)` parameter order to match `AgentTool.execute`. Previously it was `(toolCallId, params, onUpdate, ctx, signal)`. This makes wrapping built-in tools trivial since the first four parameters now align. Update your extensions by swapping the `signal` and `onUpdate` parameters:
  ```ts
  // Before
  async execute(toolCallId, params, onUpdate, ctx, signal) { ... }

  // After
  async execute(toolCallId, params, signal, onUpdate, ctx) { ... }
  ```

### New Features

- **Android/Termux support**: Pi now runs on Android via Termux. Install with:
  ```bash
  pkg install nodejs termux-api git
  npm install -g @mariozechner/pi-coding-agent
  mkdir -p ~/.pi/agent
  echo "You are running on Android in Termux." > ~/.pi/agent/AGENTS.md
  ```
  Clipboard operations fall back gracefully when `termux-api` is unavailable. ([#1164](https://github.com/badlogic/pi-mono/issues/1164))
- **Bash spawn hook**: Extensions can now intercept and modify bash commands before execution via `pi.setBashSpawnHook()`. Adjust the command string, working directory, or environment variables. See [docs/extensions.md](docs/extensions.md). ([#1160](https://github.com/badlogic/pi-mono/pull/1160) by [@mitsuhiko](https://github.com/mitsuhiko))
- **Linux ARM64 musl support**: Pi now runs on Alpine Linux ARM64 (linux-arm64-musl) via updated clipboard dependency.
- **Nix/Guix support**: `PI_PACKAGE_DIR` environment variable overrides the package path for content-addressed package managers where store paths tokenize poorly. See [README.md#environment-variables](README.md#environment-variables). ([#1153](https://github.com/badlogic/pi-mono/pull/1153) by [@odysseus0](https://github.com/odysseus0))
- **Named session filter**: `/resume` picker now supports filtering to show only named sessions via Ctrl+N. Configurable via `toggleSessionNamedFilter` keybinding. See [docs/keybindings.md](docs/keybindings.md). ([#1128](https://github.com/badlogic/pi-mono/pull/1128) by [@w-winter](https://github.com/w-winter))
- **Typed tool call events**: Extension developers can narrow `ToolCallEvent` types using `isToolCallEventType()` for better TypeScript support. See [docs/extensions.md#tool-call-events](docs/extensions.md#tool-call-events). ([#1147](https://github.com/badlogic/pi-mono/pull/1147) by [@giuseppeg](https://github.com/giuseppeg))
- **Extension UI Protocol**: Full RPC documentation and examples for extension dialogs and notifications, enabling headless clients to support interactive extensions. See [docs/rpc.md#extension-ui-protocol](docs/rpc.md#extension-ui-protocol). ([#1144](https://github.com/badlogic/pi-mono/pull/1144) by [@aliou](https://github.com/aliou))

### Added

- Added Linux ARM64 musl (Alpine Linux) support via clipboard dependency update
- Added Android/Termux support with graceful clipboard fallback ([#1164](https://github.com/badlogic/pi-mono/issues/1164))
- Added bash tool spawn hook support for adjusting command, cwd, and env before execution ([#1160](https://github.com/badlogic/pi-mono/pull/1160) by [@mitsuhiko](https://github.com/mitsuhiko))
- Added typed `ToolCallEvent.input` per tool with `isToolCallEventType()` type guard for narrowing built-in tool events ([#1147](https://github.com/badlogic/pi-mono/pull/1147) by [@giuseppeg](https://github.com/giuseppeg))
- Exported `discoverAndLoadExtensions` from package to enable extension testing without a local repo clone ([#1148](https://github.com/badlogic/pi-mono/issues/1148))
- Added Extension UI Protocol documentation to RPC docs covering all request/response types for extension dialogs and notifications ([#1144](https://github.com/badlogic/pi-mono/pull/1144) by [@aliou](https://github.com/aliou))
- Added `rpc-demo.ts` example extension exercising all RPC-supported extension UI methods ([#1144](https://github.com/badlogic/pi-mono/pull/1144) by [@aliou](https://github.com/aliou))
- Added `rpc-extension-ui.ts` TUI example client demonstrating the extension UI protocol with interactive dialogs ([#1144](https://github.com/badlogic/pi-mono/pull/1144) by [@aliou](https://github.com/aliou))
- Added `PI_PACKAGE_DIR` environment variable to override package path for content-addressed package managers (Nix, Guix) where store paths tokenize poorly ([#1153](https://github.com/badlogic/pi-mono/pull/1153) by [@odysseus0](https://github.com/odysseus0))
- `/resume` session picker now supports named-only filter toggle (default Ctrl+N, configurable via `toggleSessionNamedFilter`) to show only named sessions ([#1128](https://github.com/badlogic/pi-mono/pull/1128) by [@w-winter](https://github.com/w-winter))

### Fixed

- Fixed `pi update` not updating npm/git packages when called without arguments ([#1151](https://github.com/badlogic/pi-mono/issues/1151))
- Fixed `models.json` validation requiring fields documented as optional. Model definitions now only require `id`; all other fields (`name`, `reasoning`, `input`, `cost`, `contextWindow`, `maxTokens`) have sensible defaults. ([#1146](https://github.com/badlogic/pi-mono/issues/1146))
- Fixed models resolving relative paths in skill files from cwd instead of skill directory by adding explicit guidance to skills preamble ([#1136](https://github.com/badlogic/pi-mono/issues/1136))
- Fixed tree selector losing focus state when navigating entries ([#1142](https://github.com/badlogic/pi-mono/pull/1142) by [@Perlence](https://github.com/Perlence))
- Fixed `cacheRetention` option not being passed through in `buildBaseOptions` ([#1154](https://github.com/badlogic/pi-mono/issues/1154))
- Fixed OAuth login/refresh not using HTTP proxy settings (`HTTP_PROXY`, `HTTPS_PROXY` env vars) ([#1132](https://github.com/badlogic/pi-mono/issues/1132))
- Fixed `pi update <source>` installing packages locally when the source is only registered globally ([#1163](https://github.com/badlogic/pi-mono/pull/1163) by [@aliou](https://github.com/aliou))
- Fixed tree navigation with summarization overwriting editor content typed during the summarization wait ([#1169](https://github.com/badlogic/pi-mono/pull/1169) by [@aliou](https://github.com/aliou))

## [0.50.9] - 2026-02-01

### Added

- Added `titlebar-spinner.ts` example extension that shows a braille spinner animation in the terminal title while the agent is working.
- Added `PI_AI_ANTIGRAVITY_VERSION` environment variable documentation to help text ([#1129](https://github.com/badlogic/pi-mono/issues/1129))
- Added `cacheRetention` stream option with provider-specific mappings for prompt cache controls, defaulting to short retention ([#1134](https://github.com/badlogic/pi-mono/issues/1134))

## [0.50.8] - 2026-02-01

### Added

- Added `newSession`, `tree`, and `fork` keybinding actions for `/new`, `/tree`, and `/fork` commands. All unbound by default. ([#1114](https://github.com/badlogic/pi-mono/pull/1114) by [@juanibiapina](https://github.com/juanibiapina))
- Added `retry.maxDelayMs` setting to cap maximum server-requested retry delay. When a provider requests a longer delay (e.g., Google's "quota will reset after 5h"), the request fails immediately with an informative error instead of waiting silently. Default: 60000ms (60 seconds). ([#1123](https://github.com/badlogic/pi-mono/issues/1123))
- `/resume` session picker: new "Threaded" sort mode (now default) displays sessions in a tree structure based on fork relationships. Compact one-line format with message count and age on the right. ([#1124](https://github.com/badlogic/pi-mono/pull/1124) by [@pasky](https://github.com/pasky))
- Added Qwen CLI OAuth provider extension example. ([#940](https://github.com/badlogic/pi-mono/pull/940) by [@4h9fbZ](https://github.com/4h9fbZ))
- Added OAuth `modifyModels` hook support for extension-registered providers at registration time. ([#940](https://github.com/badlogic/pi-mono/pull/940) by [@4h9fbZ](https://github.com/4h9fbZ))
- Added Qwen thinking format support for OpenAI-compatible completions via `enable_thinking`. ([#940](https://github.com/badlogic/pi-mono/pull/940) by [@4h9fbZ](https://github.com/4h9fbZ))
- Added sticky column tracking for vertical cursor navigation so the editor restores the preferred column when moving across short lines. ([#1120](https://github.com/badlogic/pi-mono/pull/1120) by [@Perlence](https://github.com/Perlence))
- Added `resources_discover` extension hook to supply additional skills, prompts, and themes on startup and reload.

### Fixed

- Fixed `switchSession()` appending spurious `thinking_level_change` entry to session log on resume. `setThinkingLevel()` is now idempotent. ([#1118](https://github.com/badlogic/pi-mono/issues/1118))
- Fixed clipboard image paste on WSL2/WSLg writing invalid PNG files when clipboard provides `image/bmp` format. BMP images are now converted to PNG before saving. ([#1112](https://github.com/badlogic/pi-mono/pull/1112) by [@lightningRalf](https://github.com/lightningRalf))
- Fixed Kitty keyboard protocol base layout fallback so non-QWERTY layouts do not trigger wrong shortcuts ([#1096](https://github.com/badlogic/pi-mono/pull/1096) by [@rytswd](https://github.com/rytswd))

## [0.50.7] - 2026-01-31

### Fixed

- Multi-file extensions in packages now work correctly. Package resolution now uses the same discovery logic as local extensions: only `index.ts` (or manifest-declared entries) are loaded from subdirectories, not helper modules. ([#1102](https://github.com/badlogic/pi-mono/issues/1102))

## [0.50.6] - 2026-01-30

### Added

- Added `ctx.getSystemPrompt()` to extension context for accessing the current effective system prompt ([#1098](https://github.com/badlogic/pi-mono/pull/1098) by [@kaofelix](https://github.com/kaofelix))

### Fixed

- Fixed empty rows appearing below footer when content shrinks (e.g., closing `/tree`, clearing multi-line editor) ([#1095](https://github.com/badlogic/pi-mono/pull/1095) by [@marckrenn](https://github.com/marckrenn))
- Fixed terminal cursor remaining hidden after exiting TUI via `stop()` when a render was pending ([#1099](https://github.com/badlogic/pi-mono/pull/1099) by [@haoqixu](https://github.com/haoqixu))

## [0.50.5] - 2026-01-30

## [0.50.4] - 2026-01-30

### New Features

- **OSC 52 clipboard support for SSH/mosh** - The `/copy` command now works over remote connections using the OSC 52 terminal escape sequence. No more clipboard frustration when using pi over SSH. ([#1069](https://github.com/badlogic/pi-mono/issues/1069) by [@gturkoglu](https://github.com/gturkoglu))
- **Vercel AI Gateway routing** - Route requests through Vercel's AI Gateway with provider failover and load balancing. Configure via `vercelGatewayRouting` in models.json. ([#1051](https://github.com/badlogic/pi-mono/pull/1051) by [@ben-vargas](https://github.com/ben-vargas))
- **Character jump navigation** - Bash/Readline-style character search: Ctrl+] jumps forward to the next occurrence of a character, Ctrl+Alt+] jumps backward. ([#1074](https://github.com/badlogic/pi-mono/pull/1074) by [@Perlence](https://github.com/Perlence))
- **Emacs-style Ctrl+B/Ctrl+F navigation** - Alternative keybindings for word navigation (cursor word left/right) in the editor. ([#1053](https://github.com/badlogic/pi-mono/pull/1053) by [@ninlds](https://github.com/ninlds))
- **Line boundary navigation** - Editor jumps to line start when pressing Up at first visual line, and line end when pressing Down at last visual line. ([#1050](https://github.com/badlogic/pi-mono/pull/1050) by [@4h9fbZ](https://github.com/4h9fbZ))
- **Performance improvements** - Optimized image line detection and box rendering cache in the TUI for better rendering performance. ([#1084](https://github.com/badlogic/pi-mono/pull/1084) by [@can1357](https://github.com/can1357))
- **`set_session_name` RPC command** - Headless clients can now set the session display name programmatically. ([#1075](https://github.com/badlogic/pi-mono/pull/1075) by [@dnouri](https://github.com/dnouri))
- **Disable double-escape behavior** - New `"none"` option for `doubleEscapeAction` setting completely disables the double-escape shortcut. ([#973](https://github.com/badlogic/pi-mono/issues/973) by [@juanibiapina](https://github.com/juanibiapina))

### Added

- Added "none" option to `doubleEscapeAction` setting to disable double-escape behavior entirely ([#973](https://github.com/badlogic/pi-mono/issues/973) by [@juanibiapina](https://github.com/juanibiapina))
- Added OSC 52 clipboard support for SSH/mosh sessions. `/copy` now works over remote connections. ([#1069](https://github.com/badlogic/pi-mono/issues/1069) by [@gturkoglu](https://github.com/gturkoglu))
- Added Vercel AI Gateway routing support via `vercelGatewayRouting` in models.json ([#1051](https://github.com/badlogic/pi-mono/pull/1051) by [@ben-vargas](https://github.com/ben-vargas))
- Added Ctrl+B and Ctrl+F keybindings for cursor word left/right navigation in the editor ([#1053](https://github.com/badlogic/pi-mono/pull/1053) by [@ninlds](https://github.com/ninlds))
- Added character jump navigation: Ctrl+] jumps forward to next character, Ctrl+Alt+] jumps backward ([#1074](https://github.com/badlogic/pi-mono/pull/1074) by [@Perlence](https://github.com/Perlence))
- Editor now jumps to line start when pressing Up at first visual line, and line end when pressing Down at last visual line ([#1050](https://github.com/badlogic/pi-mono/pull/1050) by [@4h9fbZ](https://github.com/4h9fbZ))
- Optimized image line detection and box rendering cache for better TUI performance ([#1084](https://github.com/badlogic/pi-mono/pull/1084) by [@can1357](https://github.com/can1357))
- Added `set_session_name` RPC command for headless clients to set session display name ([#1075](https://github.com/badlogic/pi-mono/pull/1075) by [@dnouri](https://github.com/dnouri))

### Fixed

- Read tool now handles macOS filenames with curly quotes (U+2019) and NFD Unicode normalization ([#1078](https://github.com/badlogic/pi-mono/issues/1078))
- Respect .gitignore, .ignore, and .fdignore files when scanning package resources for skills, prompts, themes, and extensions ([#1072](https://github.com/badlogic/pi-mono/issues/1072))
- Fixed tool call argument defaults when providers omit inputs ([#1065](https://github.com/badlogic/pi-mono/issues/1065))
- Invalid JSON in settings.json no longer causes the file to be overwritten with empty settings ([#1054](https://github.com/badlogic/pi-mono/issues/1054))
- Config selector now shows folder name for extensions with duplicate display names ([#1064](https://github.com/badlogic/pi-mono/pull/1064) by [@Graffioh](https://github.com/Graffioh))

## [0.50.3] - 2026-01-29

### New Features

- **Kimi For Coding provider**: Access Moonshot AI's Anthropic-compatible coding API. Set `KIMI_API_KEY` environment variable. See [README.md#kimi-for-coding](README.md#kimi-for-coding).

### Added

- Added Kimi For Coding provider support (Moonshot AI's Anthropic-compatible coding API). Set `KIMI_API_KEY` environment variable. See [README.md#kimi-for-coding](README.md#kimi-for-coding).

### Fixed

- Resources now appear before messages when resuming a session, preventing loaded context from appearing at the bottom of the chat.

## [0.50.2] - 2026-01-29

### New Features

- **Hugging Face provider**: Access Hugging Face models via OpenAI-compatible Inference Router. Set `HF_TOKEN` environment variable. See [README.md#hugging-face](README.md#hugging-face).
- **Extended prompt caching**: `PI_CACHE_RETENTION=long` enables 1-hour caching for Anthropic (vs 5min default) and 24-hour for OpenAI (vs in-memory default). Only applies to direct API calls. See [README.md#prompt-caching](README.md#prompt-caching).
- **Configurable autocomplete height**: `autocompleteMaxVisible` setting (3-20 items, default 5) controls dropdown size. Adjust via `/settings` or `settings.json`.
- **Shell-style keybindings**: `alt+b`/`alt+f` for word navigation, `ctrl+d` for delete character forward. See [docs/keybindings.md](docs/keybindings.md).
- **RPC `get_commands`**: Headless clients can now list available commands programmatically. See [docs/rpc.md](docs/rpc.md).

### Added

- Added Hugging Face provider support via OpenAI-compatible Inference Router ([#994](https://github.com/badlogic/pi-mono/issues/994))
- Added `PI_CACHE_RETENTION` environment variable to control cache TTL for Anthropic (5m vs 1h) and OpenAI (in-memory vs 24h). Set to `long` for extended retention. ([#967](https://github.com/badlogic/pi-mono/issues/967))
- Added `autocompleteMaxVisible` setting for configurable autocomplete dropdown height (3-20 items, default 5) ([#972](https://github.com/badlogic/pi-mono/pull/972) by [@masonc15](https://github.com/masonc15))
- Added `/files` command to list all file operations (read, write, edit) in the current session
- Added shell-style keybindings: `alt+b`/`alt+f` for word navigation, `ctrl+d` for delete character forward (when editor has text) ([#1043](https://github.com/badlogic/pi-mono/issues/1043) by [@jasonish](https://github.com/jasonish))
- Added `get_commands` RPC method for headless clients to list available commands ([#995](https://github.com/badlogic/pi-mono/pull/995) by [@dnouri](https://github.com/dnouri))

### Changed

- Improved `extractCursorPosition` performance in TUI: scans lines in reverse order, early-outs when cursor is above viewport ([#1004](https://github.com/badlogic/pi-mono/pull/1004) by [@can1357](https://github.com/can1357))
- Autocomplete improvements: better handling of partial matches and edge cases ([#1024](https://github.com/badlogic/pi-mono/pull/1024) by [@Perlence](https://github.com/Perlence))

### Fixed

- External edits to `settings.json` are now preserved when pi reloads or saves unrelated settings. Previously, editing settings.json directly (e.g., removing a package from `packages` array) would be silently reverted on next pi startup when automatic setters like `setLastChangelogVersion()` triggered a save.
- Fixed custom header not displaying correctly with `quietStartup` enabled ([#1039](https://github.com/badlogic/pi-mono/pull/1039) by [@tudoroancea](https://github.com/tudoroancea))
- Empty array in package filter now disables all resources instead of falling back to manifest defaults ([#1044](https://github.com/badlogic/pi-mono/issues/1044))
- Auto-retry counter now resets after each successful LLM response instead of accumulating across tool-use turns ([#1019](https://github.com/badlogic/pi-mono/issues/1019))
- Fixed incorrect `.md` file names in warning messages ([#1041](https://github.com/badlogic/pi-mono/issues/1041) by [@llimllib](https://github.com/llimllib))
- Fixed provider name hidden in footer when terminal is narrow ([#981](https://github.com/badlogic/pi-mono/pull/981) by [@Perlence](https://github.com/Perlence))
- Fixed backslash input buffering causing delayed character display in editor ([#1037](https://github.com/badlogic/pi-mono/pull/1037) by [@Perlence](https://github.com/Perlence))
- Fixed markdown table rendering with proper row dividers and minimum column width ([#997](https://github.com/badlogic/pi-mono/pull/997) by [@tmustier](https://github.com/tmustier))
- Fixed OpenAI completions `toolChoice` handling ([#998](https://github.com/badlogic/pi-mono/pull/998) by [@williamtwomey](https://github.com/williamtwomey))
- Fixed cross-provider handoff failing when switching from OpenAI Responses API providers due to pipe-separated tool call IDs ([#1022](https://github.com/badlogic/pi-mono/issues/1022))
- Fixed 429 rate limit errors incorrectly triggering auto-compaction instead of retry with backoff ([#1038](https://github.com/badlogic/pi-mono/issues/1038))
- Fixed Anthropic provider to handle `sensitive` stop_reason returned by API ([#978](https://github.com/badlogic/pi-mono/issues/978))
- Fixed DeepSeek API compatibility by detecting `deepseek.com` URLs and disabling unsupported `developer` role ([#1048](https://github.com/badlogic/pi-mono/issues/1048))
- Fixed Anthropic provider to preserve input token counts when proxies omit them in `message_delta` events ([#1045](https://github.com/badlogic/pi-mono/issues/1045))
- Fixed `autocompleteMaxVisible` setting not persisting to `settings.json`

## [0.50.1] - 2026-01-26

### Fixed

- Git extension updates now handle force-pushed remotes gracefully instead of failing ([#961](https://github.com/badlogic/pi-mono/pull/961) by [@aliou](https://github.com/aliou))
- Extension `ctx.newSession({ setup })` now properly syncs agent state and renders messages after setup callback runs ([#968](https://github.com/badlogic/pi-mono/issues/968))
- Fixed extension UI bindings not initializing when starting with no extensions, which broke UI methods after `/reload`
- Fixed `/hotkeys` output to title-case extension hotkeys ([#969](https://github.com/badlogic/pi-mono/pull/969) by [@Perlence](https://github.com/Perlence))
- Fixed model catalog generation to exclude deprecated OpenCode Zen models ([#970](https://github.com/badlogic/pi-mono/pull/970) by [@DanielTatarkin](https://github.com/DanielTatarkin))
- Fixed git extension removal to prune empty directories

## [0.50.0] - 2026-01-26

### New Features

- Pi packages for bundling and installing extensions, skills, prompts, and themes. See [docs/packages.md](docs/packages.md).
- Hot reload (`/reload`) of resources including AGENTS.md, SYSTEM.md, APPEND_SYSTEM.md, prompt templates, skills, themes, and extensions. See [README.md#commands](README.md#commands) and [README.md#context-files](README.md#context-files).
- Custom providers via `pi.registerProvider()` for proxies, custom endpoints, OAuth or SSO flows, and non-standard streaming APIs. See [docs/custom-provider.md](docs/custom-provider.md).
- Azure OpenAI Responses provider support with deployment-aware model mapping. See [docs/providers.md#azure-openai](docs/providers.md#azure-openai).
- OpenRouter routing support for custom models via `openRouterRouting`. See [docs/providers.md#api-keys](docs/providers.md#api-keys) and [docs/models.md](docs/models.md).
- Skill invocation messages are now collapsible and skills can opt out of model invocation via `disable-model-invocation`. See [docs/skills.md#frontmatter](docs/skills.md#frontmatter).
- Session selector renaming and configurable keybindings. See [README.md#commands](README.md#commands) and [docs/keybindings.md](docs/keybindings.md).
- `models.json` headers can resolve environment variables and shell commands. See [docs/models.md#value-resolution](docs/models.md#value-resolution).
- `--verbose` CLI flag to override quiet startup. See [README.md#cli-reference](README.md#cli-reference).

Read the fully revamped docs in `README.md`, or have your clanker read them for you.

### SDK Migration Guide

There are multiple SDK breaking changes since v0.49.3. For the quickest migration, point your agent at `packages/coding-agent/docs/sdk.md`, the SDK examples in `packages/coding-agent/examples/sdk`, and the SDK source in `packages/coding-agent/src/core/sdk.ts` and related modules.

### Breaking Changes

- Header values in `models.json` now resolve environment variables (if a header value matches an env var name, the env var value is used). This may change behavior if a literal header value accidentally matches an env var name. ([#909](https://github.com/badlogic/pi-mono/issues/909))
- External packages (npm/git) are now configured via `packages` array in settings.json instead of `extensions`. Existing npm:/git: entries in `extensions` are auto-migrated. ([#645](https://github.com/badlogic/pi-mono/issues/645))
- Resource loading now uses `ResourceLoader` only and settings.json uses arrays for extensions, skills, prompts, and themes ([#645](https://github.com/badlogic/pi-mono/issues/645))
- Removed `discoverAuthStorage` and `discoverModels` from the SDK. `AuthStorage` and `ModelRegistry` now default to `~/.pi/agent` paths unless you pass an `agentDir` ([#645](https://github.com/badlogic/pi-mono/issues/645))

### Added

- Session renaming in `/resume` picker via `Ctrl+R` without opening the session ([#863](https://github.com/badlogic/pi-mono/pull/863) by [@svkozak](https://github.com/svkozak))
- Session selector keybindings are now configurable ([#948](https://github.com/badlogic/pi-mono/pull/948) by [@aos](https://github.com/aos))
- `disable-model-invocation` frontmatter field for skills to prevent agentic invocation while still allowing explicit `/skill:name` commands ([#927](https://github.com/badlogic/pi-mono/issues/927))
- Exposed `copyToClipboard` utility for extensions ([#926](https://github.com/badlogic/pi-mono/issues/926) by [@mitsuhiko](https://github.com/mitsuhiko))
- Skill invocation messages are now collapsible in chat output, showing collapsed by default with skill name and expand hint ([#894](https://github.com/badlogic/pi-mono/issues/894))
- Header values in `models.json` now support environment variables and shell commands, matching `apiKey` resolution ([#909](https://github.com/badlogic/pi-mono/issues/909))
- Added HTTP proxy environment variable support for API requests ([#942](https://github.com/badlogic/pi-mono/pull/942) by [@haoqixu](https://github.com/haoqixu))
- Added OpenRouter provider routing support for custom models via `openRouterRouting` compat field ([#859](https://github.com/badlogic/pi-mono/pull/859) by [@v01dpr1mr0s3](https://github.com/v01dpr1mr0s3))
- Added `azure-openai-responses` provider support for Azure OpenAI Responses API. ([#890](https://github.com/badlogic/pi-mono/pull/890) by [@markusylisiurunen](https://github.com/markusylisiurunen))
- Added changelog link to update notifications ([#925](https://github.com/badlogic/pi-mono/pull/925) by [@dannote](https://github.com/dannote))
- Added `--verbose` CLI flag to override quietStartup setting ([#906](https://github.com/badlogic/pi-mono/pull/906) by [@Perlence](https://github.com/Perlence))
- `markdown.codeBlockIndent` setting to customize code block indentation in rendered output
- Extension package management with `pi install`, `pi remove`, `pi update`, and `pi list` commands ([#645](https://github.com/badlogic/pi-mono/issues/645))
- Package filtering: selectively load resources from packages using object form in `packages` array ([#645](https://github.com/badlogic/pi-mono/issues/645))
- Glob pattern support with minimatch in package filters, top-level settings arrays, and pi manifest (e.g., `"!funky.json"`, `"*.ts"`) ([#645](https://github.com/badlogic/pi-mono/issues/645))
- `/reload` command to reload extensions, skills, prompts, and themes ([#645](https://github.com/badlogic/pi-mono/issues/645))
- `pi config` command with TUI to enable/disable package and top-level resources via patterns ([#938](https://github.com/badlogic/pi-mono/issues/938))
- CLI flags for `--skill`, `--prompt-template`, `--theme`, `--no-prompt-templates`, and `--no-themes` ([#645](https://github.com/badlogic/pi-mono/issues/645))
- Package deduplication: if same package appears in global and project settings, project wins ([#645](https://github.com/badlogic/pi-mono/issues/645))
- Unified collision reporting with `ResourceDiagnostic` type for all resource types ([#645](https://github.com/badlogic/pi-mono/issues/645))
- Show provider alongside the model in the footer if multiple providers are available
- Custom provider support via `pi.registerProvider()` with `streamSimple` for custom API implementations
- Added `custom-provider.ts` example extension demonstrating custom Anthropic provider with OAuth

### Changed

- `/resume` picker sort toggle moved to `Ctrl+S` to free `Ctrl+R` for rename ([#863](https://github.com/badlogic/pi-mono/pull/863) by [@svkozak](https://github.com/svkozak))
- HTML export: clicking a sidebar message now navigates to its newest leaf and scrolls to it, instead of truncating the branch ([#853](https://github.com/badlogic/pi-mono/pull/853) by [@mitsuhiko](https://github.com/mitsuhiko))
- HTML export: active path is now visually highlighted with dimmed off-path nodes ([#929](https://github.com/badlogic/pi-mono/pull/929) by [@hewliyang](https://github.com/hewliyang))
- Azure OpenAI Responses provider now uses base URL configuration with deployment-aware model mapping and no longer includes service tier handling
- `/reload` now re-renders the entire scrollback so updated extension components are visible immediately ([#928](https://github.com/badlogic/pi-mono/pull/928) by [@ferologics](https://github.com/ferologics))
- Skill, prompt template, and theme discovery now use settings and CLI path arrays instead of legacy filters ([#645](https://github.com/badlogic/pi-mono/issues/645))

### Fixed

- Extension `setWorkingMessage()` calls in `agent_start` handlers now work correctly; previously the message was silently ignored because the loading animation didn't exist yet ([#935](https://github.com/badlogic/pi-mono/issues/935))
- Fixed package auto-discovery to respect loader rules, config overrides, and force-exclude patterns
- Fixed /reload restoring the correct editor after reload ([#949](https://github.com/badlogic/pi-mono/pull/949) by [@Perlence](https://github.com/Perlence))
- Fixed distributed themes breaking `/export` ([#946](https://github.com/badlogic/pi-mono/pull/946) by [@mitsuhiko](https://github.com/mitsuhiko))
- Fixed startup hints to clarify thinking level selection and expanded thinking guidance
- Fixed SDK initial model resolution to use `findInitialModel` and default to Claude Opus 4.5 for Anthropic models
- Fixed no-models warning to include the `/model` instruction
- Fixed authentication error messages to point to the authentication documentation
- Fixed bash output hint lines to truncate to terminal width
- Fixed custom editors to honor the `paddingX` setting ([#936](https://github.com/badlogic/pi-mono/pull/936) by [@Perlence](https://github.com/Perlence))
- Fixed system prompt tool list to show only built-in tools
- Fixed package manager to check npm package versions before using cached copies
- Fixed package manager to run `npm install` after cloning git repositories with a package.json
- Fixed extension provider registrations to apply before model resolution
- Fixed editor multi-line insertion handling and lastAction tracking ([#945](https://github.com/badlogic/pi-mono/pull/945) by [@Perlence](https://github.com/Perlence))
- Fixed editor word wrapping to reserve a cursor column ([#934](https://github.com/badlogic/pi-mono/pull/934) by [@Perlence](https://github.com/Perlence))
- Fixed editor word wrapping to use single-pass backtracking for whitespace handling ([#924](https://github.com/badlogic/pi-mono/pull/924) by [@Perlence](https://github.com/Perlence))
- Fixed Kitty image ID allocation and cleanup to prevent image ID collisions
- Fixed overlays staying centered after terminal resizes ([#950](https://github.com/badlogic/pi-mono/pull/950) by [@nicobailon](https://github.com/nicobailon))
- Fixed streaming dispatch to use the model api type instead of hardcoded API defaults
- Fixed Google providers to default tool call arguments to an empty object when omitted
- Fixed OpenAI Responses streaming to handle `arguments.done` events on OpenAI-compatible endpoints ([#917](https://github.com/badlogic/pi-mono/pull/917) by [@williballenthin](https://github.com/williballenthin))
- Fixed OpenAI Codex Responses tool strictness handling after the shared responses refactor
- Fixed Azure OpenAI Responses streaming to guard deltas before content parts and correct metadata and handoff gating
- Fixed OpenAI completions tool-result image batching after consecutive tool results ([#902](https://github.com/badlogic/pi-mono/pull/902) by [@terrorobe](https://github.com/terrorobe))
- Off-by-one error in bash output "earlier lines" count caused by counting spacing newline as hidden content ([#921](https://github.com/badlogic/pi-mono/issues/921))
- User package filters now layer on top of manifest filters instead of replacing them ([#645](https://github.com/badlogic/pi-mono/issues/645))
- Auto-retry now handles "terminated" errors from Codex API mid-stream failures
- Follow-up queue (Alt+Enter) now sends full paste content instead of `[paste #N ...]` markers ([#912](https://github.com/badlogic/pi-mono/issues/912))
- Fixed Alt-Up not restoring messages queued during compaction ([#923](https://github.com/badlogic/pi-mono/pull/923) by [@aliou](https://github.com/aliou))
- Fixed session corruption when loading empty or invalid session files via `--session` flag ([#932](https://github.com/badlogic/pi-mono/issues/932) by [@armanddp](https://github.com/armanddp))
- Fixed extension shortcuts not firing when extension also uses `setEditorComponent()` ([#947](https://github.com/badlogic/pi-mono/pull/947) by [@Perlence](https://github.com/Perlence))
- Session "modified" time now uses last message timestamp instead of file mtime, so renaming doesn't reorder the recent list ([#863](https://github.com/badlogic/pi-mono/pull/863) by [@svkozak](https://github.com/svkozak))

## [0.49.3] - 2026-01-22

### Added

- `markdown.codeBlockIndent` setting to customize code block indentation in rendered output ([#855](https://github.com/badlogic/pi-mono/pull/855) by [@terrorobe](https://github.com/terrorobe))
- Added `inline-bash.ts` example extension for expanding `!{command}` patterns in prompts ([#881](https://github.com/badlogic/pi-mono/pull/881) by [@scutifer](https://github.com/scutifer))
- Added `antigravity-image-gen.ts` example extension for AI image generation via Google Antigravity ([#893](https://github.com/badlogic/pi-mono/pull/893) by [@ben-vargas](https://github.com/ben-vargas))
- Added `PI_SHARE_VIEWER_URL` environment variable for custom share viewer URLs ([#889](https://github.com/badlogic/pi-mono/pull/889) by [@andresaraujo](https://github.com/andresaraujo))
- Added Alt+Delete as hotkey for delete word forwards ([#878](https://github.com/badlogic/pi-mono/pull/878) by [@Perlence](https://github.com/Perlence))

### Changed

- Tree selector: changed label filter shortcut from `l` to `Shift+L` so users can search for entries containing "l" ([#861](https://github.com/badlogic/pi-mono/pull/861) by [@mitsuhiko](https://github.com/mitsuhiko))
- Fuzzy matching now scores consecutive matches higher for better search relevance ([#860](https://github.com/badlogic/pi-mono/pull/860) by [@mitsuhiko](https://github.com/mitsuhiko))

### Fixed

- Fixed error messages showing hardcoded `~/.pi/agent/` paths instead of respecting `PI_CODING_AGENT_DIR` ([#887](https://github.com/badlogic/pi-mono/pull/887) by [@aliou](https://github.com/aliou))
- Fixed `write` tool not displaying errors in the UI when execution fails ([#856](https://github.com/badlogic/pi-mono/issues/856))
- Fixed HTML export using default theme instead of user's active theme ([#870](https://github.com/badlogic/pi-mono/pull/870) by [@scutifer](https://github.com/scutifer))
- Show session name in the footer and terminal / tab title ([#876](https://github.com/badlogic/pi-mono/pull/876) by [@scutifer](https://github.com/scutifer))
- Fixed 256color fallback in Terminal.app to prevent color rendering issues ([#869](https://github.com/badlogic/pi-mono/pull/869) by [@Perlence](https://github.com/Perlence))
- Fixed viewport tracking and cursor positioning for overlays and content shrink scenarios
- Fixed autocomplete to allow searches with `/` characters (e.g., `folder1/folder2`) ([#882](https://github.com/badlogic/pi-mono/pull/882) by [@richardgill](https://github.com/richardgill))
- Fixed autolinked emails displaying redundant `(mailto:...)` suffix ([#888](https://github.com/badlogic/pi-mono/pull/888) by [@terrorobe](https://github.com/terrorobe))
- Fixed `@` file autocomplete adding space after directories, breaking continued autocomplete into subdirectories

## [0.49.2] - 2026-01-19

### Added

- Added widget placement option for extension widgets via `widgetPlacement` in `pi.addWidget()` ([#850](https://github.com/badlogic/pi-mono/pull/850) by [@marckrenn](https://github.com/marckrenn))
- Added AWS credential detection for ECS/Kubernetes environments: `AWS_CONTAINER_CREDENTIALS_RELATIVE_URI`, `AWS_CONTAINER_CREDENTIALS_FULL_URI`, `AWS_WEB_IDENTITY_TOKEN_FILE` ([#848](https://github.com/badlogic/pi-mono/issues/848))
- Add "quiet startup" setting to `/settings` ([#847](https://github.com/badlogic/pi-mono/pull/847) by [@unexge](https://github.com/unexge))

### Changed

- HTML export now includes JSONL download button, jump-to-last-message on click, and fixed missing labels ([#853](https://github.com/badlogic/pi-mono/pull/853) by [@mitsuhiko](https://github.com/mitsuhiko))
- Improved error message for OAuth authentication failures (expired credentials, offline) instead of generic 'No API key found' ([#849](https://github.com/badlogic/pi-mono/pull/849) by [@zedrdave](https://github.com/zedrdave))

### Fixed
- Fixed `/model` selector scope toggle so you can switch between all and scoped models when scoped models are saved ([#844](https://github.com/badlogic/pi-mono/issues/844))
- Fixed OpenAI Responses 400 error "reasoning without following item" when replaying aborted turns ([#838](https://github.com/badlogic/pi-mono/pull/838))
- Fixed pi exiting with code 0 when cancelling resume session selection

### Removed

- Removed `strictResponsesPairing` compat option from models.json schema (no longer needed)

## [0.49.1] - 2026-01-18

### Added

- Added `strictResponsesPairing` compat option for custom OpenAI Responses models on Azure ([#768](https://github.com/badlogic/pi-mono/pull/768) by [@prateekmedia](https://github.com/prateekmedia))
- Session selector (`/resume`) now supports path display toggle (`Ctrl+P`) and session deletion (`Ctrl+D`) with inline confirmation ([#816](https://github.com/badlogic/pi-mono/pull/816) by [@w-winter](https://github.com/w-winter))
- Added undo support in interactive mode with Ctrl+- hotkey. ([#831](https://github.com/badlogic/pi-mono/pull/831) by [@Perlence](https://github.com/Perlence))

### Changed

- Share URLs now use hash fragments (`#`) instead of query strings (`?`) to prevent session IDs from being sent to buildwithpi.ai ([#829](https://github.com/badlogic/pi-mono/pull/829) by [@terrorobe](https://github.com/terrorobe))
- API keys in `models.json` can now be retrieved via shell command using `!` prefix (e.g., `"apiKey": "!security find-generic-password -ws 'anthropic'"` for macOS Keychain) ([#762](https://github.com/badlogic/pi-mono/pull/762) by [@cv](https://github.com/cv))

### Fixed

- Fixed IME candidate window appearing in wrong position when filtering menus with Input Method Editor (e.g., Chinese IME). Components with search inputs now properly propagate focus state for cursor positioning. ([#827](https://github.com/badlogic/pi-mono/issues/827))
- Fixed extension shortcut conflicts to respect user keybindings when built-in actions are remapped. ([#826](https://github.com/badlogic/pi-mono/pull/826) by [@richardgill](https://github.com/richardgill))
- Fixed photon WASM loading in standalone compiled binaries.
- Fixed tool call ID normalization for cross-provider handoffs (e.g., Codex to Antigravity Claude) ([#821](https://github.com/badlogic/pi-mono/issues/821))

## [0.49.0] - 2026-01-17

### Added

- `pi.setLabel(entryId, label)` in ExtensionAPI for setting per-entry labels from extensions ([#806](https://github.com/badlogic/pi-mono/issues/806))
- Export `keyHint`, `appKeyHint`, `editorKey`, `appKey`, `rawKeyHint` for extensions to format keybinding hints consistently ([#802](https://github.com/badlogic/pi-mono/pull/802) by [@dannote](https://github.com/dannote))
- Exported `VERSION` from the package index and updated the custom-header example. ([#798](https://github.com/badlogic/pi-mono/pull/798) by [@tallshort](https://github.com/tallshort))
- Added `showHardwareCursor` setting to control cursor visibility while still positioning it for IME support. ([#800](https://github.com/badlogic/pi-mono/pull/800) by [@ghoulr](https://github.com/ghoulr))
- Added Emacs-style kill ring editing with yank and yank-pop keybindings, plus legacy Alt+letter handling and Alt+D delete word forward support in the interactive editor. ([#810](https://github.com/badlogic/pi-mono/pull/810) by [@Perlence](https://github.com/Perlence))
- Added `ctx.compact()` and `ctx.getContextUsage()` to extension contexts for programmatic compaction and context usage checks.
- Added documentation for delete word forward and kill ring keybindings in interactive mode. ([#810](https://github.com/badlogic/pi-mono/pull/810) by [@Perlence](https://github.com/Perlence))

### Changed

- Updated the default system prompt wording to clarify the pi harness and documentation scope.
- Simplified Codex system prompt handling to use the default system prompt directly for Codex instructions.

### Fixed

- Fixed photon module failing to load in ESM context with "require is not defined" error ([#795](https://github.com/badlogic/pi-mono/pull/795) by [@dannote](https://github.com/dannote))
- Fixed compaction UI not showing when extensions trigger compaction.
- Fixed orphaned tool results after errored assistant messages causing Codex API errors. When an assistant message has `stopReason: "error"`, its tool calls are now excluded from pending tool tracking, preventing synthetic tool results from being generated for calls that will be dropped by provider-specific converters. ([#812](https://github.com/badlogic/pi-mono/issues/812))
- Fixed Bedrock Claude max_tokens handling to always exceed thinking budget tokens, preventing compaction failures. ([#797](https://github.com/badlogic/pi-mono/pull/797) by [@pjtf93](https://github.com/pjtf93))
- Fixed Claude Code tool name normalization to match the Claude Code tool list case-insensitively and remove invalid mappings.

### Removed

- Removed `pi-internal://` path resolution from the read tool.

## [0.48.0] - 2026-01-16

### Added

- Added `quietStartup` setting to silence startup output (version header, loaded context info, model scope line). Changelog notifications are still shown. ([#777](https://github.com/badlogic/pi-mono/pull/777) by [@ribelo](https://github.com/ribelo))
- Added `editorPaddingX` setting for horizontal padding in input editor (0-3, default: 0)
- Added `shellCommandPrefix` setting to prepend commands to every bash execution, enabling alias expansion in non-interactive shells (e.g., `"shellCommandPrefix": "shopt -s expand_aliases"`) ([#790](https://github.com/badlogic/pi-mono/pull/790) by [@richardgill](https://github.com/richardgill))
- Added bash-style argument slicing for prompt templates ([#770](https://github.com/badlogic/pi-mono/pull/770) by [@airtonix](https://github.com/airtonix))
- Extension commands can provide argument auto-completions via `getArgumentCompletions` in `pi.registerCommand()` ([#775](https://github.com/badlogic/pi-mono/pull/775) by [@ribelo](https://github.com/ribelo))
- Bash tool now displays the timeout value in the UI when a timeout is set ([#780](https://github.com/badlogic/pi-mono/pull/780) by [@dannote](https://github.com/dannote))
- Export `getShellConfig` for extensions to detect user's shell environment ([#766](https://github.com/badlogic/pi-mono/pull/766) by [@dannote](https://github.com/dannote))
- Added `thinkingText` and `selectedBg` to theme schema ([#763](https://github.com/badlogic/pi-mono/pull/763) by [@scutifer](https://github.com/scutifer))
- `navigateTree()` now supports `replaceInstructions` option to replace the default summarization prompt entirely, and `label` option to attach a label to the branch summary entry ([#787](https://github.com/badlogic/pi-mono/pull/787) by [@mitsuhiko](https://github.com/mitsuhiko))

### Fixed

- Fixed crash during auto-compaction when summarization fails (e.g., quota exceeded). Now displays error message instead of crashing ([#792](https://github.com/badlogic/pi-mono/issues/792))
- Fixed `--session <UUID>` to search globally across projects if not found locally, with option to fork sessions from other projects ([#785](https://github.com/badlogic/pi-mono/pull/785) by [@ribelo](https://github.com/ribelo))
- Fixed standalone binary WASM loading on Linux ([#784](https://github.com/badlogic/pi-mono/issues/784))
- Fixed string numbers in tool arguments not being coerced to numbers during validation ([#786](https://github.com/badlogic/pi-mono/pull/786) by [@dannote](https://github.com/dannote))
- Fixed `--no-extensions` flag not preventing extension discovery ([#776](https://github.com/badlogic/pi-mono/issues/776))
- Fixed extension messages rendering twice on startup when `pi.sendMessage({ display: true })` is called during `session_start` ([#765](https://github.com/badlogic/pi-mono/pull/765) by [@dannote](https://github.com/dannote))
- Fixed `PI_CODING_AGENT_DIR` env var not expanding tilde (`~`) to home directory ([#778](https://github.com/badlogic/pi-mono/pull/778) by [@aliou](https://github.com/aliou))
- Fixed session picker hint text overflow ([#764](https://github.com/badlogic/pi-mono/issues/764))
- Fixed Kitty keyboard protocol shifted symbol keys (e.g., `@`, `?`) not working in editor ([#779](https://github.com/badlogic/pi-mono/pull/779) by [@iamd3vil](https://github.com/iamd3vil))
- Fixed Bedrock tool call IDs causing API errors from invalid characters ([#781](https://github.com/badlogic/pi-mono/pull/781) by [@pjtf93](https://github.com/pjtf93))

### Changed

- Hardware cursor is now disabled by default for better terminal compatibility. Set `PI_HARDWARE_CURSOR=1` to enable (replaces `PI_NO_HARDWARE_CURSOR=1` which disabled it).

## [0.47.0] - 2026-01-16

### Breaking Changes

- Extensions using `Editor` directly must now pass `TUI` as the first constructor argument: `new Editor(tui, theme)`. The `tui` parameter is available in extension factory functions. ([#732](https://github.com/badlogic/pi-mono/issues/732))

### Added

- **OpenAI Codex official support**: Full compatibility with OpenAI's Codex CLI models (`gpt-5.1`, `gpt-5.2`, `gpt-5.1-codex-mini`, `gpt-5.2-codex`). Features include static system prompt for OpenAI allowlisting, prompt caching via session ID, and reasoning signature retention across turns. Set `OPENAI_API_KEY` and use `--provider openai-codex` or select a Codex model. ([#737](https://github.com/badlogic/pi-mono/pull/737))
- `pi-internal://` URL scheme in read tool for accessing internal documentation. The model can read files from the coding-agent package (README, docs, examples) to learn about extending pi.
- New `input` event in extension system for intercepting, transforming, or handling user input before the agent processes it. Supports three result types: `continue` (pass through), `transform` (modify text/images), `handled` (respond without LLM). Handlers chain transforms and short-circuit on handled. ([#761](https://github.com/badlogic/pi-mono/pull/761) by [@nicobailon](https://github.com/nicobailon))
- Extension example: `input-transform.ts` demonstrating input interception patterns (quick mode, instant commands, source routing) ([#761](https://github.com/badlogic/pi-mono/pull/761) by [@nicobailon](https://github.com/nicobailon))
- Custom tool HTML export: extensions with `renderCall`/`renderResult` now render in `/share` and `/export` output with ANSI-to-HTML color conversion ([#702](https://github.com/badlogic/pi-mono/pull/702) by [@aliou](https://github.com/aliou))
- Direct filter shortcuts in Tree mode: Ctrl+D (default), Ctrl+T (no-tools), Ctrl+U (user-only), Ctrl+L (labeled-only), Ctrl+A (all) ([#747](https://github.com/badlogic/pi-mono/pull/747) by [@kaofelix](https://github.com/kaofelix))

### Changed

- Skill commands (`/skill:name`) are now expanded in AgentSession instead of interactive mode. This enables skill commands in RPC and print modes, and allows the `input` event to intercept `/skill:name` before expansion.

### Fixed

- Editor no longer corrupts terminal display when loading large prompts via `setEditorText`. Content now scrolls vertically with indicators showing lines above/below the viewport. ([#732](https://github.com/badlogic/pi-mono/issues/732))
- Piped stdin now works correctly: `echo foo | pi` is equivalent to `pi -p foo`. When stdin is piped, print mode is automatically enabled since interactive mode requires a TTY ([#708](https://github.com/badlogic/pi-mono/issues/708))
- Session tree now preserves branch connectors and indentation when filters hide intermediate entries so descendants attach to the nearest visible ancestor and sibling branches align. Fixed in both TUI and HTML export ([#739](https://github.com/badlogic/pi-mono/pull/739) by [@w-winter](https://github.com/w-winter))
- Added `upstream connect`, `connection refused`, and `reset before headers` patterns to auto-retry error detection ([#733](https://github.com/badlogic/pi-mono/issues/733))
- Multi-line YAML frontmatter in skills and prompt templates now parses correctly. Centralized frontmatter parsing using the `yaml` library. ([#728](https://github.com/badlogic/pi-mono/pull/728) by [@richardgill](https://github.com/richardgill))
- `ctx.shutdown()` now waits for pending UI renders to complete before exiting, ensuring notifications and final output are visible ([#756](https://github.com/badlogic/pi-mono/issues/756))
- OpenAI Codex provider now retries on transient errors (429, 5xx, connection failures) with exponential backoff ([#733](https://github.com/badlogic/pi-mono/issues/733))

## [0.46.0] - 2026-01-15

### Fixed

- Scoped models (`--models` or `enabledModels`) now remember the last selected model across sessions instead of always starting with the first model in the scope ([#736](https://github.com/badlogic/pi-mono/pull/736) by [@ogulcancelik](https://github.com/ogulcancelik))
- Show `bun install` instead of `npm install` in update notification when running under Bun ([#714](https://github.com/badlogic/pi-mono/pull/714) by [@dannote](https://github.com/dannote))
- `/skill` prompts now include the skill path ([#711](https://github.com/badlogic/pi-mono/pull/711) by [@jblwilliams](https://github.com/jblwilliams))
- Use configurable `expandTools` keybinding instead of hardcoded Ctrl+O ([#717](https://github.com/badlogic/pi-mono/pull/717) by [@dannote](https://github.com/dannote))
- Compaction turn prefix summaries now merge correctly ([#738](https://github.com/badlogic/pi-mono/pull/738) by [@vsabavat](https://github.com/vsabavat))
- Avoid unsigned Gemini 3 tool calls ([#741](https://github.com/badlogic/pi-mono/pull/741) by [@roshanasingh4](https://github.com/roshanasingh4))
- Fixed signature support for non-Anthropic models in Amazon Bedrock provider ([#727](https://github.com/badlogic/pi-mono/pull/727) by [@unexge](https://github.com/unexge))
- Keyboard shortcuts (Ctrl+C, Ctrl+D, etc.) now work on non-Latin keyboard layouts (Russian, Ukrainian, Bulgarian, etc.) in terminals supporting Kitty keyboard protocol with alternate key reporting ([#718](https://github.com/badlogic/pi-mono/pull/718) by [@dannote](https://github.com/dannote))

### Added

- Edit tool now uses fuzzy matching as fallback when exact match fails, tolerating trailing whitespace, smart quotes, Unicode dashes, and special spaces ([#713](https://github.com/badlogic/pi-mono/pull/713) by [@dannote](https://github.com/dannote))
- Support `APPEND_SYSTEM.md` to append instructions to the system prompt ([#716](https://github.com/badlogic/pi-mono/pull/716) by [@tallshort](https://github.com/tallshort))
- Session picker search: Ctrl+R toggles sorting between fuzzy match (default) and most recent; supports quoted phrase matching and `re:` regex mode ([#731](https://github.com/badlogic/pi-mono/pull/731) by [@ogulcancelik](https://github.com/ogulcancelik))
- Export `getAgentDir` for extensions ([#749](https://github.com/badlogic/pi-mono/pull/749) by [@dannote](https://github.com/dannote))
- Show loaded prompt templates on startup ([#743](https://github.com/badlogic/pi-mono/pull/743) by [@tallshort](https://github.com/tallshort))
- MiniMax China (`minimax-cn`) provider support ([#725](https://github.com/badlogic/pi-mono/pull/725) by [@tallshort](https://github.com/tallshort))
- `gpt-5.2-codex` models for GitHub Copilot and OpenCode Zen providers ([#734](https://github.com/badlogic/pi-mono/pull/734) by [@aadishv](https://github.com/aadishv))

### Changed

- Replaced `wasm-vips` with `@silvia-odwyer/photon-node` for image processing ([#710](https://github.com/badlogic/pi-mono/pull/710) by [@can1357](https://github.com/can1357))
- Extension example: `plan-mode/` shortcut changed from Shift+P to Ctrl+Alt+P to avoid conflict with typing capital P ([#746](https://github.com/badlogic/pi-mono/pull/746) by [@ferologics](https://github.com/ferologics))
- UI keybinding hints now respect configured keybindings across components ([#724](https://github.com/badlogic/pi-mono/pull/724) by [@dannote](https://github.com/dannote))
- CLI process title is now set to `pi` for easier process identification ([#742](https://github.com/badlogic/pi-mono/pull/742) by [@richardgill](https://github.com/richardgill))

## [0.45.7] - 2026-01-13

### Added

- Exported `highlightCode` and `getLanguageFromPath` for extensions ([#703](https://github.com/badlogic/pi-mono/pull/703) by [@dannote](https://github.com/dannote))

## [0.45.6] - 2026-01-13

### Added

- `ctx.ui.custom()` now accepts `overlayOptions` for overlay positioning and sizing (anchor, margins, offsets, percentages, absolute positioning) ([#667](https://github.com/badlogic/pi-mono/pull/667) by [@nicobailon](https://github.com/nicobailon))
- `ctx.ui.custom()` now accepts `onHandle` callback to receive the `OverlayHandle` for controlling overlay visibility ([#667](https://github.com/badlogic/pi-mono/pull/667) by [@nicobailon](https://github.com/nicobailon))
- Extension example: `overlay-qa-tests.ts` with 10 commands for testing overlay positioning, animation, and toggle scenarios ([#667](https://github.com/badlogic/pi-mono/pull/667) by [@nicobailon](https://github.com/nicobailon))
- Extension example: `doom-overlay/` - DOOM game running as an overlay at 35 FPS (auto-downloads WAD on first run) ([#667](https://github.com/badlogic/pi-mono/pull/667) by [@nicobailon](https://github.com/nicobailon))

## [0.45.5] - 2026-01-13

### Fixed

- Skip changelog display on fresh install (only show on upgrades)

## [0.45.4] - 2026-01-13

### Changed

- Light theme colors adjusted for WCAG AA compliance (4.5:1 contrast ratio against white backgrounds)
- Replaced `sharp` with `wasm-vips` for image processing (resize, PNG conversion). Eliminates native build requirements that caused installation failures on some systems. ([#696](https://github.com/badlogic/pi-mono/issues/696))

### Added

- Extension example: `summarize.ts` for summarizing conversations using custom UI and an external model ([#684](https://github.com/badlogic/pi-mono/pull/684) by [@scutifer](https://github.com/scutifer))
- Extension example: `question.ts` enhanced with custom UI for asking user questions ([#693](https://github.com/badlogic/pi-mono/pull/693) by [@ferologics](https://github.com/ferologics))
- Extension example: `plan-mode/` enhanced with explicit step tracking and progress widget ([#694](https://github.com/badlogic/pi-mono/pull/694) by [@ferologics](https://github.com/ferologics))
- Extension example: `questionnaire.ts` for multi-question input with tab bar navigation ([#695](https://github.com/badlogic/pi-mono/pull/695) by [@ferologics](https://github.com/ferologics))
- Experimental Vercel AI Gateway provider support: set `AI_GATEWAY_API_KEY` and use `--provider vercel-ai-gateway`. Token usage is currently reported incorrectly by Anthropic Messages compatible endpoint. ([#689](https://github.com/badlogic/pi-mono/pull/689) by [@timolins](https://github.com/timolins))

### Fixed

- Fix API key resolution after model switches by using provider argument ([#691](https://github.com/badlogic/pi-mono/pull/691) by [@joshp123](https://github.com/joshp123))
- Fixed z.ai thinking/reasoning: thinking toggle now correctly enables/disables thinking for z.ai models ([#688](https://github.com/badlogic/pi-mono/issues/688))
- Fixed extension loading in compiled Bun binary: extensions with local file imports now work correctly. Updated `@mariozechner/jiti` to v2.6.5 which bundles babel for Bun binary compatibility. ([#681](https://github.com/badlogic/pi-mono/issues/681))
- Fixed theme loading when installed via mise: use wrapper directory in release tarballs for compatibility with mise's `strip_components=1` extraction. ([#681](https://github.com/badlogic/pi-mono/issues/681))

## [0.45.3] - 2026-01-13

## [0.45.2] - 2026-01-13

### Fixed

- Extensions now load correctly in compiled Bun binary using `@mariozechner/jiti` fork with `virtualModules` support. Bundled packages (`@sinclair/typebox`, `@mariozechner/pi-tui`, `@mariozechner/pi-ai`, `@mariozechner/pi-coding-agent`) are accessible to extensions without filesystem node_modules.

## [0.45.1] - 2026-01-13

### Changed

- `/share` now outputs `buildwithpi.ai` session preview URLs instead of `pi.dev`

## [0.45.0] - 2026-01-13

### Added

- MiniMax provider support: set `MINIMAX_API_KEY` and use `minimax/MiniMax-M2.1` ([#656](https://github.com/badlogic/pi-mono/pull/656) by [@dannote](https://github.com/dannote))
- `/scoped-models`: Alt+Up/Down to reorder enabled models. Order is preserved when saving with Ctrl+S and determines Ctrl+P cycling order. ([#676](https://github.com/badlogic/pi-mono/pull/676) by [@thomasmhr](https://github.com/thomasmhr))
- Amazon Bedrock provider support (experimental, tested with Anthropic Claude models only) ([#494](https://github.com/badlogic/pi-mono/pull/494) by [@unexge](https://github.com/unexge))
- Extension example: `sandbox/` for OS-level bash sandboxing using `@anthropic-ai/sandbox-runtime` with per-project config ([#673](https://github.com/badlogic/pi-mono/pull/673) by [@dannote](https://github.com/dannote))
- Print mode JSON output now emits the session header as the first line.

## [0.44.0] - 2026-01-12

### Breaking Changes

- `pi.getAllTools()` now returns `ToolInfo[]` (with `name` and `description`) instead of `string[]`. Extensions that only need names can use `.map(t => t.name)`. ([#648](https://github.com/badlogic/pi-mono/pull/648) by [@carsonfarmer](https://github.com/carsonfarmer))

### Added

- Session naming: `/name <name>` command sets a display name shown in the session selector instead of the first message. Useful for distinguishing forked sessions. Extensions can use `pi.setSessionName()` and `pi.getSessionName()`. ([#650](https://github.com/badlogic/pi-mono/pull/650) by [@scutifer](https://github.com/scutifer))
- Extension example: `notify.ts` for desktop notifications via OSC 777 escape sequence ([#658](https://github.com/badlogic/pi-mono/pull/658) by [@ferologics](https://github.com/ferologics))
- Inline hint for queued messages showing the `Alt+Up` restore shortcut ([#657](https://github.com/badlogic/pi-mono/pull/657) by [@tmustier](https://github.com/tmustier))
- Page-up/down navigation in `/resume` session selector to jump by 5 items ([#662](https://github.com/badlogic/pi-mono/pull/662) by [@aliou](https://github.com/aliou))
- Fuzzy search in `/settings` menu: type to filter settings by label ([#643](https://github.com/badlogic/pi-mono/pull/643) by [@ninlds](https://github.com/ninlds))

### Fixed

- Session selector now stays open when current folder has no sessions, allowing Tab to switch to "all" scope ([#661](https://github.com/badlogic/pi-mono/pull/661) by [@aliou](https://github.com/aliou))
- Extensions using theme utilities like `getSettingsListTheme()` now work in dev mode with tsx

## [0.43.0] - 2026-01-11

### Breaking Changes

- Extension editor (`ctx.ui.editor()`) now uses Enter to submit and Shift+Enter for newlines, matching the main editor. Previously used Ctrl+Enter to submit. Extensions with hardcoded "ctrl+enter" hints need updating. ([#642](https://github.com/badlogic/pi-mono/pull/642) by [@mitsuhiko](https://github.com/mitsuhiko))
- Renamed `/branch` command to `/fork` ([#641](https://github.com/badlogic/pi-mono/issues/641))
  - RPC: `branch` → `fork`, `get_branch_messages` → `get_fork_messages`
  - SDK: `branch()` → `fork()`, `getBranchMessages()` → `getForkMessages()`
  - AgentSession: `branch()` → `fork()`, `getUserMessagesForBranching()` → `getUserMessagesForForking()`
  - Extension events: `session_before_branch` → `session_before_fork`, `session_branch` → `session_fork`
  - Settings: `doubleEscapeAction: "branch" | "tree"` → `"fork" | "tree"`
- `SessionManager.list()` and `SessionManager.listAll()` are now async, returning `Promise<SessionInfo[]>`. Callers must await them. ([#620](https://github.com/badlogic/pi-mono/pull/620) by [@tmustier](https://github.com/tmustier))

### Added
- `/resume` selector now toggles between current-folder and all sessions with Tab, showing the session cwd in the All view and loading progress. ([#620](https://github.com/badlogic/pi-mono/pull/620) by [@tmustier](https://github.com/tmustier))
- `SessionManager.list()` and `SessionManager.listAll()` accept optional `onProgress` callback for progress updates
- `SessionInfo.cwd` field containing the session's working directory (empty string for old sessions)
- `SessionListProgress` type export for progress callbacks
- `/scoped-models` command to enable/disable models for Ctrl+P cycling. Changes are session-only by default; press Ctrl+S to persist to settings.json. ([#626](https://github.com/badlogic/pi-mono/pull/626) by [@CarlosGtrz](https://github.com/CarlosGtrz))
- `model_select` extension hook fires when model changes via `/model`, model cycling, or session restore with `source` field and `previousModel` ([#628](https://github.com/badlogic/pi-mono/pull/628) by [@marckrenn](https://github.com/marckrenn))
- `ctx.ui.setWorkingMessage()` extension API to customize the "Working..." message during streaming ([#625](https://github.com/badlogic/pi-mono/pull/625) by [@nicobailon](https://github.com/nicobailon))
- Skill slash commands: loaded skills are registered as `/skill:name` commands for quick access. Toggle via `/settings` or `skills.enableSkillCommands` in settings.json. ([#630](https://github.com/badlogic/pi-mono/pull/630) by [@Dwsy](https://github.com/Dwsy))
- Slash command autocomplete now uses fuzzy matching (type `/skbra` to match `/skill:brave-search`)
- `/tree` branch summarization now offers three options: "No summary", "Summarize", and "Summarize with custom prompt". Custom prompts are appended as additional focus to the default summarization instructions. ([#642](https://github.com/badlogic/pi-mono/pull/642) by [@mitsuhiko](https://github.com/mitsuhiko))

### Fixed

- Missing spacer between assistant message and text editor ([#655](https://github.com/badlogic/pi-mono/issues/655))
- Session picker respects custom keybindings when using `--resume` ([#633](https://github.com/badlogic/pi-mono/pull/633) by [@aos](https://github.com/aos))
- Custom footer extensions now see model changes: `ctx.model` is now a getter that returns the current model instead of a snapshot from when the context was created ([#634](https://github.com/badlogic/pi-mono/pull/634) by [@ogulcancelik](https://github.com/ogulcancelik))
- Footer git branch not updating after external branch switches. Git uses atomic writes (temp file + rename), which changes the inode and breaks `fs.watch` on the file. Now watches the directory instead.
- Extension loading errors are now displayed to the user instead of being silently ignored ([#639](https://github.com/badlogic/pi-mono/pull/639) by [@aliou](https://github.com/aliou))

## [0.42.5] - 2026-01-11

### Fixed

- Reduced flicker by only re-rendering changed lines ([#617](https://github.com/badlogic/pi-mono/pull/617) by [@ogulcancelik](https://github.com/ogulcancelik)). No worries tho, there's still a little flicker in the VS Code Terminal. Praise the flicker.
- Cursor position tracking when content shrinks with unchanged remaining lines
- TUI renders with wrong dimensions after suspend/resume if terminal was resized while suspended ([#599](https://github.com/badlogic/pi-mono/issues/599))
- Pasted content containing Kitty key release patterns (e.g., `:3F` in MAC addresses) was incorrectly filtered out ([#623](https://github.com/badlogic/pi-mono/pull/623) by [@ogulcancelik](https://github.com/ogulcancelik))

## [0.42.4] - 2026-01-10

### Fixed

- Bash output expanded hint now says "(ctrl+o to collapse)" ([#610](https://github.com/badlogic/pi-mono/pull/610) by [@tallshort](https://github.com/tallshort))
- Fixed UTF-8 text corruption in remote bash execution (SSH, containers) by using streaming TextDecoder ([#608](https://github.com/badlogic/pi-mono/issues/608))

## [0.42.3] - 2026-01-10

### Changed

- OpenAI Codex: updated to use bundled system prompt from upstream

## [0.42.2] - 2026-01-10

### Added

- `/model <search>` now pre-filters the model selector or auto-selects on exact match. Use `provider/model` syntax to disambiguate (e.g., `/model openai/gpt-4`). ([#587](https://github.com/badlogic/pi-mono/pull/587) by [@zedrdave](https://github.com/zedrdave))
- `FooterDataProvider` for custom footers: `ctx.ui.setFooter()` now receives a third `footerData` parameter providing `getGitBranch()`, `getExtensionStatuses()`, and `onBranchChange()` for reactive updates ([#600](https://github.com/badlogic/pi-mono/pull/600) by [@nicobailon](https://github.com/nicobailon))
- `Alt+Up` hotkey to restore queued steering/follow-up messages back into the editor without aborting the current run ([#604](https://github.com/badlogic/pi-mono/pull/604) by [@tmustier](https://github.com/tmustier))

### Fixed

- Fixed LM Studio compatibility for OpenAI Responses tool strict mapping in the ai provider ([#598](https://github.com/badlogic/pi-mono/pull/598) by [@gnattu](https://github.com/gnattu))

## [0.42.1] - 2026-01-09

### Fixed

- Symlinked directories in `prompts/` folders are now followed when loading prompt templates ([#601](https://github.com/badlogic/pi-mono/pull/601) by [@aliou](https://github.com/aliou))

## [0.42.0] - 2026-01-09

### Added

- Added OpenCode Zen provider support. Set `OPENCODE_API_KEY` env var and use `opencode/<model-id>` (e.g., `opencode/claude-opus-4-5`).

## [0.41.0] - 2026-01-09

### Added

- Anthropic OAuth support is back! Use `/login` to authenticate with your Claude Pro/Max subscription.

## [0.40.1] - 2026-01-09

### Removed

- Anthropic OAuth support (`/login`). Use API keys instead.

## [0.40.0] - 2026-01-08

### Added

- Documentation on component invalidation and theme changes in `docs/tui.md`

### Fixed

- Components now properly rebuild their content on theme change (tool executions, assistant messages, bash executions, custom messages, branch/compaction summaries)

## [0.39.1] - 2026-01-08

### Fixed

- `setTheme()` now triggers a full rerender so previously rendered components update with the new theme colors
- `mac-system-theme.ts` example now polls every 2 seconds and uses `osascript` for real-time macOS appearance detection

## [0.39.0] - 2026-01-08

### Breaking Changes

- `before_agent_start` event now receives `systemPrompt` in the event object and returns `systemPrompt` (full replacement) instead of `systemPromptAppend`. Extensions that were appending must now use `event.systemPrompt + extra` pattern. ([#575](https://github.com/badlogic/pi-mono/issues/575))
- `discoverSkills()` now returns `{ skills: Skill[], warnings: SkillWarning[] }` instead of `Skill[]`. This allows callers to handle skill loading warnings. ([#577](https://github.com/badlogic/pi-mono/pull/577) by [@cv](https://github.com/cv))

### Added

- `ctx.ui.getAllThemes()`, `ctx.ui.getTheme(name)`, and `ctx.ui.setTheme(name | Theme)` methods for extensions to list, load, and switch themes at runtime ([#576](https://github.com/badlogic/pi-mono/pull/576))
- `--no-tools` flag to disable all built-in tools, allowing extension-only tool setups ([#557](https://github.com/badlogic/pi-mono/pull/557) by [@cv](https://github.com/cv))
- Pluggable operations for built-in tools enabling remote execution via SSH or other transports ([#564](https://github.com/badlogic/pi-mono/issues/564)). Interfaces: `ReadOperations`, `WriteOperations`, `EditOperations`, `BashOperations`, `LsOperations`, `GrepOperations`, `FindOperations`
- `user_bash` event for intercepting user `!`/`!!` commands, allowing extensions to redirect to remote systems ([#528](https://github.com/badlogic/pi-mono/issues/528))
- `setActiveTools()` in ExtensionAPI for dynamic tool management
- Built-in renderers used automatically for tool overrides without custom `renderCall`/`renderResult`
- `ssh.ts` example: remote tool execution via `--ssh user@host:/path`
- `interactive-shell.ts` example: run interactive commands (vim, git rebase, htop) with full terminal access via `!i` prefix or auto-detection
- Wayland clipboard support for `/copy` command using wl-copy with xclip/xsel fallback ([#570](https://github.com/badlogic/pi-mono/pull/570) by [@OgulcanCelik](https://github.com/OgulcanCelik))
- **Experimental:** `ctx.ui.custom()` now accepts `{ overlay: true }` option for floating modal components that composite over existing content without clearing the screen ([#558](https://github.com/badlogic/pi-mono/pull/558) by [@nicobailon](https://github.com/nicobailon))
- `AgentSession.skills` and `AgentSession.skillWarnings` properties to access loaded skills without rediscovery ([#577](https://github.com/badlogic/pi-mono/pull/577) by [@cv](https://github.com/cv))

### Fixed

- String `systemPrompt` in `createAgentSession()` now works as a full replacement instead of having context files and skills appended, matching documented behavior ([#543](https://github.com/badlogic/pi-mono/issues/543))
- Update notification for bun binary installs now shows release download URL instead of npm command ([#567](https://github.com/badlogic/pi-mono/pull/567) by [@ferologics](https://github.com/ferologics))
- ESC key now works during "Working..." state after auto-retry ([#568](https://github.com/badlogic/pi-mono/pull/568) by [@tmustier](https://github.com/tmustier))
- Abort messages now show correct retry attempt count (e.g., "Aborted after 2 retry attempts") ([#568](https://github.com/badlogic/pi-mono/pull/568) by [@tmustier](https://github.com/tmustier))
- Fixed Antigravity provider returning 429 errors despite available quota ([#571](https://github.com/badlogic/pi-mono/pull/571) by [@ben-vargas](https://github.com/ben-vargas))
- Fixed malformed thinking text in Gemini/Antigravity responses where thinking content appeared as regular text or vice versa. Cross-model conversations now properly convert thinking blocks to plain text. ([#561](https://github.com/badlogic/pi-mono/issues/561))
- `--no-skills` flag now correctly prevents skills from loading in interactive mode ([#577](https://github.com/badlogic/pi-mono/pull/577) by [@cv](https://github.com/cv))

## [0.38.0] - 2026-01-08

### Breaking Changes

- `ctx.ui.custom()` factory signature changed from `(tui, theme, done)` to `(tui, theme, keybindings, done)` for keybinding access in custom components
- `LoadedExtension` type renamed to `Extension`
- `LoadExtensionsResult.setUIContext()` removed, replaced with `runtime: ExtensionRuntime`
- `ExtensionRunner` constructor now requires `runtime: ExtensionRuntime` as second parameter
- `ExtensionRunner.initialize()` signature changed from options object to positional params `(actions, contextActions, commandContextActions?, uiContext?)`
- `ExtensionRunner.getHasUI()` renamed to `hasUI()`
- OpenAI Codex model aliases removed (`gpt-5`, `gpt-5-mini`, `gpt-5-nano`, `codex-mini-latest`). Use canonical IDs: `gpt-5.1`, `gpt-5.1-codex-mini`, `gpt-5.2`, `gpt-5.2-codex`. ([#536](https://github.com/badlogic/pi-mono/pull/536) by [@ghoulr](https://github.com/ghoulr))

### Added

- `--no-extensions` flag to disable extension discovery while still allowing explicit `-e` paths ([#524](https://github.com/badlogic/pi-mono/pull/524) by [@cv](https://github.com/cv))
- SDK: `InteractiveMode`, `runPrintMode()`, `runRpcMode()` exported for building custom run modes. See `docs/sdk.md`.
- `PI_SKIP_VERSION_CHECK` environment variable to disable new version notifications at startup ([#549](https://github.com/badlogic/pi-mono/pull/549) by [@aos](https://github.com/aos))
- `thinkingBudgets` setting to customize token budgets per thinking level for token-based providers ([#529](https://github.com/badlogic/pi-mono/pull/529) by [@melihmucuk](https://github.com/melihmucuk))
- Extension UI dialogs (`ctx.ui.select()`, `ctx.ui.confirm()`, `ctx.ui.input()`) now support a `timeout` option with live countdown display ([#522](https://github.com/badlogic/pi-mono/pull/522) by [@nicobailon](https://github.com/nicobailon))
- Extensions can now provide custom editor components via `ctx.ui.setEditorComponent()`. See `examples/extensions/modal-editor.ts` and `docs/tui.md` Pattern 7.
- Extension factories can now be async, enabling dynamic imports and lazy-loaded dependencies ([#513](https://github.com/badlogic/pi-mono/pull/513) by [@austinm911](https://github.com/austinm911))
- `ctx.shutdown()` is now available in extension contexts for requesting a graceful shutdown. In interactive mode, shutdown is deferred until the agent becomes idle (after processing all queued steering and follow-up messages). In RPC mode, shutdown is deferred until after completing the current command response. In print mode, shutdown is a no-op as the process exits automatically when prompts complete. ([#542](https://github.com/badlogic/pi-mono/pull/542) by [@kaofelix](https://github.com/kaofelix))

### Fixed

- Default thinking level from settings now applies correctly when `enabledModels` is configured ([#540](https://github.com/badlogic/pi-mono/pull/540) by [@ferologics](https://github.com/ferologics))
- External edits to `settings.json` while pi is running are now preserved when pi saves settings ([#527](https://github.com/badlogic/pi-mono/pull/527) by [@ferologics](https://github.com/ferologics))
- Overflow-based compaction now skips if error came from a different model or was already handled by a previous compaction ([#535](https://github.com/badlogic/pi-mono/pull/535) by [@mitsuhiko](https://github.com/mitsuhiko))
- OpenAI Codex context window reduced from 400k to 272k tokens to match Codex CLI defaults and prevent 400 errors ([#536](https://github.com/badlogic/pi-mono/pull/536) by [@ghoulr](https://github.com/ghoulr))
- Context overflow detection now recognizes `context_length_exceeded` errors.
- Key presses no longer dropped when input is batched over SSH ([#538](https://github.com/badlogic/pi-mono/issues/538))
- Clipboard image support now works on Alpine Linux and other musl-based distros ([#533](https://github.com/badlogic/pi-mono/issues/533))

## [0.37.8] - 2026-01-07

## [0.37.7] - 2026-01-07

## [0.37.6] - 2026-01-06

### Added

- Extension UI dialogs (`ctx.ui.select()`, `ctx.ui.confirm()`, `ctx.ui.input()`) now accept an optional `AbortSignal` to programmatically dismiss dialogs. Useful for implementing timeouts. See `examples/extensions/timed-confirm.ts`. ([#474](https://github.com/badlogic/pi-mono/issues/474))
- HTML export now shows bridge prompts in model change messages for Codex sessions ([#510](https://github.com/badlogic/pi-mono/pull/510) by [@mitsuhiko](https://github.com/mitsuhiko))

## [0.37.5] - 2026-01-06

### Added

- ExtensionAPI: `setModel()`, `getThinkingLevel()`, `setThinkingLevel()` methods for extensions to change model and thinking level at runtime ([#509](https://github.com/badlogic/pi-mono/issues/509))
- Exported truncation utilities for custom tools: `truncateHead`, `truncateTail`, `truncateLine`, `formatSize`, `DEFAULT_MAX_BYTES`, `DEFAULT_MAX_LINES`, `TruncationOptions`, `TruncationResult`
- New example `truncated-tool.ts` demonstrating proper output truncation with custom rendering for extensions
- New example `preset.ts` demonstrating preset configurations with model/thinking/tools switching ([#347](https://github.com/badlogic/pi-mono/issues/347))
- Documentation for output truncation best practices in `docs/extensions.md`
- Exported all UI components for extensions: `ArminComponent`, `AssistantMessageComponent`, `BashExecutionComponent`, `BorderedLoader`, `BranchSummaryMessageComponent`, `CompactionSummaryMessageComponent`, `CustomEditor`, `CustomMessageComponent`, `DynamicBorder`, `ExtensionEditorComponent`, `ExtensionInputComponent`, `ExtensionSelectorComponent`, `FooterComponent`, `LoginDialogComponent`, `ModelSelectorComponent`, `OAuthSelectorComponent`, `SessionSelectorComponent`, `SettingsSelectorComponent`, `ShowImagesSelectorComponent`, `ThemeSelectorComponent`, `ThinkingSelectorComponent`, `ToolExecutionComponent`, `TreeSelectorComponent`, `UserMessageComponent`, `UserMessageSelectorComponent`, plus utilities `renderDiff`, `truncateToVisualLines`
- `docs/tui.md`: Common Patterns section with copy-paste code for SelectList, BorderedLoader, SettingsList, setStatus, setWidget, setFooter
- `docs/tui.md`: Key Rules section documenting critical patterns for extension UI development
- `docs/extensions.md`: Exhaustive example links for all ExtensionAPI methods and events
- System prompt now references `docs/tui.md` for TUI component development

## [0.37.4] - 2026-01-06

### Added

- Session picker (`pi -r`) and `--session` flag now support searching/resuming by session ID (UUID prefix) ([#495](https://github.com/badlogic/pi-mono/issues/495) by [@arunsathiya](https://github.com/arunsathiya))
- Extensions can now replace the startup header with `ctx.ui.setHeader()`, see `examples/extensions/custom-header.ts` ([#500](https://github.com/badlogic/pi-mono/pull/500) by [@tudoroancea](https://github.com/tudoroancea))

### Changed

- Startup help text: fixed misleading "ctrl+k to delete line" to "ctrl+k to delete to end"
- Startup help text and `/hotkeys`: added `!!` shortcut for running bash without adding output to context

### Fixed

- Queued steering/follow-up messages no longer wipe unsent editor input ([#503](https://github.com/badlogic/pi-mono/pull/503) by [@tmustier](https://github.com/tmustier))
- OAuth token refresh failure no longer crashes app at startup, allowing user to `/login` to re-authenticate ([#498](https://github.com/badlogic/pi-mono/issues/498))

## [0.37.3] - 2026-01-06

### Added

- Extensions can now replace the footer with `ctx.ui.setFooter()`, see `examples/extensions/custom-footer.ts` ([#481](https://github.com/badlogic/pi-mono/issues/481))
- Session ID is now forwarded to LLM providers for session-based caching (used by OpenAI Codex for prompt caching).
- Added `blockImages` setting to prevent images from being sent to LLM providers ([#492](https://github.com/badlogic/pi-mono/pull/492) by [@jsinge97](https://github.com/jsinge97))
- Extensions can now send user messages via `pi.sendUserMessage()` ([#483](https://github.com/badlogic/pi-mono/issues/483))

### Fixed

- Add `minimatch` as a direct dependency for explicit imports.
- Status bar now shows correct git branch when running in a git worktree ([#490](https://github.com/badlogic/pi-mono/pull/490) by [@kcosr](https://github.com/kcosr))
- Interactive mode: Ctrl+V clipboard image paste now works on Wayland sessions by using `wl-paste` with `xclip` fallback ([#488](https://github.com/badlogic/pi-mono/pull/488) by [@ghoulr](https://github.com/ghoulr))

## [0.37.2] - 2026-01-05

### Fixed

- Extension directories in `settings.json` now respect `package.json` manifests, matching global extension behavior ([#480](https://github.com/badlogic/pi-mono/pull/480) by [@prateekmedia](https://github.com/prateekmedia))
- Share viewer: deep links now scroll to the target message when opened via `/share`
- Bash tool now handles spawn errors gracefully instead of crashing the agent (missing cwd, invalid shell path) ([#479](https://github.com/badlogic/pi-mono/pull/479) by [@robinwander](https://github.com/robinwander))

## [0.37.1] - 2026-01-05

### Fixed

- Share viewer: copy-link buttons now generate correct URLs when session is viewed via `/share` (iframe context)

## [0.37.0] - 2026-01-05

### Added

- Share viewer: copy-link button on messages to share URLs that navigate directly to a specific message ([#477](https://github.com/badlogic/pi-mono/pull/477) by [@lockmeister](https://github.com/lockmeister))
- Extension example: add `claude-rules` to load `.claude/rules/` entries into the system prompt ([#461](https://github.com/badlogic/pi-mono/pull/461) by [@vaayne](https://github.com/vaayne))
- Headless OAuth login: all providers now show paste input for manual URL/code entry, works over SSH without DISPLAY ([#428](https://github.com/badlogic/pi-mono/pull/428) by [@ben-vargas](https://github.com/ben-vargas), [#468](https://github.com/badlogic/pi-mono/pull/468) by [@crcatala](https://github.com/crcatala))

### Changed

- OAuth login UI now uses dedicated dialog component with consistent borders
- Assume truecolor support for all terminals except `dumb`, empty, or `linux` (fixes colors over SSH)
- OpenAI Codex clean-up: removed per-thinking-level model variants, thinking level is now set separately and the provider clamps to what each model supports internally (initial implementation in [#472](https://github.com/badlogic/pi-mono/pull/472) by [@ben-vargas](https://github.com/ben-vargas))

### Fixed

- Messages submitted during compaction are queued and delivered after compaction completes, preserving steering and follow-up behavior. Extension commands execute immediately during compaction. ([#476](https://github.com/badlogic/pi-mono/pull/476) by [@tmustier](https://github.com/tmustier))
- Managed binaries (`fd`, `rg`) now stored in `~/.pi/agent/bin/` instead of `tools/`, eliminating false deprecation warnings ([#470](https://github.com/badlogic/pi-mono/pull/470) by [@mcinteerj](https://github.com/mcinteerj))
- Extensions defined in `settings.json` were not loaded ([#463](https://github.com/badlogic/pi-mono/pull/463) by [@melihmucuk](https://github.com/melihmucuk))
- OAuth refresh no longer logs users out when multiple pi instances are running ([#466](https://github.com/badlogic/pi-mono/pull/466) by [@Cursivez](https://github.com/Cursivez))
- Migration warnings now ignore `fd.exe` and `rg.exe` in `tools/` on Windows ([#458](https://github.com/badlogic/pi-mono/pull/458) by [@carlosgtrz](https://github.com/carlosgtrz))
- CI: add `examples/extensions/with-deps` to workspaces to fix typecheck ([#467](https://github.com/badlogic/pi-mono/pull/467) by [@aliou](https://github.com/aliou))
- SDK: passing `extensions: []` now disables extension discovery as documented ([#465](https://github.com/badlogic/pi-mono/pull/465) by [@aliou](https://github.com/aliou))

## [0.36.0] - 2026-01-05

### Added

- Experimental: OpenAI Codex OAuth provider support: access Codex models via ChatGPT Plus/Pro subscription using `/login openai-codex` ([#451](https://github.com/badlogic/pi-mono/pull/451) by [@kim0](https://github.com/kim0))

## [0.35.0] - 2026-01-05

This release unifies hooks and custom tools into a single "extensions" system and renames "slash commands" to "prompt templates". ([#454](https://github.com/badlogic/pi-mono/issues/454))

**Before migrating, read:**

- [docs/extensions.md](docs/extensions.md) - Full API reference
- [README.md](README.md) - Extensions section with examples
- [examples/extensions/](examples/extensions/) - Working examples

### Extensions Migration

Hooks and custom tools are now unified as **extensions**. Both were TypeScript modules exporting a factory function that receives an API object. Now there's one concept, one discovery location, one CLI flag, one settings.json entry.

**Automatic migration:**

- `commands/` directories are automatically renamed to `prompts/` on startup (both `~/.pi/agent/commands/` and `.pi/commands/`)

**Manual migration required:**

1. Move files from `hooks/` and `tools/` directories to `extensions/` (deprecation warnings shown on startup)
2. Update imports and type names in your extension code
3. Update `settings.json` if you have explicit hook and custom tool paths configured

**Directory changes:**

```
# Before
~/.pi/agent/hooks/*.ts       →  ~/.pi/agent/extensions/*.ts
~/.pi/agent/tools/*.ts       →  ~/.pi/agent/extensions/*.ts
.pi/hooks/*.ts               →  .pi/extensions/*.ts
.pi/tools/*.ts               →  .pi/extensions/*.ts
```

**Extension discovery rules** (in `extensions/` directories):

1. **Direct files:** `extensions/*.ts` or `*.js` → loaded directly
2. **Subdirectory with index:** `extensions/myext/index.ts` → loaded as single extension
3. **Subdirectory with package.json:** `extensions/myext/package.json` with `"pi"` field → loads declared paths

```json
// extensions/my-package/package.json
{
  "name": "my-extension-package",
  "dependencies": { "zod": "^3.0.0" },
  "pi": {
    "extensions": ["./src/main.ts", "./src/tools.ts"]
  }
}
```

No recursion beyond one level. Complex packages must use the `package.json` manifest. Dependencies are resolved via jiti, and extensions can be published to and installed from npm.

**Type renames:**

- `HookAPI` → `ExtensionAPI`
- `HookContext` → `ExtensionContext`
- `HookCommandContext` → `ExtensionCommandContext`
- `HookUIContext` → `ExtensionUIContext`
- `CustomToolAPI` → `ExtensionAPI` (merged)
- `CustomToolContext` → `ExtensionContext` (merged)
- `CustomToolUIContext` → `ExtensionUIContext`
- `CustomTool` → `ToolDefinition`
- `CustomToolFactory` → `ExtensionFactory`
- `HookMessage` → `CustomMessage`

**Import changes:**

```typescript
// Before (hook)
import type { HookAPI, HookContext } from "@mariozechner/pi-coding-agent";
export default function (pi: HookAPI) { ... }

// Before (custom tool)
import type { CustomToolFactory } from "@mariozechner/pi-coding-agent";
const factory: CustomToolFactory = (pi) => ({ name: "my_tool", ... });
export default factory;

// After (both are now extensions)
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
export default function (pi: ExtensionAPI) {
  pi.on("tool_call", async (event, ctx) => { ... });
  pi.registerTool({ name: "my_tool", ... });
}
```

**Custom tools now have full context access.** Tools registered via `pi.registerTool()` now receive the same `ctx` object that event handlers receive. Previously, custom tools had limited context. Now all extension code shares the same capabilities:

- `pi.registerTool()` - Register tools the LLM can call
- `pi.registerCommand()` - Register commands like `/mycommand`
- `pi.registerShortcut()` - Register keyboard shortcuts (shown in `/hotkeys`)
- `pi.registerFlag()` - Register CLI flags (shown in `--help`)
- `pi.registerMessageRenderer()` - Custom TUI rendering for message types
- `pi.on()` - Subscribe to lifecycle events (tool_call, session_start, etc.)
- `pi.sendMessage()` - Inject messages into the conversation
- `pi.appendEntry()` - Persist custom data in session (survives restart/branch)
- `pi.exec()` - Run shell commands
- `pi.getActiveTools()` / `pi.setActiveTools()` - Dynamic tool enable/disable
- `pi.getAllTools()` - List all available tools
- `pi.events` - Event bus for cross-extension communication
- `ctx.ui.confirm()` / `select()` / `input()` - User prompts
- `ctx.ui.notify()` - Toast notifications
- `ctx.ui.setStatus()` - Persistent status in footer (multiple extensions can set their own)
- `ctx.ui.setWidget()` - Widget display above editor
- `ctx.ui.setTitle()` - Set terminal window title
- `ctx.ui.custom()` - Full TUI component with keyboard handling
- `ctx.ui.editor()` - Multi-line text editor with external editor support
- `ctx.sessionManager` - Read session entries, get branch history

**Settings changes:**

```json
// Before
{
  "hooks": ["./my-hook.ts"],
  "customTools": ["./my-tool.ts"]
}

// After
{
  "extensions": ["./my-extension.ts"]
}
```

**CLI changes:**

```bash
# Before
pi --hook ./safety.ts --tool ./todo.ts

# After
pi --extension ./safety.ts -e ./todo.ts
```

### Prompt Templates Migration

"Slash commands" (markdown files defining reusable prompts invoked via `/name`) are renamed to "prompt templates" to avoid confusion with extension-registered commands.

**Automatic migration:** The `commands/` directory is automatically renamed to `prompts/` on startup (if `prompts/` doesn't exist). Works for both regular directories and symlinks.

**Directory changes:**

```
~/.pi/agent/commands/*.md    →  ~/.pi/agent/prompts/*.md
.pi/commands/*.md            →  .pi/prompts/*.md
```

**SDK type renames:**

- `FileSlashCommand` → `PromptTemplate`
- `LoadSlashCommandsOptions` → `LoadPromptTemplatesOptions`

**SDK function renames:**

- `discoverSlashCommands()` → `discoverPromptTemplates()`
- `loadSlashCommands()` → `loadPromptTemplates()`
- `expandSlashCommand()` → `expandPromptTemplate()`
- `getCommandsDir()` → `getPromptsDir()`

**SDK option renames:**

- `CreateAgentSessionOptions.slashCommands` → `.promptTemplates`
- `AgentSession.fileCommands` → `.promptTemplates`
- `PromptOptions.expandSlashCommands` → `.expandPromptTemplates`

### SDK Migration

**Discovery functions:**

- `discoverAndLoadHooks()` → `discoverAndLoadExtensions()`
- `discoverAndLoadCustomTools()` → merged into `discoverAndLoadExtensions()`
- `loadHooks()` → `loadExtensions()`
- `loadCustomTools()` → merged into `loadExtensions()`

**Runner and wrapper:**

- `HookRunner` → `ExtensionRunner`
- `wrapToolsWithHooks()` → `wrapToolsWithExtensions()`
- `wrapToolWithHooks()` → `wrapToolWithExtensions()`

**CreateAgentSessionOptions:**

- `.hooks` → removed (use `.additionalExtensionPaths` for paths)
- `.additionalHookPaths` → `.additionalExtensionPaths`
- `.preloadedHooks` → `.preloadedExtensions`
- `.customTools` type changed: `Array<{ path?; tool: CustomTool }>` → `ToolDefinition[]`
- `.additionalCustomToolPaths` → merged into `.additionalExtensionPaths`
- `.slashCommands` → `.promptTemplates`

**AgentSession:**

- `.hookRunner` → `.extensionRunner`
- `.fileCommands` → `.promptTemplates`
- `.sendHookMessage()` → `.sendCustomMessage()`

### Session Migration

**Automatic.** Session version bumped from 2 to 3. Existing sessions are migrated on first load:

- Message role `"hookMessage"` → `"custom"`

### Breaking Changes

- **Settings:** `hooks` and `customTools` arrays replaced with single `extensions` array
- **CLI:** `--hook` and `--tool` flags replaced with `--extension` / `-e`
- **Directories:** `hooks/`, `tools/` → `extensions/`; `commands/` → `prompts/`
- **Types:** See type renames above
- **SDK:** See SDK migration above

### Changed

- Extensions can have their own `package.json` with dependencies (resolved via jiti)
- Documentation: `docs/hooks.md` and `docs/custom-tools.md` merged into `docs/extensions.md`
- Examples: `examples/hooks/` and `examples/custom-tools/` merged into `examples/extensions/`
- README: Extensions section expanded with custom tools, commands, events, state persistence, shortcuts, flags, and UI examples
- SDK: `customTools` option now accepts `ToolDefinition[]` directly (simplified from `Array<{ path?, tool }>`)
- SDK: `extensions` option accepts `ExtensionFactory[]` for inline extensions
- SDK: `additionalExtensionPaths` replaces both `additionalHookPaths` and `additionalCustomToolPaths`

## [0.34.2] - 2026-01-04

## [0.34.1] - 2026-01-04

### Added

- Hook API: `ctx.ui.setTitle(title)` allows hooks to set the terminal window/tab title ([#446](https://github.com/badlogic/pi-mono/pull/446) by [@aliou](https://github.com/aliou))

### Changed

- Expanded keybinding documentation to list all 32 supported symbol keys with notes on ctrl+symbol behavior ([#450](https://github.com/badlogic/pi-mono/pull/450) by [@kaofelix](https://github.com/kaofelix))

## [0.34.0] - 2026-01-04

### Added

- Hook API: `pi.getActiveTools()` and `pi.setActiveTools(toolNames)` for dynamically enabling/disabling tools from hooks
- Hook API: `pi.getAllTools()` to enumerate all configured tools (built-in via --tools or default, plus custom tools)
- Hook API: `pi.registerFlag(name, options)` and `pi.getFlag(name)` for hooks to register custom CLI flags (parsed automatically)
- Hook API: `pi.registerShortcut(shortcut, options)` for hooks to register custom keyboard shortcuts using `KeyId` (e.g., `Key.shift("p")`). Conflicts with built-in shortcuts are skipped, conflicts between hooks logged as warnings.
- Hook API: `ctx.ui.setWidget(key, content)` for status displays above the editor. Accepts either a string array or a component factory function.
- Hook API: `theme.strikethrough(text)` for strikethrough text styling
- Hook API: `before_agent_start` handlers can now return `systemPromptAppend` to dynamically append text to the system prompt for that turn. Multiple hooks' appends are concatenated.
- Hook API: `before_agent_start` handlers can now return multiple messages (all are injected, not just the first)
- `/hotkeys` command now shows hook-registered shortcuts in a separate "Hooks" section
- New example hook: `plan-mode.ts` - Claude Code-style read-only exploration mode:
  - Toggle via `/plan` command, `Shift+P` shortcut, or `--plan` CLI flag
  - Read-only tools: `read`, `bash`, `grep`, `find`, `ls` (no `edit`/`write`)
  - Bash commands restricted to non-destructive operations (blocks `rm`, `mv`, `git commit`, `npm install`, etc.)
  - Interactive prompt after each response: execute plan, stay in plan mode, or refine
  - Todo list widget showing progress with checkboxes and strikethrough for completed items
  - Each todo has a unique ID; agent marks items done by outputting `[DONE:id]`
  - Progress updates via `agent_end` hook (parses completed items from final message)
  - `/todos` command to view current plan progress
  - Shows `⏸ plan` indicator in footer when in plan mode, `📋 2/5` when executing
  - State persists across sessions (including todo progress)
- New example hook: `tools.ts` - Interactive `/tools` command to enable/disable tools with session persistence
- New example hook: `pirate.ts` - Demonstrates `systemPromptAppend` to make the agent speak like a pirate
- Tool registry now contains all built-in tools (read, bash, edit, write, grep, find, ls) even when `--tools` limits the initially active set. Hooks can enable any tool from the registry via `pi.setActiveTools()`.
- System prompt now automatically rebuilds when tools change via `setActiveTools()`, updating tool descriptions and guidelines to match the new tool set
- Hook errors now display full stack traces for easier debugging
- Event bus (`pi.events`) for tool/hook communication: shared pub/sub between custom tools and hooks
- Custom tools now have `pi.sendMessage()` to send messages directly to the agent session without needing the event bus
- `sendMessage()` supports `deliverAs: "nextTurn"` to queue messages for the next user prompt

### Changed

- Removed image placeholders after copy & paste, replaced with inserting image file paths directly. ([#442](https://github.com/badlogic/pi-mono/pull/442) by [@mitsuhiko](https://github.com/mitsuhiko))

### Fixed

- Fixed potential text decoding issues in bash executor by using streaming TextDecoder instead of Buffer.toString()
- External editor (Ctrl-G) now shows full pasted content instead of `[paste #N ...]` placeholders ([#444](https://github.com/badlogic/pi-mono/pull/444) by [@aliou](https://github.com/aliou))

## [0.33.0] - 2026-01-04

### Breaking Changes

- **Key detection functions removed from `@mariozechner/pi-tui`**: All `isXxx()` key detection functions (`isEnter()`, `isEscape()`, `isCtrlC()`, etc.) have been removed. Use `matchesKey(data, keyId)` instead (e.g., `matchesKey(data, "enter")`, `matchesKey(data, "ctrl+c")`). This affects hooks and custom tools that use `ctx.ui.custom()` with keyboard input handling. ([#405](https://github.com/badlogic/pi-mono/pull/405))

### Added

- Clipboard image paste support via `Ctrl+V`. Images are saved to a temp file and attached to the message. Works on macOS, Windows, and Linux (X11). ([#419](https://github.com/badlogic/pi-mono/issues/419))
- Configurable keybindings via `~/.pi/agent/keybindings.json`. All keyboard shortcuts (editor navigation, deletion, app actions like model cycling, etc.) can now be customized. Supports multiple bindings per action. ([#405](https://github.com/badlogic/pi-mono/pull/405) by [@hjanuschka](https://github.com/hjanuschka))
- `/quit` and `/exit` slash commands to gracefully exit the application. Unlike double Ctrl+C, these properly await hook and custom tool cleanup handlers before exiting. ([#426](https://github.com/badlogic/pi-mono/pull/426) by [@ben-vargas](https://github.com/ben-vargas))

### Fixed

- Subagent example README referenced incorrect filename `subagent.ts` instead of `index.ts` ([#427](https://github.com/badlogic/pi-mono/pull/427) by [@Whamp](https://github.com/Whamp))

## [0.32.3] - 2026-01-03

### Fixed

- `--list-models` no longer shows Google Vertex AI models without explicit authentication configured
- JPEG/GIF/WebP images not displaying in terminals using Kitty graphics protocol (Kitty, Ghostty, WezTerm). The protocol requires PNG format, so non-PNG images are now converted before display.
- Version check URL typo preventing update notifications from working ([#423](https://github.com/badlogic/pi-mono/pull/423) by [@skuridin](https://github.com/skuridin))
- Large images exceeding Anthropic's 5MB limit now retry with progressive quality/size reduction ([#424](https://github.com/badlogic/pi-mono/pull/424) by [@mitsuhiko](https://github.com/mitsuhiko))

## [0.32.2] - 2026-01-03

### Added

- `$ARGUMENTS` syntax for custom slash commands as alternative to `$@` for all arguments joined. Aligns with patterns used by Claude, Codex, and OpenCode. Both syntaxes remain fully supported. ([#418](https://github.com/badlogic/pi-mono/pull/418) by [@skuridin](https://github.com/skuridin))

### Changed

- **Slash commands and hook commands now work during streaming**: Previously, using a slash command or hook command while the agent was streaming would crash with "Agent is already processing". Now:
  - Hook commands execute immediately (they manage their own LLM interaction via `pi.sendMessage()`)
  - File-based slash commands are expanded and queued via steer/followUp
  - `steer()` and `followUp()` now expand file-based slash commands and error on hook commands (hook commands cannot be queued)
  - `prompt()` accepts new `streamingBehavior` option (`"steer"` or `"followUp"`) to specify queueing behavior during streaming
  - RPC `prompt` command now accepts optional `streamingBehavior` field
    ([#420](https://github.com/badlogic/pi-mono/issues/420))

### Fixed

- Slash command argument substitution now processes positional arguments (`$1`, `$2`, etc.) before all-arguments (`$@`, `$ARGUMENTS`) to prevent recursive substitution when argument values contain dollar-digit patterns like `$100`. ([#418](https://github.com/badlogic/pi-mono/pull/418) by [@skuridin](https://github.com/skuridin))

## [0.32.1] - 2026-01-03

### Added

- Shell commands without context contribution: use `!!command` to execute a bash command that is shown in the TUI and saved to session history but excluded from LLM context. Useful for running commands you don't want the AI to see. ([#414](https://github.com/badlogic/pi-mono/issues/414))

### Fixed

- Edit tool diff not displaying in TUI due to race condition between async preview computation and tool execution

## [0.32.0] - 2026-01-03

### Breaking Changes

- **Queue API replaced with steer/followUp**: The `queueMessage()` method has been split into two methods with different delivery semantics ([#403](https://github.com/badlogic/pi-mono/issues/403)):
  - `steer(text)`: Interrupts the agent mid-run (Enter while streaming). Delivered after current tool execution.
  - `followUp(text)`: Waits until the agent finishes (Alt+Enter while streaming). Delivered only when agent stops.
- **Settings renamed**: `queueMode` setting renamed to `steeringMode`. Added new `followUpMode` setting. Old settings.json files are migrated automatically.
- **AgentSession methods renamed**:
  - `queueMessage()` → `steer()` and `followUp()`
  - `queueMode` getter → `steeringMode` and `followUpMode` getters
  - `setQueueMode()` → `setSteeringMode()` and `setFollowUpMode()`
  - `queuedMessageCount` → `pendingMessageCount`
  - `getQueuedMessages()` → `getSteeringMessages()` and `getFollowUpMessages()`
  - `clearQueue()` now returns `{ steering: string[], followUp: string[] }`
  - `hasQueuedMessages()` → `hasPendingMessages()`
- **Hook API signature changed**: `pi.sendMessage()` second parameter changed from `triggerTurn?: boolean` to `options?: { triggerTurn?, deliverAs? }`. Use `deliverAs: "followUp"` for follow-up delivery. Affects both hooks and internal `sendHookMessage()` method.
- **RPC API changes**:
  - `queue_message` command → `steer` and `follow_up` commands
  - `set_queue_mode` command → `set_steering_mode` and `set_follow_up_mode` commands
  - `RpcSessionState.queueMode` → `steeringMode` and `followUpMode`
- **Settings UI**: "Queue mode" setting split into "Steering mode" and "Follow-up mode"

### Added

- Configurable double-escape action: choose whether double-escape with empty editor opens `/tree` (default) or `/branch`. Configure via `/settings` or `doubleEscapeAction` in settings.json ([#404](https://github.com/badlogic/pi-mono/issues/404))
- Vertex AI provider (`google-vertex`): access Gemini models via Google Cloud Vertex AI using Application Default Credentials ([#300](https://github.com/badlogic/pi-mono/pull/300) by [@default-anton](https://github.com/default-anton))
- Built-in provider overrides in `models.json`: override just `baseUrl` to route a built-in provider through a proxy while keeping all its models, or define `models` to fully replace the provider ([#406](https://github.com/badlogic/pi-mono/pull/406) by [@yevhen](https://github.com/yevhen))
- Automatic image resizing: images larger than 2000x2000 are resized for better model compatibility. Original dimensions are injected into the prompt. Controlled via `/settings` or `images.autoResize` in settings.json. ([#402](https://github.com/badlogic/pi-mono/pull/402) by [@mitsuhiko](https://github.com/mitsuhiko))
- Alt+Enter keybind to queue follow-up messages while agent is streaming
- `Theme` and `ThemeColor` types now exported for hooks using `ctx.ui.custom()`
- Terminal window title now displays "pi - dirname" to identify which project session you're in ([#407](https://github.com/badlogic/pi-mono/pull/407) by [@kaofelix](https://github.com/kaofelix))

### Changed

- Editor component now uses word wrapping instead of character-level wrapping for better readability ([#382](https://github.com/badlogic/pi-mono/pull/382) by [@nickseelert](https://github.com/nickseelert))

### Fixed

- `/model` selector now opens instantly instead of waiting for OAuth token refresh. Token refresh is deferred until a model is actually used.
- Shift+Space, Shift+Backspace, and Shift+Delete now work correctly in Kitty-protocol terminals (Kitty, WezTerm, etc.) instead of being silently ignored ([#411](https://github.com/badlogic/pi-mono/pull/411) by [@nathyong](https://github.com/nathyong))
- `AgentSession.prompt()` now throws if called while the agent is already streaming, preventing race conditions. Use `steer()` or `followUp()` to queue messages during streaming.
- Ctrl+C now works like Escape in selector components, so mashing Ctrl+C will eventually close the program ([#400](https://github.com/badlogic/pi-mono/pull/400) by [@mitsuhiko](https://github.com/mitsuhiko))

## [0.31.1] - 2026-01-02

### Fixed

- Model selector no longer allows negative index when pressing arrow keys before models finish loading ([#398](https://github.com/badlogic/pi-mono/pull/398) by [@mitsuhiko](https://github.com/mitsuhiko))
- Type guard functions (`isBashToolResult`, etc.) now exported at runtime, not just in type declarations ([#397](https://github.com/badlogic/pi-mono/issues/397))

## [0.31.0] - 2026-01-02

This release introduces session trees for in-place branching, major API changes to hooks and custom tools, and structured compaction with file tracking.

### Session Tree

Sessions now use a tree structure with `id`/`parentId` fields. This enables in-place branching: navigate to any previous point with `/tree`, continue from there, and switch between branches while preserving all history in a single file.

**Existing sessions are automatically migrated** (v1 → v2) on first load. No manual action required.

New entry types: `BranchSummaryEntry` (context from abandoned branches), `CustomEntry` (hook state), `CustomMessageEntry` (hook-injected messages), `LabelEntry` (bookmarks).

See [docs/session.md](docs/session.md) for the file format and `SessionManager` API.

### Hooks Migration

The hooks API has been restructured with more granular events and better session access.

**Type renames:**

- `HookEventContext` → `HookContext`
- `HookCommandContext` is now a new interface extending `HookContext` with session control methods

**Event changes:**

- The monolithic `session` event is now split into granular events: `session_start`, `session_before_switch`, `session_switch`, `session_before_branch`, `session_branch`, `session_before_compact`, `session_compact`, `session_shutdown`
- `session_before_switch` and `session_switch` events now include `reason: "new" | "resume"` to distinguish between `/new` and `/resume`
- New `session_before_tree` and `session_tree` events for `/tree` navigation (hook can provide custom branch summary)
- New `before_agent_start` event: inject messages before the agent loop starts
- New `context` event: modify messages non-destructively before each LLM call
- Session entries are no longer passed in events. Use `ctx.sessionManager.getEntries()` or `ctx.sessionManager.getBranch()` instead

**API changes:**

- `pi.send(text, attachments?)` → `pi.sendMessage(message, triggerTurn?)` (creates `CustomMessageEntry`)
- New `pi.appendEntry(customType, data?)` for hook state persistence (not in LLM context)
- New `pi.registerCommand(name, options)` for custom slash commands (handler receives `HookCommandContext`)
- New `pi.registerMessageRenderer(customType, renderer)` for custom TUI rendering
- New `ctx.isIdle()`, `ctx.abort()`, `ctx.hasQueuedMessages()` for agent state (available in all events)
- New `ctx.ui.editor(title, prefill?)` for multi-line text editing with Ctrl+G external editor support
- New `ctx.ui.custom(component)` for full TUI component rendering with keyboard focus
- New `ctx.ui.setStatus(key, text)` for persistent status text in footer (multiple hooks can set their own)
- New `ctx.ui.theme` getter for styling text with theme colors
- `ctx.exec()` moved to `pi.exec()`
- `ctx.sessionFile` → `ctx.sessionManager.getSessionFile()`
- New `ctx.modelRegistry` and `ctx.model` for API key resolution

**HookCommandContext (slash commands only):**

- `ctx.waitForIdle()` - wait for agent to finish streaming
- `ctx.newSession(options?)` - create new sessions with optional setup callback
- `ctx.fork(entryId) - fork from a specific entry, creating a new session file
- `ctx.navigateTree(targetId, options?)` - navigate the session tree

These methods are only on `HookCommandContext` (not `HookContext`) because they can deadlock if called from event handlers that run inside the agent loop.

**Removed:**

- `hookTimeout` setting (hooks no longer have timeouts; use Ctrl+C to abort)
- `resolveApiKey` parameter (use `ctx.modelRegistry.getApiKey(model)`)

See [docs/hooks.md](docs/hooks.md) and [examples/hooks/](examples/hooks/) for the current API.

### Custom Tools Migration

The custom tools API has been restructured to mirror the hooks pattern with a context object.

**Type renames:**

- `CustomAgentTool` → `CustomTool`
- `ToolAPI` → `CustomToolAPI`
- `ToolContext` → `CustomToolContext`
- `ToolSessionEvent` → `CustomToolSessionEvent`

**Execute signature changed:**

```typescript
// Before (v0.30.2)
execute(toolCallId, params, signal, onUpdate)

// After
execute(toolCallId, params, onUpdate, ctx, signal?)
```

The new `ctx: CustomToolContext` provides `sessionManager`, `modelRegistry`, `model`, and agent state methods:

- `ctx.isIdle()` - check if agent is streaming
- `ctx.hasQueuedMessages()` - check if user has queued messages (skip interactive prompts)
- `ctx.abort()` - abort current operation (fire-and-forget)

**Session event changes:**

- `CustomToolSessionEvent` now only has `reason` and `previousSessionFile`
- Session entries are no longer in the event. Use `ctx.sessionManager.getBranch()` or `ctx.sessionManager.getEntries()` to reconstruct state
- Reasons: `"start" | "switch" | "branch" | "tree" | "shutdown"` (no separate `"new"` reason; `/new` triggers `"switch"`)
- `dispose()` method removed. Use `onSession` with `reason: "shutdown"` for cleanup

See [docs/custom-tools.md](docs/custom-tools.md) and [examples/custom-tools/](examples/custom-tools/) for the current API.

### SDK Migration

**Type changes:**

- `CustomAgentTool` → `CustomTool`
- `AppMessage` → `AgentMessage`
- `sessionFile` returns `string | undefined` (was `string | null`)
- `model` returns `Model | undefined` (was `Model | null`)
- `Attachment` type removed. Use `ImageContent` from `@mariozechner/pi-ai` instead. Add images directly to message content arrays.

**AgentSession API:**

- `branch(entryIndex: number)` → `branch(entryId: string)`
- `getUserMessagesForBranching()` returns `{ entryId, text }` instead of `{ entryIndex, text }`
- `reset()` → `newSession(options?)` where options has optional `parentSession` for lineage tracking
- `newSession()` and `switchSession()` now return `Promise<boolean>` (false if cancelled by hook)
- New `navigateTree(targetId, options?)` for in-place tree navigation

**Hook integration:**

- New `sendHookMessage(message, triggerTurn?)` for hook message injection

**SessionManager API:**

- Method renames: `saveXXX()` → `appendXXX()` (e.g., `appendMessage`, `appendCompaction`)
- `branchInPlace()` → `branch()`
- `reset()` → `newSession(options?)` with optional `parentSession` for lineage tracking
- `createBranchedSessionFromEntries(entries, index)` → `createBranchedSession(leafId)`
- `SessionHeader.branchedFrom` → `SessionHeader.parentSession`
- `saveCompaction(entry)` → `appendCompaction(summary, firstKeptEntryId, tokensBefore, details?)`
- `getEntries()` now excludes the session header (use `getHeader()` separately)
- `getSessionFile()` returns `string | undefined` (undefined for in-memory sessions)
- New tree methods: `getTree()`, `getBranch()`, `getLeafId()`, `getLeafEntry()`, `getEntry()`, `getChildren()`, `getLabel()`
- New append methods: `appendCustomEntry()`, `appendCustomMessageEntry()`, `appendLabelChange()`
- New branch methods: `branch(entryId)`, `branchWithSummary()`

**ModelRegistry (new):**

`ModelRegistry` is a new class that manages model discovery and API key resolution. It combines built-in models with custom models from `models.json` and resolves API keys via `AuthStorage`.

```typescript
import {
  discoverAuthStorage,
  discoverModels,
} from "@mariozechner/pi-coding-agent";

const authStorage = discoverAuthStorage(); // ~/.pi/agent/auth.json
const modelRegistry = discoverModels(authStorage); // + ~/.pi/agent/models.json

// Get all models (built-in + custom)
const allModels = modelRegistry.getAll();

// Get only models with valid API keys
const available = await modelRegistry.getAvailable();

// Find specific model
const model = modelRegistry.find("anthropic", "claude-sonnet-4-20250514");

// Get API key for a model
const apiKey = await modelRegistry.getApiKey(model);
```

This replaces the old `resolveApiKey` callback pattern. Hooks and custom tools access it via `ctx.modelRegistry`.

**Renamed exports:**

- `messageTransformer` → `convertToLlm`
- `SessionContext` alias `LoadedSession` removed

See [docs/sdk.md](docs/sdk.md) and [examples/sdk/](examples/sdk/) for the current API.

### RPC Migration

**Session commands:**

- `reset` command → `new_session` command with optional `parentSession` field

**Branching commands:**

- `branch` command: `entryIndex` → `entryId`
- `get_branch_messages` response: `entryIndex` → `entryId`

**Type changes:**

- Messages are now `AgentMessage` (was `AppMessage`)
- `prompt` command: `attachments` field replaced with `images` field using `ImageContent` format

**Compaction events:**

- `auto_compaction_start` now includes `reason` field (`"threshold"` or `"overflow"`)
- `auto_compaction_end` now includes `willRetry` field
- `compact` response includes full `CompactionResult` (`summary`, `firstKeptEntryId`, `tokensBefore`, `details`)

See [docs/rpc.md](docs/rpc.md) for the current protocol.

### Structured Compaction

Compaction and branch summarization now use a structured output format:

- Clear sections: Goal, Progress, Key Information, File Operations
- File tracking: `readFiles` and `modifiedFiles` arrays in `details`, accumulated across compactions
- Conversations are serialized to text before summarization to prevent the model from "continuing" them

The `before_compact` and `before_tree` hook events allow custom compaction implementations. See [docs/compaction.md](docs/compaction.md).

### Interactive Mode

**`/tree` command:**

- Navigate the full session tree in-place
- Search by typing, page with ←/→
- Filter modes (Ctrl+O): default → no-tools → user-only → labeled-only → all
- Press `l` to label entries as bookmarks
- Selecting a branch switches context and optionally injects a summary of the abandoned branch

**Entry labels:**

- Bookmark any entry via `/tree` → select → `l`
- Labels appear in tree view and persist as `LabelEntry`

**Theme changes (breaking for custom themes):**

Custom themes must add these new color tokens or they will fail to load:

- `selectedBg`: background for selected/highlighted items in tree selector and other components
- `customMessageBg`: background for hook-injected messages (`CustomMessageEntry`)
- `customMessageText`: text color for hook messages
- `customMessageLabel`: label color for hook messages (the `[customType]` prefix)

Total color count increased from 46 to 50. See [docs/themes.md](docs/themes.md) for the full color list and copy values from the built-in dark/light themes.

**Settings:**

- `enabledModels`: allowlist models in `settings.json` (same format as `--models` CLI)

### Added

- `ctx.ui.setStatus(key, text)` for hooks to display persistent status text in the footer ([#385](https://github.com/badlogic/pi-mono/pull/385) by [@prateekmedia](https://github.com/prateekmedia))
- `ctx.ui.theme` getter for styling status text and other output with theme colors
- `/share` command to upload session as a secret GitHub gist and get a shareable URL via pi.dev ([#380](https://github.com/badlogic/pi-mono/issues/380))
- HTML export now includes a tree visualization sidebar for navigating session branches ([#375](https://github.com/badlogic/pi-mono/issues/375))
- HTML export supports keyboard shortcuts: Ctrl+T to toggle thinking blocks, Ctrl+O to toggle tool outputs
- HTML export supports theme-configurable background colors via optional `export` section in theme JSON ([#387](https://github.com/badlogic/pi-mono/pull/387) by [@mitsuhiko](https://github.com/mitsuhiko))
- HTML export syntax highlighting now uses theme colors and matches TUI rendering
- **Snake game example hook**: Demonstrates `ui.custom()`, `registerCommand()`, and session persistence. See [examples/hooks/snake.ts](examples/hooks/snake.ts).
- **`thinkingText` theme token**: Configurable color for thinking block text. ([#366](https://github.com/badlogic/pi-mono/pull/366) by [@paulbettner](https://github.com/paulbettner))

### Changed

- **Entry IDs**: Session entries now use short 8-character hex IDs instead of full UUIDs
- **API key priority**: `ANTHROPIC_OAUTH_TOKEN` now takes precedence over `ANTHROPIC_API_KEY`
- HTML export template split into separate files (template.html, template.css, template.js) for easier maintenance

### Fixed

- HTML export now properly sanitizes user messages containing HTML tags like `<style>` that could break DOM rendering
- Crash when displaying bash output containing Unicode format characters like U+0600-U+0604 ([#372](https://github.com/badlogic/pi-mono/pull/372) by [@HACKE-RC](https://github.com/HACKE-RC))
- **Footer shows full session stats**: Token usage and cost now include all messages, not just those after compaction. ([#322](https://github.com/badlogic/pi-mono/issues/322))
- **Status messages spam chat log**: Rapidly changing settings (e.g., thinking level via Shift+Tab) would add multiple status lines. Sequential status updates now coalesce into a single line. ([#365](https://github.com/badlogic/pi-mono/pull/365) by [@paulbettner](https://github.com/paulbettner))
- **Toggling thinking blocks during streaming shows nothing**: Pressing Ctrl+T while streaming would hide the current message until streaming completed.
- **Resuming session resets thinking level to off**: Initial model and thinking level were not saved to session file, causing `--resume`/`--continue` to default to `off`. ([#342](https://github.com/badlogic/pi-mono/issues/342) by [@aliou](https://github.com/aliou))
- **Hook `tool_result` event ignores errors from custom tools**: The `tool_result` hook event was never emitted when tools threw errors, and always had `isError: false` for successful executions. Now emits the event with correct `isError` value in both success and error cases. ([#374](https://github.com/badlogic/pi-mono/issues/374) by [@nicobailon](https://github.com/nicobailon))
- **Edit tool fails on Windows due to CRLF line endings**: Files with CRLF line endings now match correctly when LLMs send LF-only text. Line endings are normalized before matching and restored to original style on write. ([#355](https://github.com/badlogic/pi-mono/issues/355) by [@Pratham-Dubey](https://github.com/Pratham-Dubey))
- **Edit tool fails on files with UTF-8 BOM**: Files with UTF-8 BOM marker could cause "text not found" errors since the LLM doesn't include the invisible BOM character. BOM is now stripped before matching and restored on write. ([#394](https://github.com/badlogic/pi-mono/pull/394) by [@prathamdby](https://github.com/prathamdby))
- **Use bash instead of sh on Unix**: Fixed shell commands using `/bin/sh` instead of `/bin/bash` on Unix systems. ([#328](https://github.com/badlogic/pi-mono/pull/328) by [@dnouri](https://github.com/dnouri))
- **OAuth login URL clickable**: Made OAuth login URLs clickable in terminal. ([#349](https://github.com/badlogic/pi-mono/pull/349) by [@Cursivez](https://github.com/Cursivez))
- **Improved error messages**: Better error messages when `apiKey` or `model` are missing. ([#346](https://github.com/badlogic/pi-mono/pull/346) by [@ronyrus](https://github.com/ronyrus))
- **Session file validation**: `findMostRecentSession()` now validates session headers before returning, preventing non-session JSONL files from being loaded
- **Compaction error handling**: `generateSummary()` and `generateTurnPrefixSummary()` now throw on LLM errors instead of returning empty strings
- **Compaction with branched sessions**: Fixed compaction incorrectly including entries from abandoned branches, causing token overflow errors. Compaction now uses `sessionManager.getPath()` to work only on the current branch path, eliminating 80+ lines of duplicate entry collection logic between `prepareCompaction()` and `compact()`
- **enabledModels glob patterns**: `--models` and `enabledModels` now support glob patterns like `github-copilot/*` or `*sonnet*`. Previously, patterns were only matched literally or via substring search. ([#337](https://github.com/badlogic/pi-mono/issues/337))

## [0.30.2] - 2025-12-26

### Changed

- **Consolidated migrations**: Moved auth migration from `AuthStorage.migrateLegacy()` to new `migrations.ts` module.

## [0.30.1] - 2025-12-26

### Fixed

- **Sessions saved to wrong directory**: In v0.30.0, sessions were being saved to `~/.pi/agent/` instead of `~/.pi/agent/sessions/<encoded-cwd>/`, breaking `--resume` and `/resume`. Misplaced sessions are automatically migrated on startup. ([#320](https://github.com/badlogic/pi-mono/issues/320) by [@aliou](https://github.com/aliou))
- **Custom system prompts missing context**: When using a custom system prompt string, project context files (AGENTS.md), skills, date/time, and working directory were not appended. ([#321](https://github.com/badlogic/pi-mono/issues/321))

## [0.30.0] - 2025-12-25

### Breaking Changes

- **SessionManager API**: The second parameter of `create()`, `continueRecent()`, and `list()` changed from `agentDir` to `sessionDir`. When provided, it specifies the session directory directly (no cwd encoding). When omitted, uses default (`~/.pi/agent/sessions/<encoded-cwd>/`). `open()` no longer takes `agentDir`. ([#313](https://github.com/badlogic/pi-mono/pull/313))

### Added

- **`--session-dir` flag**: Use a custom directory for sessions instead of the default `~/.pi/agent/sessions/<encoded-cwd>/`. Works with `-c` (continue) and `-r` (resume) flags. ([#313](https://github.com/badlogic/pi-mono/pull/313) by [@scutifer](https://github.com/scutifer))
- **Reverse model cycling and model selector**: Shift+Ctrl+P cycles models backward, Ctrl+L opens model selector (retaining text in editor). ([#315](https://github.com/badlogic/pi-mono/pull/315) by [@mitsuhiko](https://github.com/mitsuhiko))

## [0.29.1] - 2025-12-25

### Added

- **Automatic custom system prompt loading**: Pi now auto-loads `SYSTEM.md` files to replace the default system prompt. Project-local `.pi/SYSTEM.md` takes precedence over global `~/.pi/agent/SYSTEM.md`. CLI `--system-prompt` flag overrides both. ([#309](https://github.com/badlogic/pi-mono/issues/309))
- **Unified `/settings` command**: New settings menu consolidating thinking level, theme, queue mode, auto-compact, show images, hide thinking, and collapse changelog. Replaces individual `/thinking`, `/queue`, `/theme`, `/autocompact`, and `/show-images` commands. ([#310](https://github.com/badlogic/pi-mono/issues/310))

### Fixed

- **Custom tools/hooks with typebox subpath imports**: Fixed jiti alias for `@sinclair/typebox` to point to package root instead of entry file, allowing imports like `@sinclair/typebox/compiler` to resolve correctly. ([#311](https://github.com/badlogic/pi-mono/issues/311) by [@kim0](https://github.com/kim0))

## [0.29.0] - 2025-12-25

### Breaking Changes

- **Renamed `/clear` to `/new`**: The command to start a fresh session is now `/new`. Hook event reasons `before_clear`/`clear` are now `before_new`/`new`. Merry Christmas [@mitsuhiko](https://github.com/mitsuhiko)! ([#305](https://github.com/badlogic/pi-mono/pull/305))

### Added

- **Auto-space before pasted file paths**: When pasting a file path (starting with `/`, `~`, or `.`) after a word character, a space is automatically prepended. ([#307](https://github.com/badlogic/pi-mono/pull/307) by [@mitsuhiko](https://github.com/mitsuhiko))
- **Word navigation in input fields**: Added Ctrl+Left/Right and Alt+Left/Right for word-by-word cursor movement. ([#306](https://github.com/badlogic/pi-mono/pull/306) by [@kim0](https://github.com/kim0))
- **Full Unicode input**: Input fields now accept Unicode characters beyond ASCII. ([#306](https://github.com/badlogic/pi-mono/pull/306) by [@kim0](https://github.com/kim0))

### Fixed

- **Readline-style Ctrl+W**: Now skips trailing whitespace before deleting the preceding word, matching standard readline behavior. ([#306](https://github.com/badlogic/pi-mono/pull/306) by [@kim0](https://github.com/kim0))

## [0.28.0] - 2025-12-25

### Changed

- **Credential storage refactored**: API keys and OAuth tokens are now stored in `~/.pi/agent/auth.json` instead of `oauth.json` and `settings.json`. Existing credentials are automatically migrated on first run. ([#296](https://github.com/badlogic/pi-mono/issues/296))

- **SDK API changes** ([#296](https://github.com/badlogic/pi-mono/issues/296)):

  - Added `AuthStorage` class for credential management (API keys and OAuth tokens)
  - Added `ModelRegistry` class for model discovery and API key resolution
  - Added `discoverAuthStorage()` and `discoverModels()` discovery functions
  - `createAgentSession()` now accepts `authStorage` and `modelRegistry` options
  - Removed `configureOAuthStorage()`, `defaultGetApiKey()`, `findModel()`, `discoverAvailableModels()`
  - Removed `getApiKey` callback option (use `AuthStorage.setRuntimeApiKey()` for runtime overrides)
  - Use `getModel()` from `@mariozechner/pi-ai` for built-in models, `modelRegistry.find()` for custom models + built-in models
  - See updated [SDK documentation](docs/sdk.md) and [README](README.md)

- **Settings changes**: Removed `apiKeys` from `settings.json`. Use `auth.json` instead. ([#296](https://github.com/badlogic/pi-mono/issues/296))

### Fixed

- **Duplicate skill warnings for symlinks**: Skills loaded via symlinks pointing to the same file are now silently deduplicated instead of showing name collision warnings. ([#304](https://github.com/badlogic/pi-mono/pull/304) by [@mitsuhiko](https://github.com/mitsuhiko))

## [0.27.9] - 2025-12-24

### Fixed

- **Model selector and --list-models with settings.json API keys**: Models with API keys configured in settings.json (but not in environment variables) now properly appear in the /model selector and `--list-models` output. ([#295](https://github.com/badlogic/pi-mono/issues/295))

## [0.27.8] - 2025-12-24

### Fixed

- **API key priority**: OAuth tokens now take priority over settings.json API keys. Previously, an API key in settings.json would trump OAuth, causing users logged in with a plan (unlimited tokens) to be billed via PAYG instead.

## [0.27.7] - 2025-12-24

### Fixed

- **Thinking tag leakage**: Fixed Claude mimicking literal `</thinking>` tags in responses. Unsigned thinking blocks (from aborted streams) are now converted to plain text without `<thinking>` tags. The TUI still displays them as thinking blocks. ([#302](https://github.com/badlogic/pi-mono/pull/302) by [@nicobailon](https://github.com/nicobailon))

## [0.27.6] - 2025-12-24

### Added

- **Compaction hook improvements**: The `before_compact` session event now includes:

  - `previousSummary`: Summary from the last compaction (if any), so hooks can preserve accumulated context
  - `messagesToKeep`: Messages that will be kept after the summary (recent turns), in addition to `messagesToSummarize`
  - `resolveApiKey`: Function to resolve API keys for any model (checks settings, OAuth, env vars)
  - Removed `apiKey` string in favor of `resolveApiKey` for more flexibility

- **SessionManager API cleanup**:
  - Renamed `loadSessionFromEntries()` to `buildSessionContext()` (builds LLM context from entries, handling compaction)
  - Renamed `loadEntries()` to `getEntries()` (returns defensive copy of all session entries)
  - Added `buildSessionContext()` method to SessionManager

## [0.27.5] - 2025-12-24

### Added

- **HTML export syntax highlighting**: Code blocks in markdown and tool outputs (read, write) now have syntax highlighting using highlight.js with theme-aware colors matching the TUI.
- **HTML export improvements**: Render markdown server-side using marked (tables, headings, code blocks, etc.), honor user's chosen theme (light/dark), add image rendering for user messages, and style code blocks with TUI-like language markers. ([@scutifer](https://github.com/scutifer))

### Fixed

- **Ghostty inline images in tmux**: Fixed terminal detection for Ghostty when running inside tmux by checking `GHOSTTY_RESOURCES_DIR` env var. ([#299](https://github.com/badlogic/pi-mono/pull/299) by [@nicobailon](https://github.com/nicobailon))

## [0.27.4] - 2025-12-24

### Fixed

- **Symlinked skill directories**: Skills in symlinked directories (e.g., `~/.pi/agent/skills/my-skills -> /path/to/skills`) are now correctly discovered and loaded.

## [0.27.3] - 2025-12-24

### Added

- **API keys in settings.json**: Store API keys in `~/.pi/agent/settings.json` under the `apiKeys` field (e.g., `{ "apiKeys": { "anthropic": "sk-..." } }`). Settings keys take priority over environment variables. ([#295](https://github.com/badlogic/pi-mono/issues/295))

### Fixed

- **Allow startup without API keys**: Interactive mode no longer throws when no API keys are configured. Users can now start the agent and use `/login` to authenticate. ([#288](https://github.com/badlogic/pi-mono/issues/288))
- **`--system-prompt` file path support**: The `--system-prompt` argument now correctly resolves file paths (like `--append-system-prompt` already did). ([#287](https://github.com/badlogic/pi-mono/pull/287) by [@scutifer](https://github.com/scutifer))

## [0.27.2] - 2025-12-23

### Added

- **Skip conversation restore on branch**: Hooks can return `{ skipConversationRestore: true }` from `before_branch` to create the branched session file without restoring conversation messages. Useful for checkpoint hooks that restore files separately. ([#286](https://github.com/badlogic/pi-mono/pull/286) by [@nicobarray](https://github.com/nicobarray))

## [0.27.1] - 2025-12-22

### Fixed

- **Skill discovery performance**: Skip `node_modules` directories when recursively scanning for skills. Fixes ~60ms startup delay when skill directories contain npm dependencies.

### Added

- **Startup timing instrumentation**: Set `PI_TIMING=1` to see startup performance breakdown (interactive mode only).

## [0.27.0] - 2025-12-22

### Breaking

- **Session hooks API redesign**: Merged `branch` event into `session` event. `BranchEvent`, `BranchEventResult` types and `pi.on("branch", ...)` removed. Use `pi.on("session", ...)` with `reason: "before_branch" | "branch"` instead. `AgentSession.branch()` returns `{ cancelled }` instead of `{ skipped }`. `AgentSession.reset()` and `switchSession()` now return `boolean` (false if cancelled by hook). RPC commands `reset`, `switch_session`, and `branch` now include `cancelled` in response data. ([#278](https://github.com/badlogic/pi-mono/issues/278))

### Added

- **Session lifecycle hooks**: Added `before_*` variants (`before_switch`, `before_clear`, `before_branch`) that fire before actions and can be cancelled with `{ cancel: true }`. Added `shutdown` reason for graceful exit handling. ([#278](https://github.com/badlogic/pi-mono/issues/278))

### Fixed

- **File tab completion display**: File paths no longer get cut off early. Folders now show trailing `/` and removed redundant "directory"/"file" labels to maximize horizontal space. ([#280](https://github.com/badlogic/pi-mono/issues/280))

- **Bash tool visual line truncation**: Fixed bash tool output in collapsed mode to use visual line counting (accounting for line wrapping) instead of logical line counting. Now consistent with bash-execution.ts behavior. Extracted shared `truncateToVisualLines` utility. ([#275](https://github.com/badlogic/pi-mono/issues/275))

## [0.26.1] - 2025-12-22

### Fixed

- **SDK tools respect cwd**: Core tools (bash, read, edit, write, grep, find, ls) now properly use the `cwd` option from `createAgentSession()`. Added tool factory functions (`createBashTool`, `createReadTool`, etc.) for SDK users who specify custom `cwd` with explicit tools. ([#279](https://github.com/badlogic/pi-mono/issues/279))

## [0.26.0] - 2025-12-22

### Added

- **SDK for programmatic usage**: New `createAgentSession()` factory with full control over model, tools, hooks, skills, session persistence, and settings. Philosophy: "omit to discover, provide to override". Includes 12 examples and comprehensive documentation. ([#272](https://github.com/badlogic/pi-mono/issues/272))

- **Project-specific settings**: Settings now load from both `~/.pi/agent/settings.json` (global) and `<cwd>/.pi/settings.json` (project). Project settings override global with deep merge for nested objects. Project settings are read-only (for version control). ([#276](https://github.com/badlogic/pi-mono/pull/276))

- **SettingsManager static factories**: `SettingsManager.create(cwd?, agentDir?)` for file-based settings, `SettingsManager.inMemory(settings?)` for testing. Added `applyOverrides()` for programmatic overrides.

- **SessionManager static factories**: `SessionManager.create()`, `SessionManager.open()`, `SessionManager.continueRecent()`, `SessionManager.inMemory()`, `SessionManager.list()` for flexible session management.

## [0.25.4] - 2025-12-22

### Fixed

- **Syntax highlighting stderr spam**: Fixed cli-highlight logging errors to stderr when markdown contains malformed code fences (e.g., missing newlines around closing backticks). Now validates language identifiers before highlighting and falls back silently to plain text. ([#274](https://github.com/badlogic/pi-mono/issues/274))

## [0.25.3] - 2025-12-21

### Added

- **Gemini 3 preview models**: Added `gemini-3-pro-preview` and `gemini-3-flash-preview` to the google-gemini-cli provider. ([#264](https://github.com/badlogic/pi-mono/pull/264) by [@LukeFost](https://github.com/LukeFost))

- **External editor support**: Press `Ctrl+G` to edit your message in an external editor. Uses `$VISUAL` or `$EDITOR` environment variable. On successful save, the message is replaced; on cancel, the original is kept. ([#266](https://github.com/badlogic/pi-mono/pull/266) by [@aliou](https://github.com/aliou))

- **Process suspension**: Press `Ctrl+Z` to suspend pi and return to the shell. Resume with `fg` as usual. ([#267](https://github.com/badlogic/pi-mono/pull/267) by [@aliou](https://github.com/aliou))

- **Configurable skills directories**: Added granular control over skill sources with `enableCodexUser`, `enableClaudeUser`, `enableClaudeProject`, `enablePiUser`, `enablePiProject` toggles, plus `customDirectories` and `ignoredSkills` settings. ([#269](https://github.com/badlogic/pi-mono/pull/269) by [@nicobailon](https://github.com/nicobailon))

- **Skills CLI filtering**: Added `--skills <patterns>` flag for filtering skills with glob patterns. Also added `includeSkills` setting and glob pattern support for `ignoredSkills`. ([#268](https://github.com/badlogic/pi-mono/issues/268))

## [0.25.2] - 2025-12-21

### Fixed

- **Image shifting in tool output**: Fixed an issue where images in tool output would shift down (due to accumulating spacers) each time the tool output was expanded or collapsed via Ctrl+O.

## [0.25.1] - 2025-12-21

### Fixed

- **Gemini image reading broken**: Fixed the `read` tool returning images causing flaky/broken responses with Gemini models. Images in tool results are now properly formatted per the Gemini API spec.

- **Tab completion for absolute paths**: Fixed tab completion producing `//tmp` instead of `/tmp/`. Also fixed symlinks to directories (like `/tmp`) not getting a trailing slash, which prevented continuing to tab through subdirectories.

## [0.25.0] - 2025-12-20

### Added

- **Interruptible tool execution**: Queuing a message while tools are executing now interrupts the current tool batch. Remaining tools are skipped with an error result, and your queued message is processed immediately. Useful for redirecting the agent mid-task. ([#259](https://github.com/badlogic/pi-mono/pull/259) by [@steipete](https://github.com/steipete))

- **Google Gemini CLI OAuth provider**: Access Gemini 2.0/2.5 models for free via Google Cloud Code Assist. Login with `/login` and select "Google Gemini CLI". Uses your Google account with rate limits.

- **Google Antigravity OAuth provider**: Access Gemini 3, Claude (sonnet/opus thinking models), and GPT-OSS models for free via Google's Antigravity sandbox. Login with `/login` and select "Antigravity". Uses your Google account with rate limits.

### Changed

- **Model selector respects --models scope**: The `/model` command now only shows models specified via `--models` flag when that flag is used, instead of showing all available models. This prevents accidentally selecting models from unintended providers. ([#255](https://github.com/badlogic/pi-mono/issues/255))

### Fixed

- **Connection errors not retried**: Added "connection error" to the list of retryable errors so Anthropic connection drops trigger auto-retry instead of silently failing. ([#252](https://github.com/badlogic/pi-mono/issues/252))

- **Thinking level not clamped on model switch**: Fixed TUI showing xhigh thinking level after switching to a model that doesn't support it. Thinking level is now automatically clamped to model capabilities. ([#253](https://github.com/badlogic/pi-mono/issues/253))

- **Cross-model thinking handoff**: Fixed error when switching between models with different thinking signature formats (e.g., GPT-OSS to Claude thinking models via Antigravity). Thinking blocks without signatures are now converted to text with `<thinking>` delimiters.

## [0.24.5] - 2025-12-20

### Fixed

- **Input buffering in iTerm2**: Fixed Ctrl+C, Ctrl+D, and other keys requiring multiple presses in iTerm2. The cell size query response parser was incorrectly holding back keyboard input.

## [0.24.4] - 2025-12-20

### Fixed

- **Arrow keys and Enter in selector components**: Fixed arrow keys and Enter not working in model selector, session selector, OAuth selector, and other selector components when Caps Lock or Num Lock is enabled. ([#243](https://github.com/badlogic/pi-mono/issues/243))

## [0.24.3] - 2025-12-19

### Fixed

- **Footer overflow on narrow terminals**: Fixed footer path display exceeding terminal width when resizing to very narrow widths, causing rendering crashes. /arminsayshi

## [0.24.2] - 2025-12-20

### Fixed

- **More Kitty keyboard protocol fixes**: Fixed Backspace, Enter, Home, End, and Delete keys not working with Caps Lock enabled. The initial fix in 0.24.1 missed several key handlers that were still using raw byte detection. Now all key handlers use the helper functions that properly mask out lock key bits. ([#243](https://github.com/badlogic/pi-mono/issues/243))

## [0.24.1] - 2025-12-19

### Added

- **OAuth and model config exports**: Scripts using `AgentSession` directly can now import `getAvailableModels`, `getApiKeyForModel`, `findModel`, `login`, `logout`, and `getOAuthProviders` from `@mariozechner/pi-coding-agent` to reuse OAuth token storage and model resolution. ([#245](https://github.com/badlogic/pi-mono/issues/245))

- **xhigh thinking level for gpt-5.2 models**: The thinking level selector and shift+tab cycling now show xhigh option for gpt-5.2 and gpt-5.2-codex models (in addition to gpt-5.1-codex-max). ([#236](https://github.com/badlogic/pi-mono/pull/236) by [@theBucky](https://github.com/theBucky))

### Fixed

- **Hooks wrap custom tools**: Custom tools are now executed through the hook wrapper, so `tool_call`/`tool_result` hooks can observe, block, and modify custom tool executions (consistent with hook type docs). ([#248](https://github.com/badlogic/pi-mono/pull/248) by [@nicobailon](https://github.com/nicobailon))

- **Hook onUpdate callback forwarding**: The `onUpdate` callback is now correctly forwarded through the hook wrapper, fixing custom tool progress updates. ([#238](https://github.com/badlogic/pi-mono/pull/238) by [@nicobailon](https://github.com/nicobailon))

- **Terminal cleanup on Ctrl+C in session selector**: Fixed terminal not being properly restored when pressing Ctrl+C in the session selector. ([#247](https://github.com/badlogic/pi-mono/pull/247) by [@aliou](https://github.com/aliou))

- **OpenRouter models with colons in IDs**: Fixed parsing of OpenRouter model IDs that contain colons (e.g., `openrouter:meta-llama/llama-4-scout:free`). ([#242](https://github.com/badlogic/pi-mono/pull/242) by [@aliou](https://github.com/aliou))

- **Global AGENTS.md loaded twice**: Fixed global AGENTS.md being loaded twice when present in both `~/.pi/agent/` and the current directory. ([#239](https://github.com/badlogic/pi-mono/pull/239) by [@aliou](https://github.com/aliou))

- **Kitty keyboard protocol on Linux**: Fixed keyboard input not working in Ghostty on Linux when Num Lock is enabled. The Kitty protocol includes Caps Lock and Num Lock state in modifier values, which broke key detection. Now correctly masks out lock key bits when matching keyboard shortcuts. ([#243](https://github.com/badlogic/pi-mono/issues/243))

- **Emoji deletion and cursor movement**: Backspace, Delete, and arrow keys now correctly handle multi-codepoint characters like emojis. Previously, deleting an emoji would leave partial bytes, corrupting the editor state. ([#240](https://github.com/badlogic/pi-mono/issues/240))

## [0.24.0] - 2025-12-19

### Added

- **Subagent orchestration example**: Added comprehensive custom tool example for spawning and orchestrating sub-agents with isolated context windows. Includes scout/planner/reviewer/worker agents and workflow commands for multi-agent pipelines. ([#215](https://github.com/badlogic/pi-mono/pull/215) by [@nicobailon](https://github.com/nicobailon))

- **`getMarkdownTheme()` export**: Custom tools can now import `getMarkdownTheme()` from `@mariozechner/pi-coding-agent` to use the same markdown styling as the main UI.

- **`pi.exec()` signal and timeout support**: Custom tools and hooks can now pass `{ signal, timeout }` options to `pi.exec()` for cancellation and timeout handling. The result includes a `killed` flag when the process was terminated.

- **Kitty keyboard protocol support**: Shift+Enter, Alt+Enter, Shift+Tab, Ctrl+D, and all Ctrl+key combinations now work in Ghostty, Kitty, WezTerm, and other modern terminals. ([#225](https://github.com/badlogic/pi-mono/pull/225) by [@kim0](https://github.com/kim0))

- **Dynamic API key refresh**: OAuth tokens (GitHub Copilot, Anthropic OAuth) are now refreshed before each LLM call, preventing failures in long-running agent loops where tokens expire mid-session. ([#223](https://github.com/badlogic/pi-mono/pull/223) by [@kim0](https://github.com/kim0))

- **`/hotkeys` command**: Shows all keyboard shortcuts in a formatted table.

- **Markdown table borders**: Tables now render with proper top and bottom borders.

### Changed

- **Subagent example improvements**: Parallel mode now streams updates from all tasks. Chain mode shows all completed steps during streaming. Expanded view uses proper markdown rendering with syntax highlighting. Usage footer shows turn count.

- **Skills standard compliance**: Skills now adhere to the [Agent Skills standard](https://agentskills.io/specification). Validates name (must match parent directory, lowercase, max 64 chars), description (required, max 1024 chars), and frontmatter fields. Warns on violations but remains lenient. Prompt format changed to XML structure. Removed `{baseDir}` placeholder in favor of relative paths. ([#231](https://github.com/badlogic/pi-mono/issues/231))

### Fixed

- **JSON mode stdout flush**: Fixed race condition where `pi --mode json` could exit before all output was written to stdout, causing consumers to miss final events.

- **Symlinked tools, hooks, and slash commands**: Discovery now correctly follows symlinks when scanning for custom tools, hooks, and slash commands. ([#219](https://github.com/badlogic/pi-mono/pull/219), [#232](https://github.com/badlogic/pi-mono/pull/232) by [@aliou](https://github.com/aliou))

### Breaking Changes

- **Custom tools now require `index.ts` entry point**: Auto-discovered custom tools must be in a subdirectory with an `index.ts` file. The old pattern `~/.pi/agent/tools/mytool.ts` must become `~/.pi/agent/tools/mytool/index.ts`. This allows multi-file tools to import helper modules. Explicit paths via `--tool` or `settings.json` still work with any `.ts` file.

- **Hook `tool_result` event restructured**: The `ToolResultEvent` now exposes full tool result data instead of just text. ([#233](https://github.com/badlogic/pi-mono/pull/233))
  - Removed: `result: string` field
  - Added: `content: (TextContent | ImageContent)[]` - full content array
  - Added: `details: unknown` - tool-specific details (typed per tool via discriminated union on `toolName`)
  - `ToolResultEventResult.result` renamed to `ToolResultEventResult.text` (removed), use `content` instead
  - Hook handlers returning `{ result: "..." }` must change to `{ content: [{ type: "text", text: "..." }] }`
  - Built-in tool details types exported: `BashToolDetails`, `ReadToolDetails`, `GrepToolDetails`, `FindToolDetails`, `LsToolDetails`, `TruncationResult`
  - Type guards exported for narrowing: `isBashToolResult`, `isReadToolResult`, `isEditToolResult`, `isWriteToolResult`, `isGrepToolResult`, `isFindToolResult`, `isLsToolResult`

## [0.23.4] - 2025-12-18

### Added

- **Syntax highlighting**: Added syntax highlighting for markdown code blocks, read tool output, and write tool content. Uses cli-highlight with theme-aware color mapping and VS Code-style syntax colors. ([#214](https://github.com/badlogic/pi-mono/pull/214) by [@svkozak](https://github.com/svkozak))

- **Intra-line diff highlighting**: Edit tool now shows word-level changes with inverse highlighting when a single line is modified. Multi-line changes show all removed lines first, then all added lines.

### Fixed

- **Gemini tool result format**: Fixed tool result format for Gemini 3 Flash Preview which strictly requires `{ output: value }` for success and `{ error: value }` for errors. Previous format using `{ result, isError }` was rejected by newer Gemini models. ([#213](https://github.com/badlogic/pi-mono/issues/213), [#220](https://github.com/badlogic/pi-mono/pull/220))

- **Google baseUrl configuration**: Google provider now respects `baseUrl` configuration for custom endpoints or API proxies. ([#216](https://github.com/badlogic/pi-mono/issues/216), [#221](https://github.com/badlogic/pi-mono/pull/221) by [@theBucky](https://github.com/theBucky))

- **Google provider FinishReason**: Added handling for new `IMAGE_RECITATION` and `IMAGE_OTHER` finish reasons. Upgraded @google/genai to 1.34.0.

## [0.23.3] - 2025-12-17

### Fixed

- Check for compaction before submitting user prompt, not just after agent turn ends. This catches cases where user aborts mid-response and context is already near the limit.

### Changed

- Improved system prompt documentation section with clearer pointers to specific doc files for custom models, themes, skills, hooks, custom tools, and RPC.

- Cleaned up documentation:

  - `theme.md`: Added missing color tokens (`thinkingXhigh`, `bashMode`)
  - `skills.md`: Rewrote with better framing and examples
  - `hooks.md`: Fixed timeout/error handling docs, added import aliases section
  - `custom-tools.md`: Added intro with use cases and comparison table
  - `rpc.md`: Added missing `hook_error` event documentation
  - `README.md`: Complete settings table, condensed philosophy section, standardized OAuth docs

- Hooks loader now supports same import aliases as custom tools (`@sinclair/typebox`, `@mariozechner/pi-ai`, `@mariozechner/pi-tui`, `@mariozechner/pi-coding-agent`).

### Breaking Changes

- **Hooks**: `turn_end` event's `toolResults` type changed from `AppMessage[]` to `ToolResultMessage[]`. If you have hooks that handle `turn_end` events and explicitly type the results, update your type annotations.

## [0.23.2] - 2025-12-17

### Fixed

- Fixed Claude models via GitHub Copilot re-answering all previous prompts in multi-turn conversations. The issue was that assistant message content was sent as an array instead of a string, which Copilot's Claude adapter misinterpreted. Also added missing `Openai-Intent: conversation-edits` header and fixed `X-Initiator` logic to check for any assistant/tool message in history. ([#209](https://github.com/badlogic/pi-mono/issues/209))

- Detect image MIME type via file magic (read tool and `@file` attachments), not filename extension.

- Fixed markdown tables overflowing terminal width. Tables now wrap cell contents to fit available width instead of breaking borders mid-row. ([#206](https://github.com/badlogic/pi-mono/pull/206) by [@kim0](https://github.com/kim0))

## [0.23.1] - 2025-12-17

### Fixed

- Fixed TUI performance regression caused by Box component lacking render caching. Built-in tools now use Text directly (like v0.22.5), and Box has proper caching for custom tool rendering.

- Fixed custom tools failing to load from `~/.pi/agent/tools/` when pi is installed globally. Module imports (`@sinclair/typebox`, `@mariozechner/pi-tui`, `@mariozechner/pi-ai`) are now resolved via aliases.

## [0.23.0] - 2025-12-17

### Added

- **Custom tools**: Extend pi with custom tools written in TypeScript. Tools can provide custom TUI rendering, interact with users via `pi.ui` (select, confirm, input, notify), and maintain state across sessions via `onSession` callback. See [docs/custom-tools.md](docs/custom-tools.md) and [examples/custom-tools/](examples/custom-tools/). ([#190](https://github.com/badlogic/pi-mono/issues/190))

- **Hook and tool examples**: Added `examples/hooks/` and `examples/custom-tools/` with working examples. Examples are now bundled in npm and binary releases.

### Breaking Changes

- **Hooks**: Replaced `session_start` and `session_switch` events with unified `session` event. Use `event.reason` (`"start" | "switch" | "clear"`) to distinguish. Event now includes `entries` array for state reconstruction.

## [0.22.5] - 2025-12-17

### Fixed

- Fixed `--session` flag not saving sessions in print mode (`-p`). The session manager was never receiving events because no subscriber was attached.

## [0.22.4] - 2025-12-17

### Added

- `--list-models [search]` CLI flag to list available models with optional fuzzy search. Shows provider, model ID, context window, max output, thinking support, and image support. Only lists models with configured API keys. ([#203](https://github.com/badlogic/pi-mono/issues/203))

### Fixed

- Fixed tool execution showing green (success) background while still running. Now correctly shows gray (pending) background until the tool completes.

## [0.22.3] - 2025-12-16

### Added

- **Streaming bash output**: Bash tool now streams output in real-time during execution. The TUI displays live progress with the last 5 lines visible (expandable with ctrl+o). ([#44](https://github.com/badlogic/pi-mono/issues/44))

### Changed

- **Tool output display**: When collapsed, tool output now shows the last N lines instead of the first N lines, making streaming output more useful.

- Updated `@mariozechner/pi-ai` with X-Initiator header support for GitHub Copilot, ensuring agent calls are not deducted from quota. ([#200](https://github.com/badlogic/pi-mono/pull/200) by [@kim0](https://github.com/kim0))

### Fixed

- Fixed editor text being cleared during compaction. Text typed while compaction is running is now preserved. ([#179](https://github.com/badlogic/pi-mono/issues/179))
- Improved RGB to 256-color mapping for terminals without truecolor support. Now correctly uses grayscale ramp for neutral colors and preserves semantic tints (green for success, red for error, blue for pending) instead of mapping everything to wrong cube colors.
- `/think off` now actually disables thinking for all providers. Previously, providers like Gemini with "dynamic thinking" enabled by default would still use thinking even when turned off. ([#180](https://github.com/badlogic/pi-mono/pull/180) by [@markusylisiurunen](https://github.com/markusylisiurunen))

## [0.22.2] - 2025-12-15

### Changed

- Updated `@mariozechner/pi-ai` with interleaved thinking enabled by default for Anthropic Claude 4 models.

## [0.22.1] - 2025-12-15

_Dedicated to Peter's shoulder ([@steipete](https://twitter.com/steipete))_

### Changed

- Updated `@mariozechner/pi-ai` with interleaved thinking support for Anthropic models.

## [0.22.0] - 2025-12-15

### Added

- **GitHub Copilot support**: Use GitHub Copilot models via OAuth login (`/login` -> "GitHub Copilot"). Supports both github.com and GitHub Enterprise. Models are sourced from models.dev and include Claude, GPT, Gemini, Grok, and more. All models are automatically enabled after login. ([#191](https://github.com/badlogic/pi-mono/pull/191) by [@cau1k](https://github.com/cau1k))

### Fixed

- Model selector fuzzy search now matches against provider name (not just model ID) and supports space-separated tokens where all tokens must match

## [0.21.0] - 2025-12-14

### Added

- **Inline image rendering**: Terminals supporting Kitty graphics protocol (Kitty, Ghostty, WezTerm) or iTerm2 inline images now render images inline in tool output. Aspect ratio is preserved by querying terminal cell dimensions on startup. Toggle with `/show-images` command or `terminal.showImages` setting. Falls back to text placeholder on unsupported terminals or when disabled. ([#177](https://github.com/badlogic/pi-mono/pull/177) by [@nicobailon](https://github.com/nicobailon))

- **Gemini 3 Pro thinking levels**: Thinking level selector now works with Gemini 3 Pro models. Minimal/low map to Google's LOW, medium/high map to Google's HIGH. ([#176](https://github.com/badlogic/pi-mono/pull/176) by [@markusylisiurunen](https://github.com/markusylisiurunen))

### Fixed

- Fixed read tool failing on macOS screenshot filenames due to Unicode Narrow No-Break Space (U+202F) in timestamp. Added fallback to try macOS variant paths and consolidated duplicate expandPath functions into shared path-utils.ts. ([#181](https://github.com/badlogic/pi-mono/pull/181) by [@nicobailon](https://github.com/nicobailon))

- Fixed double blank lines rendering after markdown code blocks ([#173](https://github.com/badlogic/pi-mono/pull/173) by [@markusylisiurunen](https://github.com/markusylisiurunen))

## [0.20.1] - 2025-12-13

### Added

- **Exported skills API**: `loadSkillsFromDir`, `formatSkillsForPrompt`, and related types are now exported for use by other packages (e.g., mom).

## [0.20.0] - 2025-12-13

### Breaking Changes

- **Pi skills now use `SKILL.md` convention**: Pi skills must now be named `SKILL.md` inside a directory, matching Codex CLI format. Previously any `*.md` file was treated as a skill. Migrate by renaming `~/.pi/agent/skills/foo.md` to `~/.pi/agent/skills/foo/SKILL.md`.

### Added

- Display loaded skills on startup in interactive mode

## [0.19.1] - 2025-12-12

### Fixed

- Documentation: Added skills system documentation to README (setup, usage, CLI flags, settings)

## [0.19.0] - 2025-12-12

### Added

- **Skills system**: Auto-discover and load instruction files on-demand. Supports Claude Code (`~/.claude/skills/*/SKILL.md`), Codex CLI (`~/.codex/skills/`), and Pi-native formats (`~/.pi/agent/skills/`, `.pi/skills/`). Skills are listed in system prompt with descriptions, agent loads them via read tool when needed. Supports `{baseDir}` placeholder. Disable with `--no-skills` or `skills.enabled: false` in settings. ([#169](https://github.com/badlogic/pi-mono/issues/169))

- **Version flag**: Added `--version` / `-v` flag to display the current version and exit. ([#170](https://github.com/badlogic/pi-mono/pull/170))

## [0.18.2] - 2025-12-11

### Added

- **Auto-retry on transient errors**: Automatically retries requests when providers return overloaded, rate limit, or server errors (429, 500, 502, 503, 504). Uses exponential backoff (2s, 4s, 8s). Shows retry status in TUI with option to cancel via Escape. Configurable in `settings.json` via `retry.enabled`, `retry.maxRetries`, `retry.baseDelayMs`. RPC mode emits `auto_retry_start` and `auto_retry_end` events. ([#157](https://github.com/badlogic/pi-mono/issues/157))

- **HTML export line numbers**: Read tool calls in HTML exports now display line number ranges (e.g., `file.txt:10-20`) when offset/limit parameters are used, matching the TUI display format. Line numbers appear in yellow color for better visibility. ([#166](https://github.com/badlogic/pi-mono/issues/166))

### Fixed

- **Branch selector now works with single message**: Previously the branch selector would not open when there was only one user message. Now it correctly allows branching from any message, including the first one. This is needed for checkpoint hooks to restore state from before the first message. ([#163](https://github.com/badlogic/pi-mono/issues/163))

- **In-memory branching for `--no-session` mode**: Branching now works correctly in `--no-session` mode without creating any session files. The conversation is truncated in memory.

- **Git branch indicator now works in subdirectories**: The footer's git branch detection now walks up the directory hierarchy to find the git root, so it works when running pi from a subdirectory of a repository. ([#156](https://github.com/badlogic/pi-mono/issues/156))

## [0.18.1] - 2025-12-10

### Added

- **Mistral provider**: Added support for Mistral AI models. Set `MISTRAL_API_KEY` environment variable to use.

### Fixed

- Fixed print mode (`-p`) not exiting after output when custom themes are present (theme watcher now properly stops in print mode) ([#161](https://github.com/badlogic/pi-mono/issues/161))

## [0.18.0] - 2025-12-10

### Added

- **Hooks system**: TypeScript modules that extend agent behavior by subscribing to lifecycle events. Hooks can intercept tool calls, prompt for confirmation, modify results, and inject messages from external sources. Auto-discovered from `~/.pi/agent/hooks/*.ts` and `.pi/hooks/*.ts`. Thanks to [@nicobailon](https://github.com/nicobailon) for the collaboration on the design and implementation. ([#145](https://github.com/badlogic/pi-mono/issues/145), supersedes [#158](https://github.com/badlogic/pi-mono/pull/158))

- **`pi.send()` API**: Hooks can inject messages into the agent session from external sources (file watchers, webhooks, CI systems). If streaming, messages are queued; otherwise a new agent loop starts immediately.

- **`--hook <path>` CLI flag**: Load hook files directly for testing without modifying settings.

- **Hook events**: `session_start`, `session_switch`, `agent_start`, `agent_end`, `turn_start`, `turn_end`, `tool_call` (can block), `tool_result` (can modify), `branch`.

- **Hook UI primitives**: `ctx.ui.select()`, `ctx.ui.confirm()`, `ctx.ui.input()`, `ctx.ui.notify()` for interactive prompts from hooks.

- **Hooks documentation**: Full API reference at `docs/hooks.md`, shipped with npm package.

## [0.17.0] - 2025-12-09

### Changed

- **Simplified compaction flow**: Removed proactive compaction (aborting mid-turn when threshold approached). Compaction now triggers in two cases only: (1) overflow error from LLM, which compacts and auto-retries, or (2) threshold crossed after a successful turn, which compacts without retry.

- **Compaction retry uses `Agent.continue()`**: Auto-retry after overflow now uses the new `continue()` API instead of re-sending the user message, preserving exact context state.

- **Merged turn prefix summary**: When a turn is split during compaction, the turn prefix summary is now merged into the main history summary instead of being stored separately.

### Added

- **`isCompacting` property on AgentSession**: Check if auto-compaction is currently running.

- **Session compaction indicator**: When resuming a compacted session, displays "Session compacted N times" status message.

### Fixed

- **Block input during compaction**: User input is now blocked while auto-compaction is running to prevent race conditions.

- **Skip error messages in usage calculation**: Context size estimation now skips both aborted and error messages, as neither have valid usage data.

## [0.16.0] - 2025-12-09

### Breaking Changes

- **New RPC protocol**: The RPC mode (`--mode rpc`) has been completely redesigned with a new JSON protocol. The old protocol is no longer supported. See [`docs/rpc.md`](docs/rpc.md) for the new protocol documentation and [`test/rpc-example.ts`](test/rpc-example.ts) for a working example. Includes `RpcClient` TypeScript class for easy integration. ([#91](https://github.com/badlogic/pi-mono/issues/91))

### Changed

- **README restructured**: Reorganized documentation from 30+ flat sections into 10 logical groups. Converted verbose subsections to scannable tables. Consolidated philosophy sections. Reduced size by ~60% while preserving all information.

## [0.15.0] - 2025-12-09

### Changed

- **Major code refactoring**: Restructured codebase for better maintainability and separation of concerns. Moved files into organized directories (`core/`, `modes/`, `utils/`, `cli/`). Extracted `AgentSession` class as central session management abstraction. Split `main.ts` and `tui-renderer.ts` into focused modules. See `DEVELOPMENT.md` for the new code map. ([#153](https://github.com/badlogic/pi-mono/issues/153))

## [0.14.2] - 2025-12-08

### Added

- `/debug` command now includes agent messages as JSONL in the output

### Fixed

- Fix crash when bash command outputs binary data (e.g., `curl` downloading a video file)

## [0.14.1] - 2025-12-08

### Fixed

- Fix build errors with tsgo 7.0.0-dev.20251208.1 by properly importing `ReasoningEffort` type

## [0.14.0] - 2025-12-08

### Breaking Changes

- **Custom themes require new color tokens**: Themes must now include `thinkingXhigh` and `bashMode` color tokens. The theme loader provides helpful error messages listing missing tokens. See built-in themes (dark.json, light.json) for reference values.

### Added

- **OpenAI compatibility overrides in models.json**: Custom models using `openai-completions` API can now specify a `compat` object to override provider quirks (`supportsStore`, `supportsDeveloperRole`, `supportsReasoningEffort`, `maxTokensField`). Useful for LiteLLM, custom proxies, and other non-standard endpoints. ([#133](https://github.com/badlogic/pi-mono/issues/133), thanks @fink-andreas for the initial idea and PR)

- **xhigh thinking level**: Added `xhigh` thinking level for OpenAI codex-max models. Cycle through thinking levels with Shift+Tab; `xhigh` appears only when using a codex-max model. ([#143](https://github.com/badlogic/pi-mono/issues/143))

- **Collapse changelog setting**: Add `"collapseChangelog": true` to `~/.pi/agent/settings.json` to show a condensed "Updated to vX.Y.Z" message instead of the full changelog after updates. Use `/changelog` to view the full changelog. ([#148](https://github.com/badlogic/pi-mono/issues/148))

- **Bash mode**: Execute shell commands directly from the editor by prefixing with `!` (e.g., `!ls -la`). Output streams in real-time, is added to the LLM context, and persists in session history. Supports multiline commands, cancellation (Escape), truncation for large outputs, and preview/expand toggle (Ctrl+O). Also available in RPC mode via `{"type":"bash","command":"..."}`. ([#112](https://github.com/badlogic/pi-mono/pull/112), original implementation by [@markusylisiurunen](https://github.com/markusylisiurunen))

## [0.13.2] - 2025-12-07

### Changed

- **Tool output truncation**: All tools now enforce consistent truncation limits with actionable notices for the LLM. ([#134](https://github.com/badlogic/pi-mono/issues/134))
  - **Limits**: 2000 lines OR 50KB (whichever hits first), never partial lines
  - **read**: Shows `[Showing lines X-Y of Z. Use offset=N to continue]`. If first line exceeds 50KB, suggests bash command
  - **bash**: Tail truncation with temp file. Shows `[Showing lines X-Y of Z. Full output: /tmp/...]`
  - **grep**: Pre-truncates match lines to 500 chars. Shows match limit and line truncation notices
  - **find/ls**: Shows result/entry limit notices
  - TUI displays truncation warnings in yellow at bottom of tool output (visible even when collapsed)

## [0.13.1] - 2025-12-06

### Added

- **Flexible Windows shell configuration**: The bash tool now supports multiple shell sources beyond Git Bash. Resolution order: (1) custom `shellPath` in settings.json, (2) Git Bash in standard locations, (3) any bash.exe on PATH. This enables Cygwin, MSYS2, and other bash environments. Configure with `~/.pi/agent/settings.json`: `{"shellPath": "C:\\cygwin64\\bin\\bash.exe"}`.

### Fixed

- **Windows binary detection**: Fixed Bun compiled binary detection on Windows by checking for URL-encoded `%7EBUN` in addition to `$bunfs` and `~BUN` in `import.meta.url`. This ensures the binary correctly locates supporting files (package.json, themes, etc.) next to the executable.

## [0.12.15] - 2025-12-06

### Fixed

- **Editor crash with emojis/CJK characters**: Fixed crash when pasting or typing text containing wide characters (emojis like ✅, CJK characters) that caused line width to exceed terminal width. The editor now uses grapheme-aware text wrapping with proper visible width calculation.

## [0.12.14] - 2025-12-06

### Added

- **Double-Escape Branch Shortcut**: Press Escape twice with an empty editor to quickly open the `/branch` selector for conversation branching.

## [0.12.13] - 2025-12-05

### Changed

- **Faster startup**: Version check now runs in parallel with TUI initialization instead of blocking startup for up to 1 second. Update notifications appear in chat when the check completes.

## [0.12.12] - 2025-12-05

### Changed

- **Footer display**: Token counts now use M suffix for millions (e.g., `10.2M` instead of `10184k`). Context display shortened from `61.3% of 200k` to `61.3%/200k`.

### Fixed

- **Multi-key sequences in inputs**: Inputs like model search now handle multi-key sequences identically to the main prompt editor. ([#122](https://github.com/badlogic/pi-mono/pull/122) by [@markusylisiurunen](https://github.com/markusylisiurunen))
- **Line wrapping escape codes**: Fixed underline style bleeding into padding when wrapping long URLs. ANSI codes now attach to the correct content, and line-end resets only turn off underline (preserving background colors). ([#109](https://github.com/badlogic/pi-mono/issues/109))

### Added

- **Fuzzy search models and sessions**: Implemented a simple fuzzy search for models and sessions (e.g., `codexmax` now finds `gpt-5.1-codex-max`). ([#122](https://github.com/badlogic/pi-mono/pull/122) by [@markusylisiurunen](https://github.com/markusylisiurunen))
- **Prompt History Navigation**: Browse previously submitted prompts using Up/Down arrow keys when the editor is empty. Press Up to cycle through older prompts, Down to return to newer ones or clear the editor. Similar to shell history and Claude Code's prompt history feature. History is session-scoped and stores up to 100 entries. ([#121](https://github.com/badlogic/pi-mono/pull/121) by [@nicobailon](https://github.com/nicobailon))
- **`/resume` Command**: Switch to a different session mid-conversation. Opens an interactive selector showing all available sessions. Equivalent to the `--resume` CLI flag but can be used without restarting the agent. ([#117](https://github.com/badlogic/pi-mono/pull/117) by [@hewliyang](https://github.com/hewliyang))

## [0.12.11] - 2025-12-05

### Changed

- **Compaction UI**: Simplified collapsed compaction indicator to show warning-colored text with token count instead of styled banner. Removed redundant success message after compaction. ([#108](https://github.com/badlogic/pi-mono/issues/108))

### Fixed

- **Print mode error handling**: `-p` flag now outputs error messages and exits with code 1 when requests fail, instead of silently producing no output.
- **Branch selector crash**: Fixed TUI crash when user messages contained Unicode characters (like `✔` or `›`) that caused line width to exceed terminal width. Now uses proper `truncateToWidth` instead of `substring`.
- **Bash output escape sequences**: Fixed incomplete stripping of terminal escape sequences in bash tool output. `stripAnsi` misses some sequences like standalone String Terminator (`ESC \`), which could cause rendering issues when displaying captured TUI output.
- **Footer overflow crash**: Fixed TUI crash when terminal width is too narrow for the footer stats line. The footer now truncates gracefully instead of overflowing.

### Added

- **`authHeader` option in models.json**: Custom providers can set `"authHeader": true` to automatically add `Authorization: Bearer <apiKey>` header. Useful for providers that require explicit auth headers. ([#81](https://github.com/badlogic/pi-mono/issues/81))
- **`--append-system-prompt` Flag**: Append additional text or file contents to the system prompt. Supports both inline text and file paths. Complements `--system-prompt` for layering custom instructions without replacing the base system prompt. ([#114](https://github.com/badlogic/pi-mono/pull/114) by [@markusylisiurunen](https://github.com/markusylisiurunen))
- **Thinking Block Toggle**: Added `Ctrl+T` shortcut to toggle visibility of LLM thinking blocks. When toggled off, shows a static "Thinking..." label instead of full content. Useful for reducing visual clutter during long conversations. ([#113](https://github.com/badlogic/pi-mono/pull/113) by [@markusylisiurunen](https://github.com/markusylisiurunen))

## [0.12.10] - 2025-12-04

### Added

- Added `gpt-5.1-codex-max` model support

## [0.12.9] - 2025-12-04

### Added

- **`/copy` Command**: Copy the last agent message to clipboard. Works cross-platform (macOS, Windows, Linux). Useful for extracting text from rendered Markdown output. ([#105](https://github.com/badlogic/pi-mono/pull/105) by [@markusylisiurunen](https://github.com/markusylisiurunen))

## [0.12.8] - 2025-12-04

- Fix: Use CTRL+O consistently for compaction expand shortcut (not CMD+O on Mac)

## [0.12.7] - 2025-12-04

### Added

- **Context Compaction**: Long sessions can now be compacted to reduce context usage while preserving recent conversation history. ([#92](https://github.com/badlogic/pi-mono/issues/92), [docs](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/README.md#context-compaction))
  - `/compact [instructions]`: Manually compact context with optional custom instructions for the summary
  - `/autocompact`: Toggle automatic compaction when context exceeds threshold
  - Compaction summarizes older messages while keeping recent messages (default 20k tokens) verbatim
  - Auto-compaction triggers when context reaches `contextWindow - reserveTokens` (default 16k reserve)
  - Compacted sessions show a collapsible summary in the TUI (toggle with `o` key)
  - HTML exports include compaction summaries as collapsible sections
  - RPC mode supports `{"type":"compact"}` command and auto-compaction (emits compaction events)
- **Branch Source Tracking**: Branched sessions now store `branchedFrom` in the session header, containing the path to the original session file. Useful for tracing session lineage.

## [0.12.5] - 2025-12-03

### Added

- **Forking/Rebranding Support**: All branding (app name, config directory, environment variable names) is now configurable via `piConfig` in `package.json`. Forks can change `piConfig.name` and `piConfig.configDir` to rebrand the CLI without code changes. Affects CLI banner, help text, config paths, and error messages. ([#95](https://github.com/badlogic/pi-mono/pull/95))

### Fixed

- **Bun Binary Detection**: Fixed Bun compiled binary failing to start after Bun updated its virtual filesystem path format from `%7EBUN` to `$bunfs`. ([#95](https://github.com/badlogic/pi-mono/pull/95))

## [0.12.4] - 2025-12-02

### Added

- **RPC Termination Safeguard**: When running as an RPC worker (stdin pipe detected), the CLI now exits immediately if the parent process terminates unexpectedly. Prevents orphaned RPC workers from persisting indefinitely and consuming system resources.

## [0.12.3] - 2025-12-02

### Fixed

- **Rate limit handling**: Anthropic rate limit errors now trigger automatic retry with exponential backoff (base 10s, max 5 retries). Previously these errors would abort the request immediately.
- **Usage tracking during retries**: Retried requests now correctly accumulate token usage from all attempts, not just the final successful one. Fixes artificially low token counts when requests were retried.

## [0.12.2] - 2025-12-02

### Changed

- Removed support for gpt-4.5-preview and o3 models (not yet available)

## [0.12.1] - 2025-12-02

### Added

- **Models**: Added support for OpenAI's new models:
  - `gpt-4.1` (128K context)
  - `gpt-4.1-mini` (128K context)
  - `gpt-4.1-nano` (128K context)
  - `o3` (200K context, reasoning model)
  - `o4-mini` (200K context, reasoning model)

## [0.12.0] - 2025-12-02

### Added

- **`-p, --print` Flag**: Run in non-interactive batch mode. Processes input message or piped stdin without TUI, prints agent response directly to stdout. Ideal for scripting, piping, and CI/CD integration. Exits after first response.
- **`-P, --print-streaming` Flag**: Like `-p`, but streams response tokens as they arrive. Use `--print-streaming --no-markdown` for raw unformatted output.
- **`--print-turn` Flag**: Continue processing tool calls and agent turns until the agent naturally finishes or requires user input. Combine with `-p` for complete multi-turn conversations.
- **`--no-markdown` Flag**: Output raw text without Markdown formatting. Useful when piping output to tools that expect plain text.
- **Streaming Print Mode**: Added internal `printStreaming` option for streaming output in non-TUI mode.
- **RPC Mode `print` Command**: Send `{"type":"print","content":"text"}` to get formatted print output via `print_output` events.
- **Auto-Save in Print Mode**: Print mode conversations are automatically saved to the session directory, allowing later resumption with `--continue`.
- **Thinking level options**: Added `--thinking-off`, `--thinking-minimal`, `--thinking-low`, `--thinking-medium`, `--thinking-high` flags for directly specifying thinking level without the selector UI.

### Changed

- **Simplified RPC Protocol**: Replaced the `prompt` wrapper command with direct message objects. Send `{"role":"user","content":"text"}` instead of `{"type":"prompt","message":"text"}`. Better aligns with message format throughout the codebase.
- **RPC Message Handling**: Agent now processes raw message objects directly, with `timestamp` auto-populated if missing.

## [0.11.9] - 2025-12-02

### Changed

- Change Ctrl+I to Ctrl+P for model cycling shortcut to avoid collision with Tab key in some terminals

## [0.11.8] - 2025-12-01

### Fixed

- Absolute glob patterns (e.g., `/Users/foo/**/*.ts`) are now handled correctly. Previously the leading `/` was being stripped, causing the pattern to be interpreted relative to the current directory.

## [0.11.7] - 2025-12-01

### Fixed

- Fix read path traversal vulnerability. Paths are now validated to prevent reading outside the working directory or its parents. The `read` tool can read from `cwd`, its ancestors (for config files), and all descendants. Symlinks are resolved before validation.

## [0.11.6] - 2025-12-01

### Fixed

- Fix `--system-prompt <path>` allowing the path argument to be captured by the message collection, causing "file not found" errors.

## [0.11.5] - 2025-11-30

### Fixed

- Fixed fatal error "Cannot set properties of undefined (setting '0')" when editing empty files in the `edit` tool.
- Simplified `edit` tool output: Shows only "Edited file.txt" for successful edits instead of verbose search/replace details.
- Fixed fatal error in footer rendering when token counts contain NaN values due to missing usage data.

## [0.11.4] - 2025-11-30

### Fixed

- Fixed chat rendering crash when messages contain preformatted/styled text (e.g., thinking traces with gray italic styling). The markdown renderer now preserves existing ANSI escape codes when they appear before inline elements.

## [0.11.3] - 2025-11-29

### Fixed

- Fix file drop functionality for absolute paths

## [0.11.2] - 2025-11-29

### Fixed

- Fixed TUI crash when pasting content containing tab characters. Tabs are now converted to 4 spaces before insertion.
- Fixed terminal corruption after exit when shell integration sequences (OSC 133) appeared in bash output. These sequences are now stripped along with other ANSI codes.

## [0.11.1] - 2025-11-29

### Added

- Added `fd` integration for file path autocompletion. Now uses `fd` for faster fuzzy file search

### Fixed

- Fixed keyboard shortcuts Ctrl+A, Ctrl+E, Ctrl+K, Ctrl+U, Ctrl+W, and word navigation (Option+Arrow) not working in VS Code integrated terminal and some other terminal emulators

## [0.11.0] - 2025-11-29

### Added

- **File-based Slash Commands**: Create custom reusable prompts as `.txt` files in `~/.pi/slash-commands/`. Files become `/filename` commands with first-line descriptions. Supports `{{selection}}` placeholder for referencing selected/attached content.
- **`/branch` Command**: Create conversation branches from any previous user message. Opens a selector to pick a message, then creates a new session file starting from that point. Original message text is placed in the editor for modification.
- **Unified Content References**: Both `@path` in messages and `--file path` CLI arguments now use the same attachment system with consistent MIME type detection.
- **Drag & Drop Files**: Drop files onto the terminal to attach them to your message. Supports multiple files and both text and image content.

### Changed

- **Model Selector with Search**: The `/model` command now opens a searchable list. Type to filter models by name, use arrows to navigate, Enter to select.
- **Improved File Autocomplete**: File path completion after `@` now supports fuzzy matching and shows file/directory indicators.
- **Session Selector with Search**: The `--resume` and `--session` flags now open a searchable session list with fuzzy filtering.
- **Attachment Display**: Files added via `@path` are now shown as "Attached: filename" in the user message, separate from the prompt text.
- **Tab Completion**: Tab key now triggers file path autocompletion anywhere in the editor, not just after `@` symbol.

### Fixed

- Fixed autocomplete z-order issue where dropdown could appear behind chat messages
- Fixed cursor position when navigating through wrapped lines in the editor
- Fixed attachment handling for continued sessions to preserve file references

## [0.10.6] - 2025-11-28

### Changed

- Show base64-truncated indicator for large images in tool output

### Fixed

- Fixed image dimensions not being read correctly from PNG/JPEG/GIF files
- Fixed PDF images being incorrectly base64-truncated in display
- Allow reading files from ancestor directories (needed for monorepo configs)

## [0.10.5] - 2025-11-28

### Added

- Full multimodal support: attach images (PNG, JPEG, GIF, WebP) and PDFs to prompts using `@path` syntax or `--file` flag

### Fixed

- `@`-references now handle special characters in file names (spaces, quotes, unicode)
- Fixed cursor positioning issues with multi-byte unicode characters in editor

## [0.10.4] - 2025-11-28

### Fixed

- Removed padding on first user message in TUI to improve visual consistency.

## [0.10.3] - 2025-11-28

### Added

- Added RPC mode (`--rpc`) for programmatic integration. Accepts JSON commands on stdin, emits JSON events on stdout. See [RPC mode documentation](https://github.com/nicobailon/pi-mono/blob/main/packages/coding-agent/README.md#rpc-mode) for protocol details.

### Changed

- Refactored internal architecture to support multiple frontends (TUI, RPC) with shared agent logic.

## [0.10.2] - 2025-11-26

### Added

- Added thinking level persistence. Default level stored in `~/.pi/settings.json`, restored on startup. Per-session overrides saved in session files.
- Added model cycling shortcut: `Ctrl+I` cycles through available models (or scoped models with `-m` flag).
- Added automatic retry with exponential backoff for transient API errors (network issues, 500s, overload).
- Cumulative token usage now shown in footer (total tokens used across all messages in session).
- Added `--system-prompt` flag to override default system prompt with custom text or file contents.
- Footer now shows estimated total cost in USD based on model pricing.

### Changed

- Replaced `--models` flag with `-m/--model` supporting multiple values. Specify models as `provider/model@thinking` (e.g., `anthropic/claude-sonnet-4-20250514@high`). Multiple `-m` flags scope available models for the session.
- Thinking level border now persists visually after selector closes.
- Improved tool result display with collapsible output (default collapsed, expand with `Ctrl+O`).

## [0.10.1] - 2025-11-25

### Added

- Add custom model configuration via `~/.pi/models.json`

## [0.10.0] - 2025-11-25

Initial public release.

### Added

- Interactive TUI with streaming responses
- Conversation session management with `--continue`, `--resume`, and `--session` flags
- Multi-line input support (Shift+Enter or Option+Enter for new lines)
- Tool execution: `read`, `write`, `edit`, `bash`, `glob`, `grep`, `think`
- Thinking mode support for Claude with visual indicator and `/thinking` selector
- File path autocompletion with `@` prefix
- Slash command autocompletion
- `/export` command for HTML session export
- `/model` command for runtime model switching
- `/session` command for session statistics
- Model provider support: Anthropic (Claude), OpenAI, Google (Gemini)
- Git branch display in footer
- Message queueing during streaming responses
- OAuth integration for Gmail and Google Calendar access
- HTML export with syntax highlighting and collapsible sections
