@oh-my-pi/pi-agent-core
Added
- Added optional queued-message preparation with cancellation-safe delivery and appended context (#11835 by @andrebrait).
Fixed
- Fixed streaming CPU blowup on long turns: per-delta
message_updatesnapshots now deep-clone only the blocks the stream actually touched instead of the entire accumulated message, eliminating the quadratic cloning work that could freeze the TUI for tens of seconds to minutes while a subagent streams (#10605). - Native compaction now carries an existing local summary into the first provider-native request instead of losing the summarized history. (#11525 by @rpie9)
- Subsequent native compactions preserve messages appended between a speculative snapshot and its commit, while honoring
/clearboundaries. (#11525 by @rpie9) - Native replay compatibility checks the active provider and Responses API independently of whether future native compaction is enabled. (#11525 by @rpie9)
- Fixed compaction retaining oversized older steps beyond the recent-history budget and skipping previously retained history on later passes, preventing long tool loops from freeing enough context (#11365).
- Fixed Codex remote compaction retries for both Bun and proxy socket-closure messages and stopped falling back to the unsupported
/responses/compactendpoint after V2 failures.
@oh-my-pi/pi-ai
Added
- Added support for Cerebras Qwen 3.8-27b with improved reasoning effort control
- Added optional host browser-session callbacks for Perplexity SSO login, keeping browser automation out of pi-ai and preserving email and authenticator-code login.
Fixed
- Fixed the auth-gateway sending a model's own reasoning back to Anthropic as demoted plain text, which tripped the
reasoning_extractionclassifier on Fable, leaked reasoning into visible answers on Opus, Sonnet and Haiku, and broke the prompt cache prefix on every tool-calling turn. Replayed assistant turns now carry the model id the request resolves to and astopReasonderived from the turn's own tool calls, so same-model thinking blocks keep their signatures and replay natively (#12115 by @Zhu-Aemon). - Fixed custom OpenAI-compatible Responses streams crashing on omitted delta payloads or reasoning-summary fields, and recovered text delivered only in completed snapshots (#11863 by @moodiness).
- Fixed streaming CPU blowup on long Responses turns: per-delta content-index lookups are now O(1) instead of re-scanning the accumulated content blocks, eliminating the quadratic work that could freeze the TUI for tens of seconds to minutes while a subagent streams (#10605).
- Fixed sessions permanently wedged by
400 Invalid signature in thinking blockafter a failover proxy swapped upstream models mid-conversation (e.g. Claude -> GLM -> Claude): when the unsigned-demotion retry fails identically, the anthropic-messages transport now retries once with replayed thinking dropped and pins that mode for the session, so the conversation continues without starting a new session (#12006 by @Damin-Lee). - Fixed OpenAI Codex backend rejecting requests with HTTP 400 (
string_above_max_length) when replaying tool call IDs exceeding 64 characters or containing composite delimiters (|,\n) by sanitizing and deterministically clamping call IDs on the wire (#11342). - Fixed OpenRouter multi-turn tool-call sessions failing with
400 Referenced reasoning item ... was not found or has expiredon Meta Muse Spark models by suppressing reasoning reconstruction when history is filtered and synthetic replay is disallowed, while preserving Anthropic and DeepSeek replay (#10966). - The auth gateway now keeps provider session state per session, so a model reached through it stops re-learning the same rejection every turn. Sticky fallbacks such as strict-tools and fast mode previously did nothing on the
pi-nativetransport used by containerized and robomp deployments, because the state cannot cross the wire and the gateway kept none of its own (#12058 by @camjac251). - Fixed full OpenAI Responses request-body timeout recovery so the exact HTTP 408 is surfaced for a changed-request recovery instead of repeated unchanged transport retries when eligible tool-result history can be safely elided (#11878 by @hellofrommorgan).
- Fixed Codex sessions producing unrelated visible output on later turns after a progress-only response. (#11466)
- Fixed OpenRouter reasoning models (e.g. Meta Muse Spark) rejecting every turn with
400 Provider returned errorafter the session history contains a tool-call turn from another provider, by no longer sending a fabricated reasoning item id (#11791 by @brndnmtthws). - Fixed statusless stream-drop diagnostics (stream disconnected/closed before
response.completed, upstream stream interrupted or ended before its terminal chunk, socket disconnected before the secure TLS handshake) classifying as terminal errors, so they now retry like their status-tagged twins instead of settling the turn (#11805). - OpenAI-compatible endpoints that report
ReasoningEffortin CamelCase now trigger effort-downgrade retries instead of terminating turns with HTTP 400 (#11804). - Fixed openai-responses replay wedging a repaired orphan tool-result note between another call's
function_callandfunction_call_output, which broke round pairing on strict validators (e.g. DeepSeek) with400 No tool output found for tool call …: orphan-output/call repair now runs before the interleaved-message hoist, so any injected note is relocated out of the tool-call batch (#11473). - A stale Anthropic tier block (
tier:fable,tier:mythos) is now cleared once a live usage report shows headroom on both the tier row and the shared windows, instead of idling a usable account until the reported reset. Healing requires a live report, and a credential held by an unscoped block spends no usage request on a probe that cannot lift it (#11334 by @AshishKumar4). - A running session now picks up credentials another process committed: adding an account in a second terminal is visible to credential selection and rotation without restarting the session, and a session's pinned account is re-resolved by row id so a row another process deleted cannot hand its slot to a sibling (#11329 by @AshishKumar4).
- Fixed rate-limit/overload failures that arrive inside an HTTP 200 body (Azure, LiteLLM-style aggregators, and reverse proxies that already committed to the stream) not advancing
retry.fallbackChains: a{"error":{…}}/{"code":429}chunk or a plain-text throttle frame (429 Too Many Requests, an nginx page) is now classified as a retryable 429/5xx through the same path an HTTP-status 429 takes, so a busy provider backs off and fails over instead of ending the session. Only bodies the provider actually reported are used: no status is inferred from error wording, and an unreadable body can no longer consume a credential. - Fixed tool schema normalization and cycle detection for frozen, sealed, and nonextensible schemas.
- Reduced memory retained by
complete()andcompleteSimple()while streaming responses. - Antigravity quota summaries now identify Claude/GPT routing copies as one shared upstream pool while preserving model-specific quota selection (#11268).
- Fixed the auth-gateway rejecting
content: nullon/v1/responsesand/v1/chat/completionsmessage items with a 400; Codex and other OpenAI clients that emit null content on empty turns now work, matching OpenAI's tolerance (#10956). - Fixed Azure GPT-6 Astra Chat Completions requests with function tools sending a non-
nonereasoning effort, which Azure rejects with HTTP 400 (#11052). - Fixed Z.AI and Zhipu usage-limit credential blocks and oneshot completion retries (titles, summaries, classifiers) resolving eight hours late when provider responses omit the reset timestamp timezone (#11014).
- Fixed provider requests failing with
ENOENTwhen another process removes a stale shared concurrency lock during acquisition. - Fixed Devin-hosted Gemini models rejecting turns that include nullable tool parameters by normalizing tool schemas to Gemini's supported JSON Schema dialect (#8647, #10233 by @will-bogusz).
- Fixed Devin gateway failures leaking raw proxy HTML into turn errors; HTTP status and retry metadata remain available for recovery (#10233 by @will-bogusz).
@oh-my-pi/pi-catalog
Added
- DeepSeek V4.1 Flash (
deepseek-flash) now accepts image inputs and resolves its reasoning metadata, name, and effort ladder from upstream instead of shipping as a text-only row without them.
Fixed
- Fixed Cerebras Qwen 3.8 reasoning control by enabling correct effort tiers and disable behavior
- Fixed Cerebras Qwen models using incorrect reasoning format, enabling proper support for thinking modes
- Fixed Command Code's
deepseek/deepseek-v4.1-flashrow exposing its documented low/high/max thinking levels and image input, and made live discovery resolve the reasoning contract its rules declare (#1666, #11703 by @aliefe04). - Fixed Meta Model API and Muse Code requests failing with 400 whenever omp forced a tool choice:
api.meta.ai/v1accepts onlytool_choice: "auto", sonone,required, and named choices (subagent final-retryyield, forced tools, structured output, compaction handoff) are now omitted instead of sent (#11635 by @quantmind-br). - Bedrock's Qwen rows no longer ask for more output tokens than the model accepts, which Bedrock rejected with a 400. (#12117 by @Huang-404-Q)
- Gemini 2.5 Flash Lite on Vertex AI no longer requests
maxOutputTokens=65536, which the endpoint rejects with a 400; the output cap is clamped to 65535 (#10595 by @WeMingT). - Fixed Meta muse-spark models on OpenRouter wedging every turn with
400 Referenced reasoning item ... was not found or has expired: replayed Responses reasoning history is now filtered for the muse-spark family, matching the existing Anthropic-on-OpenRouter treatment (#10675 by @Giardi77). - Fixed Ollama Cloud model discovery synthesizing a generic
minimal/low/medium/higheffort ladder for every thinking-capable model, which shadowed the per-model compat rules and mademaxunreachable on the DeepSeek V4 line (including the serveddeepseek-v4.1-flash,deepseek-v4-flash:0731, anddeepseek-v4-pro:0813ids): discovery now leaves the ladder to the rule tree, so those models advertise the wire-exactlow/high/maxand GLM-5.3 exposeslow/high/max(#8334). - Fixed Meta Model API and Muse Code requests failing with 400 whenever omp forced a tool choice:
api.meta.ai/v1accepts onlytool_choice: "auto", sonone,required, and named choices (subagent final-retryyield, forced tools, structured output, compaction handoff) are now omitted instead of sent. - Fixed Azure GPT-6 Astra Chat Completions policy to disable reasoning with function tools and encode thinking-off as
reasoning_effort: "none"(#11052). - Fixed Z.AI and Zhipu timezone-naive quota reset timestamps resolving eight hours late by declaring their UTC+8 reset timezone (#11014).
- Fixed Amazon Bedrock Claude Fable 5.1 effort metadata to expose
xhighandmaxinstead of the unsupportedminimallevel. (#10788 by @voonfoo) - LiteLLM discovery no longer exposes known task-specific models, including embedding, media, moderation, reranking, and search models, as coding models.
- Fixed custom
anthropic-messagesproviders whose adaptive effort ladder exposesminimalsendingoutput_config.effort: "minimal", which the Anthropic Messages API rejects with400 level "minimal" not supported; the adaptive effort mapper now clampsminimaltolow(#10994). - Qwen 3.8 models on Alibaba Token Plan now send the selected reasoning effort and replay reasoning history across turns.
- Fixed DeepInfra model cost reporting so promotional pricing is reflected: the
metadata.discountfraction is now applied to input, output, and cache-read rates (#10935). - Fixed LiteLLM model discovery leaking ClinePass display names and pricing into models with colliding ids (#10932).
- Raised Cursor context windows to Cursor's documented sizes (Grok 4.5/4.6 256k, default/Auto 256k, Kimi K2.7 Code 262k, GPT-5.6 272k, Claude Opus 5 and Fable 300k by default) so compaction no longer fires too early, without lowering existing 1M Max-mode windows.
@oh-my-pi/pi-coding-agent
Breaking Changes
- Renamed the
/dropslash command to/deleteso that "drop" is no longer overloaded between deleting the session and dropping a goal (/goal drop). - Read tool results no longer duplicate the body in
details.truncation.content; use resultcontentordetails.displayContentinstead. (#11255 by @jiwangyihao) - Removed the
DEL,DEL.BLK,COPY, andCOPY.BLKhashline edit operations. UseCUT/CUT.BLKfor deletion; removed content remains available toPASTE. - Changed tab.screenshot() to no longer accept a per-call save path; it now saves screenshots under browser.screenshotDir (or the OS temp directory if unset) and returns the saved path.
Added
- Added keyless Parallel web search when the provider is explicitly selected (#9770 by @georgeatparallel).
- Sloppy edits support
<SM:AFTER>to insert new lines after an anchor without repeating or replacing it. - Fixed eligible full OpenAI Responses request-body timeouts by retrying once after conservative local tool-result elision, while preserving assistant/user history, unsafe partial output, and existing stateful retries (#11878 by @hellofrommorgan).
- User append instructions (
APPEND_SYSTEM.md,--append-system-prompt) now render under their own## User Instructionsheading whenever generated blocks precede them, instead of trailing the## MCP Server Instructionssection and reading as server-supplied, unverified content (#11832 by @iacore). - Prewalk now arms for a hand-off target served by a
models.ymldiscovery:provider (e.g.openai-models-list):buildSessionOptionsruns a cache-aware refresh for the provider named by the selector and retries, instead of disabling prewalk with aModel "…" not foundwarning for idsomp modelslists (#11820). - Non-throwing tool failures now retain their error status through extension result rewrites and eval-defined subagent tools (#11585).
- Session rewrites now refuse to replace a file changed by another process, preserving durable turns from concurrent terminals (#11496).
- Goal mode now idles after repeated continuations return identical tool evidence instead of re-waking indefinitely (#11819).
- Cycling models with Ctrl+P no longer injects a spurious tool-roster notice that made the model believe still-callable tools had been removed; a prompt rebuild now discards the queued delta it already reflects (#11824).
- Subagent
yieldno longer fails a run withSYSTEM WARNING: Subagent called yield with null data.when a data-lessuseLastTurnfinalize (e.g.{type:"result"}) lands on a thinking-only turn with no text; the tool now rejects it at the boundary so the child is reminded to resubmit withdata(#11150). --continueno longer treats a merely-missing breadcrumb cwd as a project move. Re-root now requires the continue directory to be the same device+inode the breadcrumb recorded (git worktree move/ same-filesystemmv). A cross-filesystemmv(copy+unlink, new inode) is intentionally not re-rooted: the session stays in the original bucket,header.cwdis not rewritten, and a warn is logged (#11565).- Cold-revived persisted subagents now anchor wake-turn artifacts to their own transcript directory rather than the live root session's, so nested-depth and post-
/newrevivals no longer write<id>.mdoutside the revived agent's tree (#11563). - Legacy
settings.json→config.ymlmigration now writes the YAML first and only then archives the JSON, surfaces failures instead of swallowing them, and recovers from an orphanedsettings.json.bakwhenconfig.ymlis missing (#11569). - Legacy
settings.json→config.ymlmigration now writes the YAML first and only then archives the JSON, and surfaces failures instead of swallowing them (#11569). - MCP server names may now contain spaces, so human-friendly display labels like
MaaS Slacksurvive/mcp reauthwrite-back instead of being rejected by the config writer (#11731). - File paths in the compact grouped
Read (N)tree are now clickable OSC 8 hyperlinks, matching standalone Read rows; delimited reads carry a resolved link target per row so both live output and rebuilt transcripts link correctly (#11732). - Added server-name autocomplete for
/mcpcommands (enable,disable,test,remove,reconnect,reauth,unauth) using configured and runtime-discovered MCP servers. - Added
CUTandPASTEops to the hashline edit tool for moving code without retyping it:CUT N.=M(and.BLKblock forms) capture lines into a clipboard register, andPASTEoperations insert them. The register flows across sections within a patch (cross-file moves) and persists across edit calls per session. - Added
--from-claudeand--from-codexsession imports (including compaction state for Codex), also available from/resume @claudeand/resume @codex. - Added interactive Exa API-key onboarding through
/login exa, opening the official key dashboard and saving pasted keys for authenticated web search while preservingEXA_API_KEYand explicit-selection public MCP fallback behavior (#1798). - Added
ExtensionContext.getAsyncJobSnapshot()so extensions can read the owning session's async-job state without relying on process-global job-manager identity - Added opt-in
tui.codexResetFireworkscelebrations for unscheduled Codex weekly usage resets and newly banked saved resets, shown in a theme-aware top-third modal until Escape (#6858 by @joshrzemien). - The Cursor exec bridge serves the seven modern Pi tool frames, mapping each to its local equivalent:
pi_read/pi_ls→read,pi_bash→bash,pi_edit→edit,pi_write→write,pi_grep→grep, andpi_find→glob. The frames are a separate wire family from the legacy args, not aliases, so each mapping is a real translation —pi_grep'signore_caseis the inverse of the local tool's case-sensitivity flag,pi_findsearches filenames rather than contents, andpi_edit's replacements are renamed to the local snake_case pairs. providers.autoThinkingMaxEffort(xhigh|max, defaultxhigh) raises the ceiling of theautothinking classifier.maxbecame a first-class effort tier after the classifier prompt was written, soautocould never reach it on models that expose the tier — only theultrathinkkeyword could. Opting in addsmaxto the classifier's vocabulary, gated on the target model actually supporting it; the default keeps today's prompt byte-for-byte. The ceiling is enforced inside the effort clamp rather than on the classifier's answer, so a sparse ladder cannot snap an excluded request back up, and the Low floor is still resolved against the model's own ladder. The on-device 3-bucket classifier stays capped atxhighregardless of the setting. The ceiling governs whatautoresolves: a ladder with nothing underneath it yields no auto level, and athinking.requiresEffortmodel still gets its lowest supported effort from the transport.- Added omp cleanse, a new command that automatically detects language-ecosystem checkers, parses diagnostics (such as Cargo Clippy JSON), distributes repair workloads across concurrent subagents, and runs verification checks with a live progress bar.
- Added the bundled
ts-no-local-is-recordTTSR rule, which catches localisRecordfunction and lambda definitions and directs agents to shared guards plus explicit shape validation. - A
tool_callhandler (extension or hook) can now returninputto revise the arguments a tool executes with, not justblockit. The returned object is the raw execution input passed to the tool (ignored whenblockis set, and not applied tocomputertool calls), enabling wrappers that normalize or rewrite a built-in's arguments without reimplementing the tool. For model-issued calls the event fires at arg-prep time in the agent loop, so a revision is revalidated against the tool schema and is what concurrency scheduling,tool_execution_start/transcripts, the persisted assistant message, and the approval gate all observe — the user approves exactly what runs, and a revision that changes a tool's functional concurrency (e.g. bashpty) schedules correctly. A revised nestedwrite xd://device dispatch forfeits the outer write gate's approval and faces the full prompt again (#6681 by @psyrendust). - Added a parser for macOS
sample(1) call-tree reports to the read tool:*.sample.txtreads now return a compact bottleneck summary — per-thread hot paths with on-CPU sample counts (blocked syscall time excluded), demangled Rust v0/legacy symbols, flattened direct recursion, merged call-site siblings, idle-thread classification, and a process-wide top-functions-by-self-samples table.:rawstill reads the original report, and files that merely carry the extension fall back to plain text. - Added V8
.cpuprofilesupport to the read tool (Node/Bun--cpu-prof, Chrome DevTools, CDPProfiler.stopoutput): reads now return a compact bottleneck summary — hot-path call tree with on-CPU milliseconds ((idle)time excluded), collapsed pass-through chains, flattened direct recursion, shortened file URLs, and a top-functions-by-self-time table.:rawstill reads the original JSON, and files that merely carry the extension fall back to plain text. - Added separate Advisor cost visibility to the status line, rendering primary and Advisor spend as
$2.67 (sub) + $0.41 (adv)while keeping already-incurred Advisor cost across runtime disablement and same-session history rewrites. - Added a configurable per-request timeout for the
inspect_imagetool (inspect_image.timeoutMs, default 5 minutes; set to 0 to disable) so a stalled vision-model provider fails fast with a clear error instead of blocking until manual abort (#4165).
Changed
- Eval status rows for
browser/computercalls now say what happened (open main https://…,main.id(5).click(),close all) with a globe/computer icon instead of a barebrowserlabel; preludes with nothing to show record no row, while failures still surface. - Codex Spark, all MiniMax models, and GLM-5.3-Flash now default to replace edits instead of hashline; explicit edit-mode overrides remain honored.
- Storage maintenance streams large session journals and gzip archives instead of loading complete files into memory.
- Long sessions spend less time checking retired transcript blocks on each frame.
- An extension-originated message that starts no agent turn (e.g. an idle steer superseded by a concurrent turn) no longer crashes a headless
--mode rpcsession with an unhandled rejection (#11654 by @sjawhar). - Fixed reconnecting to a collab session while a tool was still running sometimes leaving its spinner animation active for the rest of the process (#9377 by @sjawhar).
- Reduced startup memory and latency when initializing memory with large session histories by reading only session header metadata instead of loading entire transcripts into memory.
- A revived subagent whose wake turn fails, is cancelled, or produces no output now relays a distinct notice (with the attributed
[provider/model]error and ahistory://<id>pointer) to whoever woke it, so ahub send await:truewaiter learns why there is no answer instead of a generic "stopped without replying" (#11290). - Orchestrators now verify with project-appropriate checks instead of Bun-specific commands, so non-Bun projects are no longer told to run a checker they do not have (#10985).
- Fixed long streamed replies being clipped to the live viewport until the turn ended; finished lines now retire into terminal scrollback while the response is still streaming. Models whose wire can revise text it has already streamed (
stream-revision) keep the old behaviour (#11276). - Prevent undeclared process-executing
hubtool injection into read-only subagents (#11044, closes #10257). - Reduced resume memory use by resolving persisted snapcompact frames only when they are included in the rebuilt context (#10227 by @lemonleks).
- Improved grouped read-call layout by nesting each request's usage metrics beneath its final path.
- Improved turn recovery to prevent duplicate output streaming during credential rotation or model fallback when visible text has already been streamed.
- Optimized tool guidance for bash, grep, and glob to be more concise while clarifying shell boundaries and search timeouts.
- Optimized models configuration resource probing to run in a single child process, reducing startup contention.
- Startup release notes now default to a compact change-count summary. Use
startup.changelogMode(summary|expanded|hidden) to control them; legacycollapseChangelogchoices migrate automatically (#6771). - Reworked the /guided-goal command from a modal-based popup flow into a natural, conversational chat interface where the agent asks follow-up questions directly in the session.
- Reduced startup memory usage by lazy-loading HTML session export assets only on their first use.
- Direct and
xd://dispatch now share one canonical tool map:write xd://<tool>executes any enabled top-level or mounted tool, andread xd://<tool>returns its docs, instead of failing when the name was exposed through the other layer. Mounted names are presentation metadata only, so tool replacement and disconnection cannot leave stale device instances; disabled tools remain unreachable, and bothxd://and Cursor/top-level fallback execution retain the tool's approval and ACP permission gates. - Session listing now caches parsed headers keyed on file stat identity (mtime + size), so repeated resume-picker opens and startup scans re-read only changed session files
- Reduced per-keystroke editor dispatch overhead: keybinding resolution happens once per input chunk and the per-action interception chain is gated behind a single canonical-key set probe
xd://device docs now render the parameter schema as a comment-annotated TypeScript type (viajsonSchemaToTypeScript, the same renderer the in-band tool inventory uses) instead of a raw JSON Schema dump, shrinking system-prompt device sections while keeping descriptions inline.- Added a
/vision [on|off|auto|status]slash command for session-scoped control of theinspect_imagevision-delegation tool, modeled on/computer:on/offforce the tool for the current session only,autoreturns to the persisted setting, andstatusreports the effective mode, session override, tool state, and active-model image capability. - Replaced the
inspect_image.enabledboolean with the tri-stateinspect_image.mode(auto|on|off, defaultauto). Inautothe tool is registered only when the active model lacks native image input, so vision-capable models (e.g.kimi-code/k3) read images inline with their own capabilities instead of delegating to a separate vision model; the tool set is re-evaluated on every model switch with a status notice when it flips. Thereadtool now follows the effective state dynamically rather than the raw setting, so it returns decoded image blocks again wheneverinspect_imageis hidden. Existinginspect_image.enabled: true/falseconfigs migrate toinspect_image.mode: on/off. - Made the task tool's per-spawn
effortparameter opt-in throughtask.enableEffort, which defaults to false and omits the field from flat and batch schemas and tool guidance until enabled. - Reduced terminal-title update overhead by deduplicating unchanged titles on every platform and using
SetConsoleTitleWthroughbun:ffiinstead of OSC writes on Windows. Windows working titles now keep a static:separator instead of scheduling spinner updates; other platforms retain the animated separator. - Added
task.maxEffortto cap the task tool's optional per-spawn effort hint after model-specific resolution, so operators can enable effort hints without allowing them to exceed a configured ceiling; the ceiling now also rides into the spawned session so retry-fallback model swaps re-clamp to it instead of escalating past the cap (#6580, #6794 by @wolfiesch). - Restructured the steering/interjection envelope sent to the model: the injected
<user_interjection>...<message>...</message>...wrapper around user text is now a<system-notice>explaining the interjection followed by the user's raw message unwrapped, matching the existing<system-notice>/<system-directive>convention instead of nesting the literal message inside its own tag pair, which some models found confusing. - Reduced default startup resident memory by constructing the default-off ComputerTool ArkType schema only on first parameter access, then reusing it across tool instances without changing validation or tool behavior (#6742 by @usr-bin-roygbiv).
- Reduced startup CPU and memory by loading the bundled changelog only when needed, while preserving source, npm bundle, standalone binary, and native absolute-path fallback resolution.
- Moved PTY log replay into the shared project launch broker, so normal CLI and Hub startup no longer load the xterm runtime while launch logs return validated rendered terminal rows.
Fixed
- Late non-blocking advisor notes arriving while a terminal primary turn unwinds now stay visible as advisor cards instead of starting an extra primary request (#12154 by @korri123).
- Fixed Perplexity sign-in for SSO-only accounts in
/loginand the setup wizard with isolated browser sign-in and automatic session capture, supporting both secure-prefixed and unprefixed session cookies without manual cookie copying. (#12064 by @lance0) - Mid-run compaction no longer sends the pre-compaction history to the next provider call when the live message array is rewritten in place.
- Collab guests now receive the host's goodbye even when the relay closes the room right behind it, and a fully sent snapshot no longer holds later frames behind transport backpressure.
- Fixed standalone
omp read skill://<name>failing withUnknown skillby discovering configured skills before resolving the URI (#10961). - Subagents no longer remain
runningafter their final result is accepted; a finished run reaches a terminal state without the parent having to send a status message (#11079). - Fixed
/loopnever resubmitting after a/skill:<name>prompt: the loop prompt is now captured for skill invocations, and resubmitted skill prompts are dispatched the same way the composer sends them instead of as literal text. /force:<tool>now reports that the current model cannot force a tool on hosts that only accept automatic tool selection (Meta Model API, Muse Code), instead of announcing a forced turn that the request silently drops (#11635 by @quantmind-br).- Fixed isolated subagent spawns exhausting host memory when the checkout's staged or unstaged diff is huge (for example a jj conflict commit exported to git); the spawn now fails with the isolation-budget error instead (#11454 by @sjawhar).
- Moving a session (
/move, or re-rooting on resume when its directory is gone) into a project it lived in before no longer fails withENOTEMPTY; the two artifact directories are merged instead (#12035 by @sjawhar). - Inbound user messages delivered by an extension (e.g. HCOM
sendUserMessage) no longer clear the composer draft; in-progress text and pasted images are preserved. - zsh completions for
--resume,--modeland the other dynamic value flags work again. (#12113 by @Huang-404-Q) - Leftover child
.gitdirectories and broken gitfiles no longer appear as the active project in the status line or agent instructions (#12105 by @bobbyhuang-dev). - Clicking a file path in the VS Code terminal opens the file at the requested line instead of a blank tab, and no longer breaks JVM language servers. (#12123 by @Huang-404-Q)
- An
http/sseMCP server that drops while the session is idle (a restart, a redeploy, a laptop waking) now reconnects on its own with a backoff instead of staying disconnected until the next tool call or/mcp reconnect, so its resource subscriptions and notifications come back with it (#11803 by @sjawhar). - Fixed pending-task reminders restarting the model after empty-response retries were exhausted (#11879 by @moodiness).
/tannow waits for descendant results before returning its final answer and remains cancellable while waiting (#12090 by @ryxli).- Ollama web search results now collapse tabs and embedded newlines in titles and snippets so they render on single lines.
- Pre-execution extensions that rewrite a streamed edit now execute the rewritten edit instead of the original input.
- Fixed sessions with skills disabled still advertising unavailable
skill://resources (#10215). - Singular and plural now work on both plugin surfaces:
/pluginin the TUI andomp pluginson the CLI (#12092 by @XL-Lewis). - ACP no longer advertises a custom or file slash command whose name collides with a builtin alias (e.g.
models,status,rewind), which previously offered a command that ran the builtin instead of the configured handler (#12092 by @XL-Lewis). - A manual
/compact(slash command, RPCcompact, extensionctx.compact()) issued while a turn is in flight now resumes that turn once the summary is committed, or immediately when there was nothing to compact — a queued steer/follow-up drives the resume, otherwise the same auto-continue nudge context-full compaction uses — instead of leaving the agent idle on a half-finished tool loop until the user types "continue". A prompt or extension-triggered turn that lands first takes the session instead.compaction.autoContinue: falsestill disables the resume; plan-mode "Approve and compact context" keeps dispatching its own execution turn (#11873 by @brndnmtthws). - Model-browser prices now preserve integer trailing zeros and positive sub-cent rates, and identify invalid individual rates (#11624 by @cyriusweng).
- Fixed the composer stranding blank rows below the input after a confirmation dialog or tall multi-line editor collapses; the editor now stays pinned to the bottom instead of drifting up until a resize (#11007).
- Subagent transcripts now identify their parent session and attribute host or parent-agent steering to the agent instead of the user (#12077).
- User-shell
!commands now keep their transcript block mutable until queued PTY replay finishes, preventing successful and nonzero stdout/stderr from disappearing into immutable terminal history (#12062; #12080 by @Dante-dan). - Headless print mode now stays alive while first-turn mnemopi recall waits for its embedding worker (#12067).
- Deferred TTSR reminders no longer repeat before the configured
repeatGaphas elapsed (#12065 by @Dante-dan). - Queued user steering and follow-up messages now refresh extension policy at delivery, including the first steering turn in a new session; returned overrides stay current when hooks change tools, and repeated policy changes pause automatic draining until an explicit retry (#11835 by @andrebrait).
- Fixed the TODO HUD auto-dismiss lifecycle: completed plans now persist their hidden state, survive session reopen, and can be explicitly revealed without stale timers hiding replacement plans.
- Agents shipped by omp-installed marketplace plugins now honor their
model:frontmatter instead of always inheriting@default; only Claude Code-format plugins (declaring.claude-plugin/plugin.json) keep dropping their provider-specific aliases (#12028). --resume/--continuecombined with--no-sessionnow fail with--resume requires session persistenceinstead of silently starting a fresh empty session and discarding the resumed history (#12008).- Session search now keeps exact and partial title matches above prompt-history matches, so a session found by name stays at the top after typing pauses (#11990 by @lemonleks).
- Collab replication now enforces its 1 MiB frame ceiling: an entry too large to shrink ships as a "too large to replicate" entry instead of an oversized frame, a deeply nested entry no longer aborts a guest's join, and the ceiling is measured in bytes rather than UTF-16 code units (#11433; #11999 by @MertSoylu).
- Model Hub now waits for default-role assignment to finish before accepting more input, preventing stale UI state and duplicate model changes that made a selection appear to require a second attempt (#10982 by @lemonleks).
- Fixed macOS copies showing pasteboard warnings, mangling non-ASCII text, reinterpreting PDF/EPS/RTF text, or leaving stale text after rapid copies (#9015 by @lemonleks).
- Fixed the coding-agent binary bundle failing with
Could not resolve: "chalk"in hermetic installs (e.g.nix run) by importing chalk from the in-repo@oh-my-pi/pi-utils/chalkreimplementation instead of the undeclared npmchalkpackage (#12001). - Fixed
edit.modelVariantsand other model-dependent system-prompt policy going stale after an automatic retry or usage-aware fallback swapped the model, so a session that fell back to a variant-pinned model now rebuilds its prompt for the model actually serving the turn (#11983). omp auth-gateway servenow picks up credential logins and logouts made by another process within ~10s instead of serving its boot-time credential set until restart: broker-backed clients implementpollExternalChanges(), and the gateway polls it to reload credentials and rebuild its served catalog so a newly-logged-in provider becomes routable and a logged-out one stops being advertised and used (#11781).- Fixed
omp benchandomp if-benchrejecting models thatomp modelslists (e.g. llama.cpp, Ollama, LM Studio,models.ymlservers) by retrying model resolution through a live discovery pass when the local cache can't restore their credentials (#11598 by @yomgui1). omp --forkwith a missing session path now fails withSession "<path>" not found.instead of silently opening an empty parentless session (#11944 by @onlyysaurabh).omp read <mcp-resource>now waits for a still-handshaking MCP server to finish connecting instead of reportingNo MCP server has resourcewhen the connect outlasts the startup race (#11950).memory://rootis now advertised in URL completion only onmemory.backend=local, and reading it onhindsight/mnemopireports the file-backed root as local-only (pointing atrecall/reflect) instead of telling you to enable memories that are already enabled; the memory glob validator now names the expected form (memory://root/**) instead of echoing the rejected input (#11909).- Advisors no longer brick themselves permanently on a transient rate limit: a usage-limit error whose credential is only temporarily blocked is now waited out and retried (bounded by
retry.maxDelayMs/retry.maxRetries), latching the quota-exhausted state only when the block is a genuine long quota window (#11947). - Large eval
display()values now stay bounded in session history while remaining available through output artifacts, preventing slow--resumestartup (#11920). - Hindsight mental-model refresh no longer rewrites the active session's cached system-prompt prefix: the rendered
<mental_models>block is frozen for the session lifetime (a background reflect applies to the next session;/memory mm reloadremains the explicit in-session refresh), and volatilelast_refreshed_atmetadata no longer enters the model-facing prompt (#11961). - Fixed Ctrl+D quitting the prompt even with draft text; it now deletes the character at the cursor like Delete, and only exits on an empty draft.
- Task subagents now honor the parent session's pinned OAuth account, including parallel and nested tasks (#11939).
- Advisor acknowledgments distinguish acceptance, deferral, and suppression; higher-priority findings replace only pending notes from the same review (#11881 by @olegpulatov).
/extensionsnow shows an enabled context file as active when its higher-priority competitor is disabled (#11870).- Anthropic prompt caching now keeps rolling breakpoints on persisted history when multiple
contextextension handlers append per-call messages (#11897). - Collab guests now automatically rejoin when a transient host network drop recreates the relay room (#11858).
- Yield now resets the schema-validation retry budget after each valid section and recovers double-encoded JSON values instead of spending retries (#11890 by @lucamaia9).
- Bash commands whose
cwdis a secondary Git worktree no longer inherit the agent's ownGIT_DIR/GIT_WORK_TREEand related repo-location overrides, so a failed cherry-pick stays in the worktree where it ran instead of contaminating the primary one (#11082). - Fixed
hub startfailing with a rawconnect ENOENT …/broker.sockwhen the project daemon broker's lease was stale: the lease is now a process-owned lock the OS releases however the broker dies, a stale lease no longer blocks startup, and a broker that still cannot start reports its scope path plus recovery commands (#11080). - Fixed concurrent
/pintoggles from multiple omp instances silently dropping each other's pins, and crashes mid-write corrupting the pins file. - LSP and debugger connections reject oversized or invalid frames instead of accumulating stdout indefinitely; fragmented headers decode without rescanning previous bytes.
- Read-only transcripts skip image blobs from hidden history, and session blob loading limits concurrent reads.
- Ctrl+C during an in-flight extension/hook load now exits cleanly instead of raising an
ExtensionExitErrorunhandled-rejection storm (#11789). - The legacy
@earendil-works/pi-coding-agentshim now exportsfindCutPoint(adapted to upstream Pi's tokenizer-less 4-arg signature) andsessionEntryToContextMessages, so extensions targeting upstream Pi 0.84.2's compaction/session APIs (e.g. NVlabs/SoL-Pi) install instead of failing validation (#11796). writenow rejects exact incomplete read projections before they can replace and truncate an existing file (#11792).- Long reasoning streams retain less memory while preserving scrollback and terminal-width replay.
omp read <image>?q=<question>no longer fails with "Model registry is unavailable for image questions."; the read CLI now wires a model registry so image questions resolvemodelRoles.vision/@defaultlike the agent (#11338).- Shared sessions stay connected when a guest sends a corrupted frame or uses the wrong room key.
- Fixed turns dying with
undefined is not an object (evaluating 'e.identity.class')as soon as the model started thinking when an extension provider projects its own catalog throughoauth.modifyModels(pi-provider-kiroand friends); projected models are now materialized like every other catalog source. - Legacy
agent.dbsettings rows are deleted after a successfulconfig.ymlmigration write, so deletingconfig.ymlno longer silently resurrects stale values (#11568). - Subagents (including
/vibeworkers) that write their report in one turn and then finalize with a data-lessyieldin the next no longer come back asSYSTEM WARNING: Subagent called yield with null datastapled to accumulated narration. The finalize now harvests the last turn that actually reported — prose with no further work started — so mid-run narration can never surface as a final result either (#11746 by @oldschoola). - Fixed
/forceand other forced tool choices refusing every OpenRouter model:buildNamedToolChoicedid not recognise theopenrouterapi. Models whose compat disables tool choice or forced tool choice now report forcing as unsupported instead of queueing a choice the transport discards (#11658 by @datrixlab). - Provider
baseUrloverrides now scope by API: custom models inheriting the provider URL define which APIs it covers (a provider-levelapicovers override-only providers),transport: pi-nativekeeps its gatewaybaseUrlprovider-wide, and a bundled model no longer routes to another API's endpoint (#11608 by @danilouchoa). - Invalidated stale background speculative compaction results when post-snapshot branch growth prevents recovery headroom or causes net context expansion, preventing dead-end progress pauses and provider context overflows (#11637 by @alvins82).
- Fixed
AgentSession.waitForIdle()returning before successful retry recovery events and persistence had settled. - Reviving a parked subagent whose session file vanished, or whose transcript lost its message history, now fails loudly instead of resurrecting a zero-history agent that runs, answers peers, and writes attributed work (#11500).
- Native compaction preserves prior local summaries and messages arriving while a speculative compaction is in flight. (#11525 by @rpie9)
- Advisor maintenance preserves compaction summaries and native replay payloads in later requests without duplicating native-covered retained messages. (#11525 by @rpie9)
- Advisor maintenance uses portable summaries for incompatible native targets and prevents automatic model switches or recovery re-primes from stranding native history. (#11525 by @rpie9)
- Advisor fallback, cooldown restoration, and context promotion can replay compatible native history when new native compaction is disabled; creating native results still requires the remote method to be enabled. (#11525 by @rpie9)
- Secret obfuscation covers native message, tool/search text, and dynamic discovery descriptions and schema annotations in replay and preserved compaction history, including search/discovery-only collisions and snapshots committed after a later secret is discovered, while preserving tool schema constraints. (#11525 by @rpie9)
- A session store that stops accepting writes (full disk, locked file, removed drive) now reports the failure on stderr in print mode and as an error notice in RPC mode, and a run whose transcript never became durable exits nonzero instead of reporting success (#11493).
- Online auto-thinking classification and session titles now walk
retry.fallbackChainswhen the tiny/smol primary returns a provider error, instead of failing the background task while the main turn still has a fallback chain. - Online tiny tasks now use canonical model-keyed, wildcard, and role fallback resolution, and stop at the first resolvable model when
retry.modelFallbackis disabled. - Session title generation now expands the appended active session model's own
retry.fallbackChainsafter that model fails, without merging tiny/commit/smol role defaults onto it (#10938). /exportHTML now renders bold inline code inside ordered-list items followed by fenced code blocks instead of displaying literal<strong>and<code>tags (#11690).- Disabled providers are no longer selected as pinned subagent models; ordered agent model lists now skip them (#11709).
- Entering goal or vibe mode while a plan session is paused now warns
Plan mode is paused — run /plan again to fully exit.instead of the staleExit plan mode first.(#11692). omp plugin install <name>for npm packages now bypasses bun's manifest cache, so a reinstall picks up a newly published version instead of a stale one, and installing an explicit<name>@<version>no longer fails to resolve a version that exists on the registry (#11634).- File slash commands now surface their
argument-hintfrontmatter as inline autocomplete ghost text and ACPinput.hint, not only in the/extensionsinspector (#11647). - Extensions authored against upstream Pi (e.g. pi-fabric) no longer crash every session at startup: registered tools now carry the upstream-shaped
sourceInfoprovenance thatgetAllRegisteredTools()consumers read (#11661). - Custom
openai-responses/openai-codex-responsesproviders can now setcompat.supportsConfigurationUpdate: falseinmodels.ymlso auto-thinking effort changes ongpt-6-astraare sent as the top-levelreasoning.effortinstead of aconfiguration_updateinput item the endpoint rejects with HTTP 400; the key is validated as a boolean and documented (#11121). - Missing execute-time tool context now fails closed to
always-askwith an empty policy map (no user grant) instead of silently resolving asyolowith empty policies. The former copies (ExtensionToolWrapper.execute, CursorrefuseByWritePolicy,mcpApprovalPreflight, and eval prelude host calls) share one helper so they cannot drift. A session-bound wrapper that is invoked without context still inherits that session's settings (#10362). - Advisors that repeatedly emit unsafe tool calls now pause their optional review until reset or their model/tool capability basis changes.
- Stop eval from advertising
agent()after the session reaches its subagent recursion-depth limit. - Background job snapshots preserve complete sibling results when a capture fails and show each capture warning only once.
- Failed raw-output captures now show a warning without failing the command or advertising an incomplete artifact as full output.
- Unknown custom status-line segment ids now produce a config warning and are rejected by
omp config setinstead of silently disappearing (#11579). ast_edit,search, andast_grepno longer fan out into overlapping scans whenpathsmixes a directory with a file inside it and the directory is spelled as an absolute path;ast_editpreviously applied each rewrite twice to the nested file (corrupting it, e.g.wrap(wrap(log(1)))) or reported a spurious stale-preview error (#11584).- Selecting the Custom status line preset now starts from its built-in segment layout when no segment lists are configured, while explicit empty lists still hide either side (#11577).
- Snapcompact frame-overflow rescue now replaces its superseded divider instead of rendering two contradictory before→after badges (#11607).
- Windows home launches and in-process shell paths (builtins,
ls, and redirections) now resolve/tmpto the system temporary directory instead of a drive-roottmpdirectory (#11603). - Shared-session guests can no longer fetch private advisor transcripts by agent ID.
- Fixed
/restartand worker spawning failing with ENOENT after package managers prune the unlinked previous version directory during an upgrade (#10873). - xAI web search omits relay narration even when responses include aggregate text or blank citation URLs, while preserving substantive answers.
- xAI web search no longer rejects valid aggregate answers because of non-message relay metadata.
- Advisor calls to tools it was not granted are answered in-band with the loop's
Tool <name> not foundresult instead of discarding the whole turn; only hazardous output is still quarantined, and the repeated-quarantine latch is gone. - macOS self-updates preserve executable backups still used by running sessions, preventing lost privacy-permission attribution.
- Startup and daemon commands no longer crash when project-directory canonicalization encounters EPERM or EACCES.
omp plugin install --dry-runnow previews marketplace installs without mutating plugin state.- In colocated jj-git workspaces, the status line and footer now show the JJ label (bookmark or short change ID) instead of a detached git HEAD. Git-backed automation still resolves these directories to Git (#11071, #11325 by @boazy).
- Command output from native Windows tools on Chinese (and other non-UTF-8) locales is decoded using the system ANSI code page instead of turning into replacement characters.
omp sharenow reports missing session paths instead of creating and publishing empty sessions (#11483).omp gc --blobsno longer deletes image blobs still referenced by a session stored via--session-dir/--session, including exact paths without a.jsonlsuffix; relocated transcript files are now recorded in a persistent registry the blob reachability scan reads (issue #11551).--exportnow reports missing input files instead of creating empty sessions and successful transcript-less exports (#11481).AgentLifecycleManager.global()now rebinds to the current global registry after a loneAgentRegistryreset, so a test that resets only the registry can no longer strand the lifecycle manager on a dead instance and hang the collab kill path (#11432).- Unset
advisormodel roles now honor the configured@slowfallback without inheriting an unconfigured primary model (#11428). - Unknown-context-window providers (e.g. a custom/self-hosted OpenAI-compatible profile the model registry has no metadata for) no longer permanently dead-end on a non-media payload-rejection 413 when a usable compaction method is configured; the session now gets the same promotion/compaction attempt a known-window overflow would (#11479).
- The
set_auto_compactionandset_auto_retryRPC commands are now session-scoped likeset_thinking_level, so a short-lived RPC client no longer silently writescompaction.enabled/retry.enabledto the machine-globalconfig.yml(#11431). - Closing an idle terminal whose draft was resumed and materialized into a real conversation by another terminal no longer deletes that conversation; the close-time draft GC now re-reads the session file before dropping it (#11497).
- RPC output spills to temporary disk storage for slow readers instead of retaining an unbounded memory queue, and drains final responses before shutdown.
- Large session records load faster without repeatedly copying unfinished JSONL rows.
omp updatenow bypasses mise'sminimum_release_agegate when updating via mise, so a fresh release published within the freshness window (24h by default) installs instead of being silently skipped (#11316).- Bounded reads of large files no longer report a partial scan count as the exact file line total (#11417).
- Alt+Up (dequeue) now pops only the last queued message back into the composer instead of draining the entire queue, so pressing it no longer destroys composer work (#11402).
- Large collab snapshots now stream in order through slow connections; an overloaded live queue ends sharing explicitly instead of silently losing updates or commands.
- A collab guest that disconnects mid-snapshot, or a host that reconnects into a recreated room, no longer leaves stale snapshot frames at the head of the shared send queue delaying every other guest's welcome.
- Fixed a collab authorization bypass: after a host reconnect the relay reissues guest ids from 1, and the host kept the previous ids' write permissions, so a client holding only the read-only view link could take a reissued id and run prompts, interrupts, agent commands or answer host prompts without ever joining.
- A host prompt awaiting a collab guest's answer no longer hangs when the host reconnects: the relay closes everyone who could answer, so the request now resolves as unavailable instead of waiting forever or being re-posed to whoever joins next.
- LSP semantic queries (references, definition, rename, hover) now reconcile an already-open document with disk before running, so an external edit that shifts lines no longer resolves the query against the server's stale document and returns a different symbol (#11416).
- Antigravity usage views now show the shared Claude/GPT five-hour and weekly quotas once per account instead of duplicating Anthropic and OpenAI rows (#11268).
- Fixed spelling typo underlines painting solid black bars over composer text in Apple Terminal, which does not implement colon-subparameter styled underlines. Terminals without that capability now use a flat underline. kitty, Ghostty, WezTerm, and iTerm2 version 3.5 or later keep the red curly underline.
- Fixed a
/moveor cross-project resume completing before memory was rebound, so the next prompt could recall and retain against the previous project's Hindsight bank, the destination project'smemory.backendand Hindsight server were ignored, and a failed rebind was reported as a successful move. Cwd rebinding drains Mnemopi extractions without auto-retaining the transcript during move or rollback, and rejects moves when destination Mnemopi startup fails. - Hide unavailable Hindsight memory tools after moving to a project without an effective Hindsight URL.
- Keep memory disabled in restricted SDK sessions after
/moveand/wt. - Clear source-bank recall and mental-model context before Hindsight cwd rebinding completes.
- Fixed effort-specific retry fallback chains selecting the wrong chain by object/YAML order: a
model:lowselector no longer matches a configuredmodel:maxkey (or vice versa), so a 429 retry stays on the same effort instead of escalating to an unrelated chain (#11192). - Fixed
computer.capabilities()returningundefinedwhen called before anycomputer.run; the direct helper now fetches fresh backend and permission state from the desktop worker instead of a run-populated cache (#11169). - Editor shortcuts for thinking visibility, history search, external editing, and tool activity now work while the Ask dialog has focus (#11213).
- Uninstalling a locally linked plugin now removes its
node_modulessymlink, so a later registry install cannot continue running the linked checkout (#11172). - Fixed a user-invoked
/skill:submission rendering two identical skill cards when the optimistic row retired into scrollback before the canonical message arrived during a slow preflight (#11217). - Fixed
.astrofiles rendering without syntax highlighting in write/edit previews and diffs: a vendored Astro grammar now highlights the---frontmatter and{…}template expressions as TypeScript and the template as HTML, instead of treating the whole file as HTML text (#11164 by @byigitt). - Credential-shaped tokens are now redacted before the
mnemopibackend persists a memory, covering theretain/learntools, the automatic transcript retention path, andmemory_edit update. Previously only thelocalandsharpshooterbackends redacted, so a token pasted into a session could be stored verbatim and handed to any provider by a laterrecall. - Fixed
/tanforking a mid-turn parent leaving the clone showing the parent's in-flight tool call as its own unresolved work: the fork now pairs the parent's unresolved tool call with a synthetic aborted result so the clone inherits a terminal, well-formed transcript (#11118). - Antigravity image generation now uses the image model advertised for the connected account instead of silently falling back after a stale-model 404 (#11106).
/tankeeps its assigned request after automatic compaction instead of returning an empty-request question (#11119).plugin doctornow flags a plugin whoseomp-plugins.lock.jsonversion differs from the version installed innode_modules, instead of reporting the stale copy healthy;--fixreconciles it by reinstalling (#11090).plugin upgradeon an npm-installed plugin (e.g. a scoped@scope/pkg) now points toomp plugin install <pkg> --forceinstead of the opaque "Expected name@marketplace" parse error (#11090).plugin install --forcenow forwards the force request to Bun so stale cached package contents are actually replaced (#11090).- Fixed
retry.waitForUsageResetscheduling Z.AI and Zhipu resets eight hours late when provider responses omit the reset timestamp timezone (#11014). - Claude Code sessions without history metadata use the working directory recorded by their transcript before falling back to the encoded project folder name.
- Reassigning a reserved JS Eval global (e.g.
var fs = await import("node:fs/promises")) now persists across cells instead of silently reverting to the injected value on the next cell (#10988). - Extension provider reloads no longer remove cached models from unrelated credential-scoped providers (#10973).
- Fixed the transcript pane rendering blank under the wmux terminal multiplexer on Windows; wmux panes are now detected as a multiplexer and repaint in place instead of emitting history the pane discards (#11012).
- Cursor sessions now preserve interrupted headless turns when SIGINT or SIGTERM stops print mode (#10965).
- Codex saved resets now auto-redeem when the exhausted weekly chat window is reported in the primary limit slot (#10929).
- Fixed ACP
always-ask/writeapproval modes leaving a granted tool call stuckpending: an approved permission now runs the tool instead of re-prompting through the interactive gate that ACP clients cannot answer (#10850). - Allowed marketplace and plugin names to contain uppercase letters while rejecting case-equivalent names that would collide in caches, so Claude-compatible marketplaces like
HexRaysSA/claude-marketplaceinstall and update instead of failing withMissing or invalid field "name"(#10827). - Eval
agent()wait no longer re-emits the same settled progress snapshot as duplicate status events. - Configured LiteLLM discovery no longer exposes known task-specific models, including embedding, media, moderation, reranking, and search models, in model selectors.
- Fixed MCP tool names dropping digits, which renamed servers such as
context7(mcp__context_query_docs→mcp__context7_query_docs) and collapsed servers differing only by a digit onto the same tool names, costing one of them a tool (#10179 by @bitboxx). Usertools.approvaldeny/promptpolicies written against the old digit-stripped names keep applying to the renamed tools;allowentries and exact (non-glob)tools.xdevInlineDevicespatterns need updating to the new names. - Fixed one-shot CLI runs (
omp --help | head,omp --version | true,omp <command> | grep -m1) crashing with a fatalEPIPE: broken pipe, writewhen the stdout consumer closed early; a vanished stdout peer now exits cleanly like any other Unix tool (#10930). - Sticky
RULES.mdand other discovered rules are now re-read from disk on/clearand/new, so rules created or edited while omp is running take effect on the next session reset instead of only after a restart (#10940). - The per-line column-cap truncation notice now points to the full-output artifact (
Read artifact://<id> for full output) when the raw stream was mirrored, matching the tail-truncation notice (#10877). - The per-line column-truncation notice now names the unit it enforces —
bytesfor streamed bash/eval output,charsforread/grep— instead of always claimingchars, which overstated visible content for multibyte text (#10888). - The per-line column-truncation notice now names the unit it enforces —
bytesfor streamed bash/eval and grep output,charsforread— instead of always claimingchars, which overstated visible content for multibyte text (#10888). - A custom
modelRolesentry that references another role (e.g.fast_worker: "@task") now resolves to the referenced role's model even whenretry.modelFallbackis disabled (#10853). - Isolated task worktrees now survive agent yields and retain committed checkpoints until the agent is released (#10913).
- Fixed Ctrl+O (
app.tools.expand) in theaskdialog only expanding a truncated question header: it now also expands truncated option descriptions in place. - GitHub failures now retain structured API diagnostics, identify failed file reads, and clarify Boolean search syntax.
- Fixed
--continueresuming a session stored outside an explicit--session-dir, and a breadcrumb recorded for a different session directory suppressing session lookup inside the requested one. - Clarifying questions entered through Ask's
Otheroption are answered before the original choice is shown again (#10672 by @Giardi77). - Fixed
/collabhiding the join URL when the QR code is clipped: the one-line fallback now includes the browser link, and the status heading keeps that URL on its first row so transcript pressure cannot drop it. - Fixed Anthropic prompt-cache cold misses on session resume with multiple OAuth accounts: the account that served a session is now recorded in the session file (as a
credential_pinsha-256 of the account + org/project scope, so exports carry no plaintext identity) and re-pinned on resume with the session's effective last-use time, so a fresh process no longer re-ranks accounts by usage headroom — which systematically routed away from the just-used account and cold-missed the entire account-scoped cache prefix. Sticky routing was previously stored only in the auth store's KV cache, which is in-memory when a remote auth broker is configured. - Fixed Anthropic prompt-cache cold misses on session resume with multiple OAuth accounts: the account that served a session is now recorded in the session file (as a PII-free
credential_pinhash) and re-pinned on resume, so a fresh process no longer re-ranks accounts by usage headroom — which systematically routed away from the just-used account and cold-missed the entire account-scoped cache prefix. Sticky routing was previously stored only in the auth store's KV cache, which is in-memory when a remote auth broker is configured. - Fixed concurrent
createAgentSessioncalls with the default agent id failing initialization withAgent "Main" was replaced during session initialization— each in-process embedder (e.g. the edit benchmark runner) can now pass a private registry via the newly exportedAgentRegistry, keeping every top-level session's "Main" out of the process-global roster race. - Fixed task tool blocks duplicating their per-agent progress rows into terminal scrollback on every update: live task frames now pin the transcript live region so mid-run rows are never recorded as frozen snapshots, and a detached background task freezes its progress the moment any of its rows commit to scrollback instead of mutating committed history.
- Fixed Codex reset fireworks comparing different quota tiers or plans, preventing false celebrations when usage reports switch between Spark and base weekly limits.
- Fixed Cursor ranged-read results losing the full file byte size after applying the requested window.
- Fixed empty Codex final-stop recovery discarding an earlier commentary message when both messages shared response metadata.
- Fixed Advisor availability with providers that refuse echoed reasoning by retrying once with primary thinking stripped and surfacing persistent refusals immediately.
- Fixed
/tanagents being unable to read parent-sessionlocal://attachments by correctly resolving local protocol options against the parent session's artifacts. - Fixed Codex web search silently returning plain completions when the hosted web search tool was skipped.
- Fixed TUI collaboration guest loader not starting when joining or reconnecting mid-turn.
- Fixed multi-second TUI freezes in reftable-format repositories by moving branch resolution off the render path and adding a timeout to synchronous git spawns.
- Fixed
xd://device summaries containing control characters and exceeding size budgets by stripping control characters and bounding summaries by UTF-8 bytes. - Fixed
task.softRequestBudgetconfiguration having no effect on bundled scout and sonic subagents. - Fixed quick LSP server exits being misreported as reader failures and resolved an issue where explicit reloads were blocked by initialization backoff.
- Forced Git subprocesses to use the stable
Clocale to ensure predictable, non-interactive command output. - Fixed compatibility replay issues for pre-upgrade launch brokers evaluating xterm inside the client process.
- Fixed Advisor cost tracking in the status line across conversation boundaries, ensuring session transitions, forks, and resumes correctly restore or isolate conversation spend.
- Fixed validation failures for legacy extensions importing from the package root, which previously blocked installations.
- Fixed ACP clients (such as Zed), TUI status lines, and collaboration guests not updating when model changes occur dynamically within the agent loop.
- Fixed assistant-facing resource summaries omitting parameterized MCP resource templates, ensuring failed reads list templates alongside concrete resources.
- Fixed redundant
xd://mount notices and prompt-cache invalidation when resuming sessions or reconnecting devices. - Fixed the model picker displaying placeholder model lists instead of the actual credential-aware catalog resolved at registration.
- Fixed file corruption and snapshot mismatches when writing files through the ACP client bridge by verifying the final on-disk content after client-side post-save formatting.
- Fixed
omp ttsr testsilently evaluating source files as prose when their extensions were missing from the allowlist, and expanded the allowlist to support .NET, Shell, SQL, Zig, Dart, Scala, Elixir, and Protobuf files. - Fixed automatic light/dark theme switching in direct WezTerm sessions on macOS when DEC Mode 2031 is unsupported, and improved theme-change color responsiveness.
- Fixed configured
retry.maxDelayMsnot being forwarded into Anthropic retry handling, so over-budget server retry delays fail fast. - Added tokens-per-second throughput to RPC
get_stateresponses for non-TUI clients. - Added the RPC
set_fast_modecommand and typed TypeScript/Python client methods for live fast-mode control. - Added
fastModeEnabledandfastModeActiveto RPCget_stateresponses. - Fixed RPC fast-mode state reporting after direct Anthropic rejects
speed: "fast", while allowing explicit re-enable requests to retry priority service. - Added opt-in subagent access to
checkpoint,rewind,learn, andmanage_skillwhen explicitly listed in an agent definition'stools:frontmatter. Listing one ofcheckpoint/rewindauto-includes the other. Settings (checkpoint.enabled,autolearn.enabled) remain master toggles. - Added a
browser.cdpUrlsetting that points browser automation at an already-running CDP endpoint by default, soapp.cdp_urlno longer has to be repeated on every call. Explicitappoptions still take precedence. - Native compaction preserves provider-native success and non-authentication failure semantics while retaining authenticated cross-provider fallback when the native provider rejects credentials.
- Fixed the Cursor Pi exec bridge silently dropping frame arguments.
pi_read'soffset/limitwere ignored, so a ranged read returned the whole file;pi_grep'sliteralwas ignored, so a fixed-string search ran as a regex and matched the wrong lines; and the path/glob join produced a./-prefixed spec. Ranges are now composed ontoread's:N+Kinline selector, literal patterns are escaped, and the join usesnode:path. These areoptional int32fields, so a present0is honored rather than folded into a default:pi_readwithlimit: 0answers with empty output instead of the entire file, andpi_findwithlimit: 0clamps to 1 the way the reference client does. pi_grep'scontextandlimitare honored. Neither is expressible in the model-facinggrepschema — context width comes fromgrep.contextBefore/grep.contextAfterfixed at tool construction — so the bridge builds a per-callgrepfor frames that supply them.GrepToolaccepts these as constructor options; the model-facing schema is unchanged, and a frame that supplies neither keeps the shared instance and the session's defaults.pi_ls'slimitis still not mapped, now deliberately: it caps directory entries, while the localreadtool renders a depth-2 tree with per-directory caps and elision rows and applies a selector as a rendered line slice. Mapping it to:1+Kwould cap a different unit while appearing honored.- The legacy pi shim's regex-literal escaper and path/glob join were verbatim copies of the modern bridge's. Both paths now call the shared helpers, so the two Pi translations cannot drift.
- Fixed every Cursor
pi_editframe failing instead of editing. Two independent causes: the session dropseditfrom the tool registry for Cursor so the model uses full-filewrite, but that registry is also the exec bridge's tool source, so the native frame — which the server sends regardless of the advertised catalog — found no tool; and the retained instance followed the session's configured edit mode, whilePiEditExecArgscarriesold_text/new_textpairs that onlyreplaceaccepts (the defaulthashlinetakes a singleinputstring). The bridge now resolves areplace-mode instance through its fallback resolver, still wrapped for approval. - Fixed a
pi_grepframe carryingcontextorlimitescaping the approval gate. Honoring those fields needs a per-callgrep, and the per-call instance was built raw while every registry tool is wrapped, so such calls bypassedtools.approval.grepand the exec-tier check for SSH-targeted paths. Both bridge callsites now build it through one shared factory that applies the same wrapper. - Fixed Cursor advisors ignoring
pi_grep'scontextandlimit. Only the primary session supplied the per-callgrepfactory, so advisor frames silently fell back to session defaults. Advisors now receive the same factory, gated on the advisor actually having been grantedgrep. - Fixed Cursor advisors failing every
pi_edit. The advisor roster handed the bridge theeditinstance built for the advisor's own loop, which follows the configurededit.mode(hashlineby default) and rejects the frame'sold_text/new_textpairs — the same mode mismatch the primary bridge already fixed, on the path it missed. The exec map now substitutes areplace-mode instance, gated on the advisor actually having been grantededit, while the advisor's own loop keeps the tool it was given. - Fixed
pi_bashkilling commands that explicitly asked for no deadline.timeoutisoptional int32andbashdocuments0as "disables the command deadline", but a truthiness check folded a supplied0into unset, applying the 300s default instead. A present0now passes through; negatives, which have no local meaning and would otherwise clamp to the 1s floor, still fall back to the default. - Fixed the Cursor exec bridge granting
editandgrepto sessions that withheld them. Both bridge-only tools are constructed rather than looked up, andexecuteToolprefers a constructed override over the registry, so a restricted tool set (toolNameswithout them, orrestrictToolNames) still got a workingpi_edit/pi_grep— native frames arrive regardless of the advertised catalog. Both are now gated on the session having actually granted the tool, matching thedeleteframe's existing check (issue #5680). - Fixed Cursor advisor bridge tools bypassing approval settings. The advisor's
pi_edit/pi_grepinstances are approval-wrapped, but the wrapper readstools.approvalMode, per-tooltools.approval.<tool>policies andautoApproveonly from the execute-time tool context — which the advisor bridge never supplied, so every native advisor frame resolved asyolowith empty policies and ran past a configuredaskordeny. Advisors now receive the same context store as the primary bridge. - Fixed Cursor's
list_mcp_resources/read_mcp_resourceframes answering as though the client hosted no MCP servers. The bridge hardcoded an empty catalog andnot_found, so resources from servers the session held live connections to were invisible to the model even while the same session read them throughmcp://. Both frames now answer from the session'sMCPManager— awaiting a server's background resource discovery rather than reading the not-yet-populated cache and reporting "advertises nothing" — and a lookup failure surfaces as an error rather than an empty catalog, which would read as "asked, none exist". A read carryingdownload_pathwrites the resource to that path and answers with the path alone, per the wire contract, instead of putting the payload back in the model's context. That path arrives from the server while the general-purpose resolver deliberately honors absolute paths and.., so downloads are confined to the workspace: the resolved target and its deepest existing ancestor must stay inside it, and a target that is itself a symlink is refused. The write then opensO_NOFOLLOWand refuses a non-regular or hard-linked file before truncating, so the final component cannot be swapped for a link or an inode shared outside after the check. A parent directory replaced by a symlink mid-write is still followed; closing that needsopenat/dirfd walking, which this does not attempt. - Fixed the Cursor native
deleteframe bypassing approval settings. Unlike every other frame it removes the file directly instead of running a registry tool, so no approval wrapper sat in front of it — the bridge'sallowDirectFileMutationgrant answers whether a mutating tool was granted, which is a different question from whether the user's policy allows the call. A configuredtools.approval.delete: deny, or analways-asksession that this channel cannot prompt in, now refuses the frame and keeps the file. - Fixed Cursor download-mode resource reads bypassing the session's mutation restrictions. A
read_mcp_resourceframe carryingdownload_pathcreates and overwrites workspace files without running a registry tool — the same hole the nativedeleteframe had — so a session that withheldwrite/edit, or one whosewritetier isdeny/always-ask, still had files written. Both frames now share one grant (allowDirectFileMutation, renamed fromallowNativeDeletenow that it gates more than deletion) and onewrite-tier policy check, and the download refuses before the read so a blocked call does not fetch the resource either. The primary session derives that grant before it rewrites its registry: Cursor moveseditout of the tool map andwritemay be auto-registered later, so reading the map at bridge-construction time would have misjudged both. - Fixed
pi_lsnever reporting that a listing was clipped. The bridge read the entry cap from a flatdetails.resultLimitReached, whichglobsets butread— the tool servingpi_ls— does not: it records the cap throughOutputMetaatdetails.meta.limits.resultLimit.reached. Every capped listing therefore reached Cursor withentry_limit_reachedunset, reading as complete. Both shapes are now checked, the same way the truncation translation already handles its two producers. - Fixed a mixed-content MCP resource read reaching Cursor mislabelled. The mime type was taken from the first content item while the payload came from whichever item supplied it, so an image blob followed by a text note sent the text as
image/png. Each branch now reports the type of the part it actually sends. - Fixed
pi_read'soffset/limitreturning more lines than the frame asked for. The range is composed onto the localreadtool's inline selector, and a plain:N+Kdeliberately pads with one leading and three trailing context lines — helpful when a human reads a snippet, wrong for a caller that named an exact range: offset 5/limit 20 handed Cursor lines 4-27. Ranged Pi reads now compose:raw:N+K, which slices exactly the requested lines. - Fixed
pi_grepreturning fewer matches than it asked for when they spread across many files. The localgrepwindows results to the first 20 files and tells the caller to paginate withskip, butPiGrepExecArgshas noskipfield — so a frame asking for 100 matches over 25 one-match files got 20,match_limit_reachedunset, and advice it could not act on: output silently short and labelled complete. A search carrying a total match cap now reads enough files to satisfy it (cap+1, so a result landing exactly on the cap is distinguishable from a clipped one) and reports the cap when it actually bites. - Fixed every native
pi_editfailing after a session switched onto Cursor. The replace-modeeditinstance the frame needs was built only for sessions created on Cursor, and the tool roster is not rebuilt on a model switch — so a session that started elsewhere kept its configured-modeeditin the registry, which the bridge resolves before its fallback, and the frame'sold_text/new_textpairs failed validation against ahashlineschema. The instance is now built from theeditgrant regardless of the session's initial provider (lazily, so a session that never reaches Cursor never constructs one) andpi_editasks for it explicitly through a dedicated accessor. A session that was never grantededitis still refused. - Fixed the Cursor bridge's tool resolver being able to execute an unadvertised
edit. That resolver doubles as the agent loop's fallback for any call outside the advertised set, so servingeditfrom it meant a hallucinated call — or one naming a tool the session deselected after startup — could run a replace-mode edit the model was never offered. It is device-only again;pi_edituses its own accessor. - Fixed the legacy Cursor
readframe ignoring theoffset/limitmodern builds paginate with. Only the Pi variant composed a range, so every page of a legacy read returned the whole file (or its own truncation) and a model walking a large file never advanced past the first window. Both frames now translate a range through the same helper, and the answer setsrange_appliedto describe whether a window was actually composed. - Fixed the legacy Cursor
grepframe ignoring its paginationoffset. The localgreppaginates by file throughskipand advertises exactly that in its own "use skip=N" advice, so an unforwarded offset re-ran the identical search and answered page one for every page. The answer now reports the offset it applied inoffset_applied. - Fixed a paginated Cursor
readorgrepframe being recorded as an unpaginated one. The executed call and the transcript block are built separately, so forwarding the frame's range and page fixed only the execution: the block still showed a bare path and an unskipped search, which is what a reloaded session replays and what the next turn reasons from — a slice of a file presented as the whole thing, and results from a later window presented as page one. Both are now synthesized from the same translation that runs them, including alimit: 0read, which is recorded as the zero lines it returns rather than a whole-file read. - Fixed Cursor advisors answering every MCP resource frame as though the client hosted no servers. Only the primary bridge received the
MCPManager-backed resource adapter, so an advisor'slist_mcp_resourcesreported an empty catalog and itsread_mcp_resourceanot_foundeven though the advisor shares the session's live connections. Advisors now receive the same adapter; it is not gated on a tool grant, since reading what a server advertises is a different permission from calling one of its tools. - Fixed advisor tools bypassing the approval gate. They are built straight from the builtin table, outside the loop that wraps every registry tool, and both the advisor's own agent loop and its Cursor exec bridge (
pi_write,pi_bash) run those instances directly — so an advisor grantedwriteorbashexecuted them regardless of a configuredaskordeny. They now carry the sameExtensionToolWrapperas every other tool. - Added
mcp_notificationextension event and multi-listenerMCPManager.addNotificationListenerAPI. The runtime already received MCP server-initiated JSON-RPC notifications at the transport layer but had no path to forward them to extensions; every notification (including server-custom methods) is now delivered as{ server, method, params }after the manager's own list/update handling. For known list-change methods (notifications/tools/list_changed,notifications/resources/list_changed,notifications/prompts/list_changed) the internal refresh promise is awaited before fanout, so a listener acting ontools/list_changedsees freshgetTools(). Notifications received before any listener attaches are buffered (bounded FIFO, cap 100, drop-oldest — matchesIrcBus'sMAILBOX_CAP) and drained into the first subscriber, so startup-time frames aren't lost even if the extension binds after MCP discovery. Extensions can use this to bridge push-capable MCP servers (e.g. peer messaging) into session behavior by injecting a mid-turn steer viapi.sendMessage/pi.sendUserMessage. - Fixed Advisor notes appending stale-review-window warnings when newer primary turns are queued during a review.
- Fixed layout padding alignment issues in bordered output blocks and web-search result panels.
- Fixed excluded web search providers remaining visible in the Web Search Provider Order settings list.
- Fixed internal Hub peer messages being exposed as ordinary tool-call updates in clients like Paseo.
- Fixed compatibility issues when installing legacy pi extensions by updating the legacy shim to correctly bridge missing runtime symbols and exports (such as isContextOverflow, isRetryableAssistantError, and JSON parsing utilities).
- Fixed an issue where routine daemon operations (like list, logs, stop, or describe) could inadvertently trigger a restart loop for detached daemons in a backoff window.
- Fixed marketplace plugin MCP discovery to correctly honor the mcpServers manifest field in plugin configuration files.
- Fixed user-initiated shell executions (! and $) being misattributed as agent actions in advisor transcripts.
- Fixed unnecessary prompt-cache invalidations by preserving the active auto-thinking effort level when per-turn classification fails.
- Fixed the omp process name showing up as bun in Linux process managers (like ps and top).
- Fixed agent shell commands inheriting environment variables from the launch directory's .env file, ensuring they only receive the parent environment and explicit tool overrides.
- Fixed the /new command retaining completed or failed async jobs from the previous session.
- Improved error handling in omp update to display a friendly timeout message if the download times out while streaming the binary.
- Fixed the write tool incorrectly treating semicolon-joined read selectors as filesystem paths and creating unintended directory structures.
- Fixed omp worktree clear prematurely deleting active task-isolation sandboxes owned by running subagents.
- Fixed /vibe mode preventing the director from completing parent tasks after verifying worker results by keeping the built-in todo tool active.
- Fixed numeric GitHub issue and pull request autocomplete being suppressed inside skill slash-command arguments.
- Restoring a prompt with image attachments via esc-esc branch or
/treenow re-attaches the images to the composer draft: previously only the text (with its[Image #N]markers) was restored, so resubmitting sent the literal marker with no image. - Fixed large bash/eval/ssh output citing two different artifact ids in one result — the truncation notice said
Read artifact://N for full outputwhile the footer saidArtifact: N+1. The streaming sink's head and tail windows each had a full budget, so a middle-elided inline body could reachheadBytes + spillThresholdand always re-tripped the final-defense inline byte cap, which truncated a second time (two elision markers), saved a duplicate already-truncated artifact, and left the notice's line ranges stale. The head and tail windows now share the spill-threshold budget (head clamped to half), the cap budget derives from the configured threshold plus notice slack, and when the cap does fire on a sink-spilled result it references the existing raw artifact instead of saving a copy. - Fixed a disabled higher-priority MCP server no longer disabling a same-named lower-priority one: disabled servers are now suppressed after key-level dedupe instead of dropped before it, so a project
foowithenabled: falsekeeps the user-levelfoooff while still not starving a differently-named equivalent connection. - Fixed the MCP tool-name collision winner flipping when the current owner reconnects: the winner is now chosen by a stable server+tool key instead of tool-array insertion order, which reconnects reorder.
- Fixed MCP resources with custom URI schemes being treated as missing filesystem paths.
readandomp readnow resolve server-advertised native resource URIs such asags://capabilities/current-host, while preserving the existingmcp://<resource-uri>form. - Fixed three gaps in native MCP resource URI resolution: server-advertised URIs whose path is exactly
/(e.g.catalog://root/) are now preserved byte-for-byte instead of losing the trailing slash to reconstruction; opaque resource URIs (urn:example:document,custom:item) are recognized by thereadandomp readresolver gates instead of falling through to filesystem handling; and a failingresources/templates/listno longer discards a successfulresources/list, which previously produced a false missing-resource error. - Fixed custom LSP servers sending
languageId: "plaintext"for extensions outside the built-in language map by honoring an optional per-serverlanguageIdinlsp.jsonfor disk and in-memory document opens (#6800). - Fixed interactive extension confirmations ignoring
dialogOptions, and cancelled handler-owned dialogs when the extension watchdog times out so stale approval UI cannot outlive a blocked tool call (#6805). - Fixed the per-handler extension context snapshotting the live
ctx.modelgetter, so a handler callingpi.setModel()and then readingctx.modelsaw the stale model; the scoped context now delegates to the base context instead of spreading it. - Fixed Python cell errors (
$commands and the eval tool) leaking runner-internal traceback frames. Cell syntax errors now render as the bare caret display with a<cell>filename instead of a_handle_request_async/ast.parsestack dump, and runtime tracebacks start at user code, matching the Ruby runner's user-frame filtering. - Dropped unavailable forced tool choices through the queue rejection lifecycle and discarded their remaining sequence yields so a skipped force cannot disable tools on the next request (#6543 by @paralin).
- Fixed identical MCP server connections discovered under direct and marketplace-plugin names spawning twice and duplicating mounted tool routes; distinct tools whose server names sanitize to the same route now keep the first registration and log both origins (#6786).
- Fixed
/usageand the other large transcript command panels (/session,/advisor status,/jobs,/changelog,/context,/memory view) duplicating in native scrollback when invoked while an agent turn is streaming. These callsites mounted their finalized panel immediately viapresent()instead of deferring it until the turn ends viapresentCommandOutput()(the path added in #5427 for/tools//mcp), so the panel landed above a still-growing live block and was recommitted lower down (#6767). - Fixed plan-mode task subagents unregistering extension-provided models, credentials, managers, and custom APIs from the shared parent
ModelRegistrywhen restricted sessions intentionally skip extension loading (#6783). - Fixed
/livesideband WebSockets ignoring standard proxy environment variables andNO_PROXY, which left proxied sessions stuck while the rest of the Codex connection succeeded (#6770). - Fixed the bash tool's
killbuiltin rejecting numeric signals and multiple process operands, stopping after the first failed target, and defaulting toSIGKILLinstead of the standardSIGTERM. Negative PID operands (process groups perkill(2)) and the--end-of-options marker are now handled instead of being misparsed as signals (#6779). - Fixed
learned.mdsaves growing a blank line on every write (trailing-newline split artifact) and hoisting all headings/prose above all bullets, which re-scoped lessons under the wrong heading in hand-organized files. Saves are now byte-idempotent and preserve mixed Markdown ordering: non-list lines keep their positions, new lessons insert newest-first at the head of the first bullet run, and dedupe/cap operate on bullet lines in place. - Fixed DeepSeek V4 Flash and Step 3.7 Flash models using hashline edit mode by default despite repeatedly misreading its range grammar; both now use the simpler replace-mode fallback unless explicitly overridden (#6671).
- Fixed an Ask form appearing while the main prompt contains a draft hiding that text and consuming the next in-flight keystroke. The draft now remains visible and keeps receiving input until it is submitted or cleared; only then do form controls activate (#6737).
- Fixed
globrejecting safememory://root/<directory>/**patterns. Memory globs now resolve their directory prefix inside the project memory root while rejecting traversal and percent-encoded path separators across the complete glob path. - Fixed
omp --resume <id>prompting to fork sessions from another existing directory instead of switching the process and cwd-scoped settings into the resumed session's recorded directory (#6752). - Fixed deferred CLI model roles resolving ambiguous bare model IDs to a preferred but unauthenticated provider instead of the authenticated provider selected by the eager path (#6727).
- Fixed Windows sessions crashing with an unhandled
EPIPE: broken pipe, writewhen an LSP server closed its stdin between filesystem mutations; LSP writes now observe asynchronousFileSink.write()failures and route them through the existing request/notification failure path. - Fixed the bash tool's
statbuiltin failing on native Windows withstat: unsupported on this platform(exit 1) for every invocation. The vendoreduu-statnow ships a Windows-native backend that maps the GNU format directives ontostd::fs::Metadata, thewindows_by_handlemetadata extensions (inode, hard-link count, and device viaGetFileInformationByHandle), and the Win32 volume APIs for--file-systemmode; Unix behavior is unchanged (#6723). - Fixed auto-retry wedging the session after an assistant-tail removal miss: when a context rebuild recreated the failed turn's message object, the identity-keyed cleanup logged
assistant removal missedbut the retry still scheduledcontinue(), which rejected the terminal assistant error message locally (Cannot continue from message role: assistant) before any provider request —auto_retry_endnever fired, the TUI kept showing retry progress, and the in-flightprompt()hung until a manual follow-up. The retry path now strips a still-failed assistant tail positionally after the backoff, and a continuation that still fails locally closes the retry saga with a failedauto_retry_end(#5382). - Fixed native Anthropic web-search history being recursively truncated during session persistence or retained under a different user turn, preserving opaque replay bytes across reload and stripping them on reparent (#6703).
- Fixed malformed or temporarily unreadable
config.ymlfiles being treated as empty settings and then overwritten by the next setting change, which could permanently erase broker tokens, model roles, and provider configuration. Invalid YAML is now moved to a timestamped.broken-*backup, read failures abort without touching the source, pending changes remain retryable with the last successfully loaded settings, atomic writes preserve symlink targets and handle WindowsEPERMreplacement, concurrent startup failures are fully observed and quarantine races fail closed, andomp config set/resetwaits for persistence before reporting success. - Fixed mounted MCP tools being hard to invoke when server or plugin guidance names their original calls: sessions now include one bounded, exact original-name-to-
xd://route map for every live mounted MCP tool—including servers without initialize instructions—and refresh it as catalogs change without disabling schema virtualization. - Fixed
inspect_imageblocking indefinitely when the vision-model API stalls by combining the caller's abort signal with anAbortSignal.timeout()and surfacing a distinct timeoutToolError(separate from user-triggered abort) (#4165). - Fixed MiMo models using hashline edit mode by default despite needing the same replace-mode fallback as Kimi. (#3772)
- Fixed
omprefusing to start on Windows when nobash.exeis discoverable — most visibly with scoop-installed Git, whose manifest shimssh.exe/git.exebut neverbash.exe, so PATH lookup missed it. Startup threwNo bash shell foundwhile merely building the bash tool description, even though bash tool commands always execute in the embedded brush-core shell and need no host bash. Shell discovery now also checksGIT_INSTALL_ROOT, scoop and per-user Git for Windows install roots, andsh.exeon PATH, then falls back tocmd.exefor the spawn-only paths (interactive PTY, ACP client terminals) instead of failing; the cmd fallback is never used to wrap user-shell commands — brush runs the POSIX line directly. - Added a selectable voice setting for
/liverealtime sessions (#6566). - Fixed pre-initialization and cross-module render crashes in magic-keyword highlights, user and assistant messages, tool execution cards, and the usage dashboard (#10864).
- Retired local title models pinned before the LFM2.5 refresh (
lfm2-350m,lfm2-700m,qwen3-0.6b,qwen2.5-0.5b,gemma-270m) now migrate to their closest current models instead of silently skipping session titles.
Removed
- Removed the dangling
MCPManager.setOnNotificationsingle-slot setter, which had no callers in the runtime. Replaced byMCPManager.addNotificationListener— multi-listener, per-listener error isolation, returns an unsubscribe function.
@oh-my-pi/collab-web
Fixed
- Browser collab guests now automatically rejoin when a transient host network drop recreates the relay room (#11858).
@oh-my-pi/pi-mnemopi
Fixed
- Fixed an explicitly invalidated memory still being returned by an identical repeat query until the recall cache expired.
- Fixed recall continuing to serve a stale, pre-embedding ranking for up to an hour after background embeddings finished, when the enhanced recall cache is enabled.
@oh-my-pi/pi-natives
Added
- Added
maxBytestoVcsGitRepo.diffTextoptions: rendering stops and the call rejects with anOutputTooLargeVcsError once the patch crosses the cap, so callers can bound the memory a large change set may consume (#11454 by @sjawhar). - Native addon embedding now rejects stale release binaries before standalone builds can package them (#11831).
- Fixed git repository discovery treating an unpopulated
.gitdirectory (noHEAD) as a checkout, which made/wtand isolated tasks fail with a raw "No such file or directory (os error 2)" instead of reporting that no Git repository was found. Discovery now skips such entries and keeps walking toward the root, matchinggit rev-parse. - Added
vcsDiscoverForDisplay(repoForDisplay): like repository discovery, but equal-root jj+git ties prefer Jujutsu for the status line and footer. Git-safe automation must keep usingvcsDiscover(#11071, #11325 by @boazy). - Shell and PTY command output on Windows now falls back from UTF-8 to the system ANSI code page (e.g. GBK on Chinese locales) instead of emitting replacement characters.
Changed
- Workspace startup scans skip excluded build directories and retain a bounded set of entries and directory rules.
- Limited newest-file searches use less memory on large directory trees when scan caching is disabled.
Fixed
- Bounded filesystem scan cache memory and prevented stale scans from repopulating the cache after file changes. (#11240 by @iliaal)
- Fixed the embedded shell and PTY sessions inheriting
GIT_DIR,GIT_WORK_TREE, and related repo-location overrides from the host process, which madegitrun in a secondary worktree mutate the primary one (#11082). - Added a vendored Astro grammar so
.astrofiles highlight the---TypeScript frontmatter and{…}template expressions instead of falling back to plain HTML (#11164 by @byigitt). - Fixed the TUI sometimes stopping repainting while the agent continued running.
- Fixed native Darwin OAuth helper compilation under sandboxed and custom build environments by respecting
$CC(#11869 by @Malix-Labs).
@oh-my-pi/omptype
Added
- Added
trim(),superRefine(), and one-argumentrecord()support to the Zod compatibility facade (#12011 by @bnivanov).
@oh-my-pi/snapcompact
Changed
historyBlocks()now resolves persisted frame payloads lazily, keeps the newest frames within a byte budget, and drops unresolved blob references instead of sending them to providers (#10227 by @lemonleks).
@oh-my-pi/omp-stats
Fixed
- Fixed the sessions API returning an encoded storage key instead of the session working directory (#12078 by @Dante-dan).
- Fixed Traces search inputs and checkbox using unthemed browser defaults, and iOS viewport zoom on search focus.
- Fixed garbage tool names from provider-side parse failures (e.g. a gateway returning the model's whole invocation text as the tool name) polluting the tools dashboard's per-tool rows and filter dropdown; such names now collapse to their leading identifier, and existing databases re-ingest cleaned on next sync.
- Reduced repeat stats-sync reads to appended transcript data while preserving service-tier accounting across restarts.
- Rebuilt stats for replaced or truncated session files instead of retaining stale totals.
- Reclaimed lingering stats dashboards from older releases using their versioned HTTP identity when process command lines are unavailable, so upgrades no longer leave
omp statsblocked by an opaque Bun listener.
@oh-my-pi/pi-tui
Added
Editor.deleteCharForward()exposes thetui.editor.deleteCharForwardoperation to hosts that resolve the chord themselves, applying the same transient-state teardown the key dispatch does (pending character jump, spelling-assist popup) and routing through Vim'sxin Normal and Visual modes.
Changed
- Inline image limits now bound Kitty graphics retained from earlier frames and fullscreen overlays; older scrollback images are evicted until replayed.
Fixed
- Enter now runs a slash command whose argument completes to a directory, instead of descending into it. (#12112 by @Huang-404-Q)
- Fixed a resize on Windows leaving the screen with a scrolled-up duplicate transcript and no visible response to input. The in-place resize path (default-on for Warp) anchors one settled repaint on a DSR round trip, but a ConPTY host owns that grid: measured on conhost, resizing the pseudoconsole re-emits its whole viewport from
CSI Hwith absolute addressing while the application writes nothing, and re-homes the cursor, so the reply reports column 1 and can never be attributed to its probe tag. ConPTY sessions now keep the alternate-screen borrow, whose settled transaction ends in theResizeScrollbackModerebuild, and skip that unattributable anchor probe — except inside a multiplexer, which answers the DSR from its own grid, and underPI_TUI_RESIZE_IN_PLACE=1, which restores the whole pre-change path (#11625 by @bse-ai). - Stopped exact-width live rows from entering native scrollback during ConPTY repaints (#9783).
- Forward delete no longer leaves the Vim Normal-mode cursor one column past the end of a line after deleting the final grapheme.
- Fixed Tabby CMD sessions enabling synchronized output from a spoofed
WT_SESSION, which caused streaming repaints to overlap when Tabby's terminal chain mishandled DEC 2026. - Extension command argument completions now refresh after typing a Space when the previous argument had no suggestions. (#11060)
- Detect the wmux Windows terminal multiplexer (
WMUX/WMUX_SURFACE_ID) so its panes take the in-place viewport repaint path instead of the direct-terminal scrollback path.
@oh-my-pi/pi-utils
Added
- Added the public
postmortem.exitProcess()utility for host-owned hard exits that must bypass temporary process-exit guards (#11789). - Added
readSseJsonOrText: likereadSseJson, but adata:frame that is not valid JSON is yielded as its raw text instead of raising aSyntaxError, so a consumer can classify a reverse proxy's plain-text throttle page (429 Too Many Requests) that arrives after the stream headers were already sent.readSseJsonis unchanged and shares the framing with it.
Fixed
- Reading an EPUB, PPTX or XLSX whose XML has a mismatched or stray end tag no longer hangs the session forever; the parser recovers and the document converts (#12018 by @kaluli123123).
- Fixed
filterChildShellEnvforwarding the host process'sGIT_DIR,GIT_WORK_TREE, and related repo-location overrides to child shells, wheregitwould ignore the command'scwd. - ACP JSON-RPC now drains accepted inbound requests on clean stdin EOF before resolving
closed, so in-flight methods such assession/newstill receive a success or explicit error response instead of being dropped on exit 0 (#11567). - Fixed provider-local usage-limit reset timestamps making
waitForUsageResetsessions resume up to eight hours late while preserving longest-window semantics for naive UTC timestamps (#11014). registerStdioDisconnectHandling()now drives graceful shutdown fromprocess.stdout's ownerrorevent, so a closed stdout consumer exits cleanly while an unrelated write EPIPE (subprocess stdin, socket) stays fatal (#10930).- Fixed Linux
ptreetimeout cleanup occasionally leaving session-escaped descendants running during subreaper adoption.
What's Changed
- fix(coding-agent): collapse whitespace in Ollama search result text by @H4vC in #12099
- fix(tui): match skill prefixes at hyphen boundaries by @domenicomassafra in #12000
- fix(coding-agent): reject --resume/--continue with --no-session by @roboomp in #12009
- fix(session): merge artifacts when moving a session into an occupied bucket by @sjawhar in #12035
- fix(advisor): preserve non-blocking notes during terminal unwind by @xiangnan0811 in #12053
- fix(ttsr): reserve deferred injections until delivery by @Dante-dan in #12065
- fix(stats): expose session cwd in summaries by @Dante-dan in #12078
- fix(coding-agent): keep mnemopi requests alive by @Dante-dan in #12079
- fix(coding-agent): attributed host and parent-agent steers to agent, recorded parentSession by @STRML in #12086
- fix(tan): wait for descendant results before completing by @ryxli in #12090
- fix(coding-agent): accept singular and plural plugin commands on the CLI and TUI by @XL-Lewis in #12092
- fix(tui): do not clear composer on inbound extension user messages by @atacolak in #12104
- fix(coding-agent): reject unpopulated child repository markers by @bobbyhuang-dev in #12105
- fix(tui): don't chain a slash command's directory argument on Enter by @Huang-404-Q in #12112
- fix(completions): read the zsh action's kind past the compadd options by @Huang-404-Q in #12113
- fix(ai): auth-gateway replays a model's own reasoning as plain text, tripping Anthropic's reasoning_extraction classifier by @Zhu-Aemon in #12115
- fix(catalog): cap Bedrock's Qwen rows at their documented output limits by @Huang-404-Q in #12117
- fix(tui): keep the location out of file hyperlink URIs by @Huang-404-Q in #12123
- fix(coding-agent): migrate retired local tiny title models to current equivalents by @H4vC in #12134
- fix(rpc): observe extension send rejections when no prompt scope is active by @sjawhar in #11654
- fix(coding-agent): build a named tool choice for OpenRouter models by @datrixlab in #11658
- fix(settings): write config.yml before renaming settings.json by @PeterPonyu in #11682
- fix(settings): clear agent.db settings after config.yml migration by @PeterPonyu in #11683
- fix(export): render nested list markup in HTML transcripts by @roboomp in #11695
- fix(coding-agent): clarify paused-plan guard warning by @roboomp in #11696
- fix(catalog): give Command Code's DeepSeek V4.1 Flash its effort ladder and image input by @aliefe04 in #11703
- fix(coding-agent): anchor persisted-revive artifacts to the revived ref's own dir by @PeterPonyu in #11706
- fix(coding-agent): enforce disabled providers for subagents by @roboomp in #11712
- fix(session): require positive evidence before moved-project re-root by @PeterPonyu in #11722
- fix(read): hyperlink grouped read tree rows like standalone rows by @roboomp in #11735
- fix(coding-agent): harvest the reporting turn for data-less subagent yields by @oldschoola in