New Features
- Shell login and logout: use
pi auth login <provider>andpi auth logout <provider>without starting a session, with API-key and no-browser sign-in options. See Credential commands. - Idle prompt cache warming: eligible caches now stay warm for up to 30 minutes between runs when a refresh is expected to pay for itself. See
cacheWarming. - Anthropic message threads: requests send only new messages while the server continues the conversation, with full-request fallback when earlier context changes. See Anthropic compatibility.
- Richer Mermaid diagrams: pie charts, author-defined styles, clickable labels on supported terminals, and diagrams in expanded branch and compaction summaries. See Display settings and Markdown transformers.
- GitHub Copilot classifiers: call Microsoft-Decision-1 through codemode
models.classify()for typed decisions and probabilities. See Use classifier models. - Package update summaries:
pi update --extensionsreports each package's npm version or git commit change and distinguishes unchanged, skipped, and warned updates. See Update Pi or packages.
Breaking Changes
- Custom
GrepOperations.readFilecallbacks are no longer called for context lines. The field remains accepted as optional and deprecated so existing integrations still compile. The grep tool now takes context lines from ripgrep and no longer reads matched files itself. To search a remote system, override grep'sexecute(); see Remote Execution (#9276) - OpenAI-compatible models no longer send
"tools": []when all tools are disabled in a session that has used tools; the field is omitted. This fixes 400 errors (tools must not be an empty array) from vLLM 0.20+, also behind LiteLLM. If your proxy requirestoolsonce the history has tool calls, such as older LiteLLM versions in front of Anthropic, setcompat.requiresToolsWithToolHistory: truefor that model inmodels.json(#11843)
Added
pi updatenow lists each updated package with its npm version or git commit change, for examplenpm:foo 1.2.0 -> 1.3.0, and printsPackages are already up to datewhen nothing changed. When nothing changed but an update printed a warning, for example because npm left the old version installed after resolving stale registry metadata, it printsNo packages were updated, see the warnings aboveinstead; in offline mode it printsSkipped package updates (offline mode).PackageManager.update()reports each changed package as a newresultprogress event whosemessageholds that line (#11707, #11711)- Anthropic sessions now use message threads: each request sends only the new messages and the server continues from the previous reply, falling back to the full request when the conversation changed (for example after compaction or a tool list change). On by default for the
anthropicprovider onapi.anthropic.com; setcompat.supportsMessageThreadsinmodels.jsonto enable it for gateways that forward thethreadfield, or to turn it off. Cache warming does not touch the session's thread (#11545) pi.registerMarkdownTransformer()takes an optional{ messageTypes }that selects the Markdown surfaces a transformer runs on. Besides user, assistant, and thinking Markdown, transformers can now opt intocustom(custom messages and skill blocks),summary(branch and compaction summaries), andchangelog(What's New,/changelog, the Extension Updates notice, and the Update Available note). Without options a transformer runs on user, assistant, and thinking Markdown as before. The built-in Mermaid renderer now also draws diagrams in expanded branch and compaction summariespi auth login <provider>logs in to a provider from the shell without starting a session, for examplepi auth login radius. It signs in with an account in the browser and exits;--api-keysaves an API key instead, and--no-browseruses device code or copy-code sign-in instead. Logging in to Radius also configures the Radius MCP server.pi auth logout <provider>removes the stored credentials, like/logoutctx.ui.custom()overlays now honor theblockedoption: pi reports blocked program status (OSC 7501) from when the overlay is shown until it callsdone(), also while it is hidden withsetHidden(). Closing one overlay keeps other open questions blocked (#11816)- Added the
qwen-token-plan-individual-cnprovider for Qwen Token Plan Individual on the China endpoint, usingQWEN_TOKEN_PLAN_CN_API_KEY(#7989 by @bigoldcat123) - Added Microsoft-Decision-1 classifier support through GitHub Copilot, including codemode
models.classify()(#11679 by @Marvae) - Added
compat.promptCacheKeyMode("auto","enabled", or"disabled") to enable prompt cache keys for compatible proxies or omit them for endpoints that reject them. Set it inmodels.jsonwhen using pi (#9442 by @dannote) - Added
compat.requiresNonNullAssistantContentfor OpenAI-compatible endpoints that require an empty string instead ofnullin assistant messages containing only tool calls. Set it inmodels.jsonwhen using pi (#8118 by @gaoyk19) - Added syntax highlighting for Dart, Nix, Groovy, and Gradle files in read and write views (#11643)
- Added GLM 5.3 to the Qwen Token Plan Individual model allowlist (#11658)
- Added Claude Fable 5.2 (
claude-fable-5-2) to theanthropicprovider ($8/$40 per million input/output tokens, 1M context, 128K output). Like Fable 5.1 it uses per-message effort and mid-conversation system messages; requests its safety classifiers refuse before any output are answered by Claude Opus 5 through server-side fallback and billed at Opus 5's price. Claude Fable 5.2 and Mythos 5.2 on other providers, such as OpenRouter'santhropic/claude-fable-5.2, get the same per-message effort support
Changed
- The default model for the
anthropicprovider is now Claude Opus 5.5 (claude-opus-5-5) instead of Claude Opus 4.8 - Default models moved to newer models at the same or a lower price:
amazon-bedrockClaude Opus 5.5,azureGPT-6.1 Sol,googleandgoogle-vertexGemini 4 Argon,vercel-ai-gatewayGLM 5.3,basetenGLM 5.3,minimaxandminimax-cnMiniMax-M3,qwen-token-planandqwen-token-plan-cnQwen3.8 Max,opencode-goKimi K3.1 Pro, and Kimi K2.7 Code instead of Kimi K2.6 formoonshotai,moonshotai-cn,huggingface,opencode,openrouter,cloudflare-workers-aiandcloudflare-ai-gateway cacheWarmingnow defaults to"idle"instead of"streaming": pi also keeps eligible prompt caches warm for up to 30 minutes between agent runs, but only when a refresh is expected to pay for itself. Set"cacheWarming": "streaming"in global settings for the previous behavior- Consecutive cache warms now show as one
Cache warmed: $<total>line with the cumulative cost instead of one line per warm - The OpenAI Codex provider is shown as "OpenAI Codex" again instead of "OpenAI Codex (legacy)" in
/loginand the model selector - The
/loginand/logoutprovider lists and/login <provider>completions now show the preferred partners Radius and OpenRouter first, then all other providers alphabetically. In the provider lists, partners are marked with✦, the selected Radius row shimmers in the Radius logo colors and the selected OpenRouter row glows in OpenRouter's brand color (lime on dark themes, violet on light themes) - Upgraded terminal Mermaid rendering to support more diagram types, including pie charts, author-defined styles, and clickable labels on terminals with hyperlink support (#8158 by @xl0)
Fixed
- Fixed the grep tool's
globmatching from the folder pi was started in instead of frompath: withpath: "repo",glob: "migrations/main/*.js"returnedNo matches foundeven thoughrepo/migrations/main/a.jsexists. Globs are now relative topath, the same form grep prints its results in, also whenpathis a symlink. A leading./(./src/*.ts) is ignored instead of matching nothing (#11807, #10998) - Fixed prompt template arguments dropping apostrophes and merging words: an apostrophe inside a word, as in
doesn't, no longer opens a quote; a quote with no closing match is kept as text; and\"inside"..."(or\'inside'...') gives a literal quote (#11861) - Fixed the bash tool reporting only
Command timed outwhen the command had already exited but a background process it started kept writing to its output until the timeout. The error now also reports the shell's exit code and when it exited (#11613) - Images in steering and follow-up messages, including
prompt()while streaming, are now resized like images in idle prompts instead of being sent and saved at full size (#11738) - A failed token refresh of an MCP connection no longer registers an OAuth client or replaces the PKCE verifier of a sign-in in progress, which made that sign-in fail. MCP sign-in now refreshes the stored tokens with the stored client even when the loopback callback port changed, instead of registering a new client and opening the browser. Ctrl+C in
/mcpand the--timeoutofpi mcp loginnow also stop a sign-in while it waits up to 25 seconds for another pi process's token refresh, and a refresh lock that fails for another reason than that wait now fails the sign-in instead of opening the browser. - Fixed
pi mcp listreporting MCP servers with"auth": { "provider": "<provider>" }, such as Radius, as needing sign-in although the provider was signed in: the shell command sent no token. It now sends the provider's/logintoken and refreshes it when it expired. For these servers the sign-in hint names/login <provider>instead ofpi mcp login, andpi mcp loginandpi mcp logoutpoint to/loginand/logoutinstead of failing with "does not use OAuth" - Fixed RPC mode ignoring an extension's
ctx.shutdown()while idle, for example from a timer: the process kept running until the client sent another command. pi now shuts down right away when idle, and a shutdown requested by an extension command waits until the command'spromptresponse is written (#11599) - Fixed changelog notes repeating on every fresh launch when the installed package version has a prerelease suffix, such as
0.1.5-20261020.7: the saved version was read as0.1.0, so the0.1.1to0.1.5notes counted as new each time. A saved version withoutmajor.minor.patchnow shows no notes and is replaced by the installed version, instead of showing the whole changelog (#11703) - Fixed RPC mode cutting off shutdown cleanup, such as a pending MCP token refresh, when stdin closed and SIGTERM arrived together, which process managers like Paseo and systemd do. Pi lost the refreshed token and the MCP server revoked the sign-in. Once a shutdown has started, a stdin EOF or a single signal no longer interrupts it; a second signal still exits at once. Print mode likewise no longer dies from a signal that arrives during its final cleanup (#11599)
- Fixed the grep tool reading every matched file into memory when
contextwas set, which ran out of memory on large files; context now comes from ripgrep, which also fixes UTF-16 files and lone CRs in matched lines, and the match limit notice no longer appears when exactlylimitmatches exist (#9276, #11423) - Fixed the find tool reporting the result limit when exactly
limitfiles match, andlimit: 0in find and ls returning every result or an empty listing; limits below 1 now mean 1 (#7121) - Fixed grep match lines, codemode output, compaction summaries of tool results, and MCP error and server summaries cutting an emoji or other non-BMP character in half when truncating, which left an invalid lone surrogate in the text (#7121)
- Fixed the find tool on Windows returning no results for patterns with Windows separators such as
src\**\*.ts, and for every path pattern such assrc/**/*.tswith fd 10.5.1, which pi now downloads. Windows path patterns now match the same way with every fd version:src/**/*.tsalso finds files directly insrc/, andsrc/*.tsno longer finds files in subdirectories (#9262) - Fixed the read tool loading whole files into memory, which ran out of memory on large files even with
offset/limit; it now streams the file and keeps only the shown lines. CustomReadOperationscan stream too by providing the new optionalcreateReadStream(#9654) - Fixed OAuth logins such as
openaiandanthropicfailing withinvalid_grantafter pi was stopped while it refreshed an expired token, for example an RPC client that stops pi right after startup while the background catalog refresh runs. The token endpoint had already replaced the refresh token, but pi exited before saving the new one. On exit, pi now waits for a token refresh in progress to be saved (#11692) - Fixed Ctrl+P not switching to the only model in scope (or the only available model) when the active model is a different one; it showed "Only one model in scope" instead. Cycling forward from a model outside the scope now also selects the first scoped model instead of skipping it (#11806)
- Fixed
/reloadand session switches leaving extension overlays on screen when an extension had more than onectx.ui.custom({ overlay: true })open: only the topmost overlay was removed, and the others kept focus and input although the extension that opened them was gone. All extension overlays, including hidden ones, are now removed and disposed; pi's own overlays stay open - Fixed
/mcpsign-in staying on "Connecting…" for minutes after a successful browser sign-in, with Ctrl+C doing nothing: pi waited for the browser to drop an unused connection to the OAuth callback port. The callback server now closes remaining connections when it shuts down (#11311) - Fixed pi aborting (
zsh: abort) after repeated image reads, reported on macOS arm64 with Node 24.16. Each image resize starts a worker thread, and pi did not wait for it to stop, so the next resize started a new worker while the previous one was still shutting down. The crash is most likely a Node bug that this overlap triggers and could not be reproduced on Linux; image resizes now wait for the previous worker to stop, which adds about 15 ms per image (#10695) - Fixed
tool_searchandsearchTools()not finding a tool by property names and descriptions behind a local$ref, as in MCP input schemas that put their models in$defs. Referenced definitions are read once, so recursive schemas do not loop, and definitions nothing references stay out of the search text (#11803) - Fixed the codemode
resolves tosummary of a tool leaving out field names behind a local$ref, for examplestructuredContent?instead ofstructuredContent?: { results }for MCP output schemas that put their models in$defs(#11803) - Fixed every codemode script failing with
URI malformedwhen any callable tool, such as an MCP tool, had a$refwith a malformed percent escape (#/$defs/%E0) in its schema, even scripts that do not call that tool. The parameter now renders asunknownin the tool's declaration (#11803) - Fixed
ctrl+onot expanding or collapsing the output of!and!!commands run while the agent is working. New!/!!output now starts in the current expand state, the output no longer disappears when a steering or follow-up message is queued, and it moves into the chat when the agent finishes instead of on the next submitted message (#11875) - Fixed resuming a session restoring an old thinking level after
/treenavigated to before a/thinkingchange. Like the model, the live thinking level is now recorded on the new branch with the next prompt (#11451) - Fixed inline images in fullscreen mode showing only their first row in Orca, while regular mode showed them in full. Fullscreen now draws Kitty images after the rows they cover on every terminal, as it already did for WezTerm (#11835)
- Fixed the edit tool rewriting the line endings of untouched lines in files with mixed CRLF/LF or lone CR line endings, and running out of memory on large files after the file was already written; the diff now covers only the changed lines and their surroundings and is computed before writing (#8544)
- Fixed the Windows installer (
irm https://pi.dev/install.ps1 | iex) aborting withNativeCommandErrorin Windows PowerShell 5.1 when npm or Node.js printed any warning, for examplenpm warn Unknown user configfrom an unknown.npmrckey. It failed before the action menu when migrating an npm installation, and during managed installs. An invalidmanaged-install.jsonalso aborted the installer instead of being reported (#11944) - Fixed
pi update --modelsfailing withCould not refresh model catalogs: openai: OAuth refresh failed for openai: ... invalid_grantwhen a provider's login had gone stale. Built-in providers whose catalog comes from pi.dev, such asopenai, no longer refresh their OAuth token for a catalog refresh at all. For providers that list models with the login, such as Radius and OpenRouter, a failed token refresh now prints a warning naming the provider andpi auth login <provider>, and the other catalogs still refresh; the command fails only for other errors, such as a network failure - Fixed the powershell tool reporting
Command exited with code 1under Windows PowerShell 5.1 when a native command succeeded but its stderr was redirected, as ingit push 2>&1 | Select-Object -Last 3. Windows PowerShell 5.1 turns that stderr into error records; such commands now report the exit code PowerShell 7 reports (#8842) - Fixed deleting a paste marker with Backspace corrupting later short markers such as
[paste #2], causing the marker text to be submitted instead of its pasted content (#11923) - Fixed dropped provider streams reported as "cut short after the reply had begun" not triggering automatic retries (#11879)
- Fixed the subagent extension example passing Bun's Windows virtual entry path as part of the prompt when spawning a compiled pi binary (#11865)
- Fixed the model selector and llama.cpp Hugging Face search moving the selection when a background catalog refresh or search result arrives (#9109)
- Fixed internal cursor markers leaking into terminal output, including with multiple markers or horizontally clipped content (#9441 by @muyiyr)
- Fixed the subagent extension example showing running tasks as completed, losing subprocess failure diagnostics, and failing to stop child processes on abort. Agent discovery and trust checks now use each task's working directory, and single and chain results are truncated without losing the full tool details (#8250 by @terrorobe)
- Fixed large pasted text being replaced by literal paste markers when switching editors, opening custom UI, or restoring queued messages (#10146 by @w-winter)
- Fixed prompts and session-tree navigation overlapping during asynchronous input hooks, authentication, or branch summaries, which could install the wrong conversation context (#9155 by @acmerfight)
- Fixed Claude Sonnet 5 requests sending an unsupported temperature parameter (#7961 by @jingtao-wisdomgraph)
- Fixed extensions loaded through symlinked paths failing to resolve their dependencies by resolving the entry file's real path before importing it (#8112 by @cad0p)
- Fixed the plan-mode extension example missing completion markers in thinking blocks and common completion phrases, dropping formatted or long plan steps, and sending an extra model turn to acknowledge completion (#7950 by @giannisCKS)
- Fixed OpenAI Responses requests sending
session_idinstead of the documentedsession-idaffinity header (#11639) - Fixed delivered image-only steering and follow-up messages remaining in the pending queue (#8612 by @wutongyuonce)
- Fixed cancellation during lazy provider loading or authentication being reported as an error instead of an abort (#8635 by @Mallikarjun-0)
- Fixed session runtime disposal tearing down extensions before active tools finished aborting and their results were recorded (#9126 by @acmerfight)
- Fixed the session-tree search cursor not being shown or positioned for input methods (#9157 by @Perlence)
- Fixed SDK and RPC reloads replacing extensions while a response or compaction was still running; reload now asks the caller to wait (#9222 by @acmerfight)
- Fixed rendered edit diffs losing shared indentation when a change inserted text at the start of a line (#9274 by @dannote)
- Fixed
!and!!commands omitting the truncation notice and full-output file link when earlier output chunks had been discarded (#10165 by @acmerfight) - Fixed extension selection dialogs growing beyond the terminal height; they now show a scrolling window of up to ten options (#11072 by @DivineDominion)
- Fixed
pi configignoring custom keybindings fromkeybindings.json(#11651) - Fixed concurrent OAuth refreshes through symlinked paths to the same
auth.jsonby sharing the lock on the resolved file (#11655) - Fixed provider connection errors hiding their underlying cause, such as connection refusal or certificate errors, behind generic messages (#11695)
- Fixed Ctrl+V not pasting clipboard images or text on Windows and WSL; both Ctrl+V and Alt+V are now default paste shortcuts there (#11765)
- Fixed llama.cpp connection errors omitting the server URL and underlying network error (#11745)
- Fixed Alacritty hyperlinks not being enabled when
TERM_PROGRAMis unset; detection now also usesTERMandALACRITTY_WINDOW_ID(#11767) - Fixed OpenAI Codex SSE retries retaining abort listeners after each backoff, causing listener buildup on repeated retries (#11708)
- Azure OpenAI models now keep OpenAI's long-context price tier, so requests above 272K input tokens are costed at Azure's long-context rates (#11948)
- Fixed Anthropic and Bedrock sending
strict: "prefer"tools strict again on every request after Claude rejected them for exceeding its strict tool limits, which cost a rejected request (400) per turn. Later requests with the samesessionIdnow send those tools non-strict right away, untilcleanupSessionResources(sessionId)(#11626) - Fixed tool arguments for
Type.BigInt()andType.Undefined()parameters being rejected: they convert as TypeBox converted them ("42"and42to42n,nulltoundefined), now that pi-schema supports both types.Type.Void()still rejects every JSON argument. - Fixed Azure GPT-6 Astra, Luna, Sol, GPT-6.1 Sol, and GPT-6.1 Terra using a 272K context window instead of the 1,050,000 tokens Azure Foundry deploys them with (#11742)
- Fixed OpenRouter rejecting requests with a 400 (
This endpoint's maximum context length is ...) for models whose output limit is close to the context window, such as DeepSeek flash. OpenRouter counts the input with its own tokenizer, which can be several percent higher than the provider's count, and pi left only 4,096 tokens spare. pi then treated the 400 as a context overflow and compacted the session, even at around 20% of the window. The default output limit now leaves 15% of the estimated input unused, and near a full window at most 32,768 output tokens are requested (#10497) - Fixed Anthropic non-strict tool schemas dropping root
$defsanddefinitions, which left property$refs pointing at nothing. Claude then produced wrong arguments for such tools (common in MCP servers), for example a JSON string instead of an object, and some Anthropic-compatible gateways rejected the request outright (#9557) - Fixed OpenCode Go Claude Haiku 5.5 failing with a 400 (
Invalid signature in thinking block ... bound to a different conversation) after the tool list, system prompt, or earlier history changed, which left the session failing on every retry. OpenCode Go and Zen Claude 5.5 models, Opus 5, and Fable 5.1 now use per-message effort and sendthinking.block_binding: drop_block, like the Anthropic provider (#10954) - Fixed Markdown displaying HTML comments (
<!-- ... -->) as visible text (#11710) - Fixed codemode
console.*output and thrown non-Error values printingNaN,Infinity, and-Infinityasnull(#11901) - Fixed large MCP stdio messages being repeatedly copied and scanned as chunks arrived, causing slow tool responses (#11761)
- Fixed MCP Streamable HTTP SSE replies with CR-only line endings failing with "stream ended without a response" (#11764)
- Fixed oversized MCP SSE responses keeping their HTTP connections open after the message-size limit rejected them (#11729)
- Fixed MCP stdio server subprocesses surviving disconnect or pi exit on POSIX when the server's main process had already exited (#11721)
- Fixed MCP Streamable HTTP JSON replies bypassing message-size limits and HTTP errors buffering entire response bodies. Oversized replies and error-body content beyond the first 8 KiB are now cancelled (#11335)
- Fixed valid tool arguments being rejected when their schema combined local
$refs with a relative root$id, such asschemas/tool.json(#11697) - Fixed the find tool starting an untracked
fdprocess when cancelled during its parent-directory lookup (#11974 by @petrroll)