github can1357/oh-my-pi v18.2.1

4 hours ago

@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_update snapshots 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 /clear boundaries. (#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/compact endpoint 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_extraction classifier 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 a stopReason derived 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 block after 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 expired on 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-native transport 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 error after 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 ReasoningEffort in 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_call and function_call_output, which broke round pairing on strict validators (e.g. DeepSeek) with 400 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() and completeSimple() 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: null on /v1/responses and /v1/chat/completions message 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-none reasoning 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 ENOENT when 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-flash row 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/v1 accepts only tool_choice: "auto", so none, required, and named choices (subagent final-retry yield, 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/high effort ladder for every thinking-capable model, which shadowed the per-model compat rules and made max unreachable on the DeepSeek V4 line (including the served deepseek-v4.1-flash, deepseek-v4-flash:0731, and deepseek-v4-pro:0813 ids): discovery now leaves the ladder to the rule tree, so those models advertise the wire-exact low/high/max and GLM-5.3 exposes low/high/max (#8334).
  • Fixed Meta Model API and Muse Code requests failing with 400 whenever omp forced a tool choice: api.meta.ai/v1 accepts only tool_choice: "auto", so none, required, and named choices (subagent final-retry yield, 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 xhigh and max instead of the unsupported minimal level. (#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-messages providers whose adaptive effort ladder exposes minimal sending output_config.effort: "minimal", which the Anthropic Messages API rejects with 400 level "minimal" not supported; the adaptive effort mapper now clamps minimal to low (#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.discount fraction 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 /drop slash command to /delete so 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 result content or details.displayContent instead. (#11255 by @jiwangyihao)
  • Removed the DEL, DEL.BLK, COPY, and COPY.BLK hashline edit operations. Use CUT / CUT.BLK for deletion; removed content remains available to PASTE.
  • 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 Instructions heading whenever generated blocks precede them, instead of trailing the ## MCP Server Instructions section and reading as server-supplied, unverified content (#11832 by @iacore).
  • Prewalk now arms for a hand-off target served by a models.yml discovery: provider (e.g. openai-models-list): buildSessionOptions runs a cache-aware refresh for the provider named by the selector and retries, instead of disabling prewalk with a Model "…" not found warning for ids omp models lists (#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 yield no longer fails a run with SYSTEM WARNING: Subagent called yield with null data. when a data-less useLastTurn finalize (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 with data (#11150).
  • --continue no 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-filesystem mv). A cross-filesystem mv (copy+unlink, new inode) is intentionally not re-rooted: the session stays in the original bucket, header.cwd is 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-/new revivals no longer write <id>.md outside the revived agent's tree (#11563).
  • Legacy settings.jsonconfig.yml migration now writes the YAML first and only then archives the JSON, surfaces failures instead of swallowing them, and recovers from an orphaned settings.json.bak when config.yml is missing (#11569).
  • Legacy settings.jsonconfig.yml migration 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 Slack survive /mcp reauth write-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 /mcp commands (enable, disable, test, remove, reconnect, reauth, unauth) using configured and runtime-discovered MCP servers.
  • Added CUT and PASTE ops to the hashline edit tool for moving code without retyping it: CUT N.=M (and .BLK block forms) capture lines into a clipboard register, and PASTE operations insert them. The register flows across sections within a patch (cross-file moves) and persists across edit calls per session.
  • Added --from-claude and --from-codex session imports (including compaction state for Codex), also available from /resume @claude and /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 preserving EXA_API_KEY and 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.codexResetFireworks celebrations 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_lsread, pi_bashbash, pi_editedit, pi_writewrite, pi_grepgrep, and pi_findglob. The frames are a separate wire family from the legacy args, not aliases, so each mapping is a real translation — pi_grep's ignore_case is the inverse of the local tool's case-sensitivity flag, pi_find searches filenames rather than contents, and pi_edit's replacements are renamed to the local snake_case pairs.
  • providers.autoThinkingMaxEffort (xhigh | max, default xhigh) raises the ceiling of the auto thinking classifier. max became a first-class effort tier after the classifier prompt was written, so auto could never reach it on models that expose the tier — only the ultrathink keyword could. Opting in adds max to 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 at xhigh regardless of the setting. The ceiling governs what auto resolves: a ladder with nothing underneath it yields no auto level, and a thinking.requiresEffort model 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-record TTSR rule, which catches local isRecord function and lambda definitions and directs agents to shared guards plus explicit shape validation.
  • A tool_call handler (extension or hook) can now return input to revise the arguments a tool executes with, not just block it. The returned object is the raw execution input passed to the tool (ignored when block is set, and not applied to computer tool 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. bash pty) schedules correctly. A revised nested write 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.txt reads 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. :raw still reads the original report, and files that merely carry the extension fall back to plain text.
  • Added V8 .cpuprofile support to the read tool (Node/Bun --cpu-prof, Chrome DevTools, CDP Profiler.stop output): 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. :raw still 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_image tool (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/computer calls now say what happened (open main https://…, main.id(5).click(), close all) with a globe/computer icon instead of a bare browser label; 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 rpc session 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 a history://<id> pointer) to whoever woke it, so a hub send await:true waiter 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 hub tool 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; legacy collapseChangelog choices 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, and read 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 both xd:// 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 (via jsonSchemaToTypeScript, 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 the inspect_image vision-delegation tool, modeled on /computer: on/off force the tool for the current session only, auto returns to the persisted setting, and status reports the effective mode, session override, tool state, and active-model image capability.
  • Replaced the inspect_image.enabled boolean with the tri-state inspect_image.mode (auto|on|off, default auto). In auto the 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. The read tool now follows the effective state dynamically rather than the raw setting, so it returns decoded image blocks again whenever inspect_image is hidden. Existing inspect_image.enabled: true/false configs migrate to inspect_image.mode: on/off.
  • Made the task tool's per-spawn effort parameter opt-in through task.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 SetConsoleTitleW through bun:ffi instead 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.maxEffort to 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 /login and 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 with Unknown skill by discovering configured skills before resolving the URI (#10961).
  • Subagents no longer remain running after their final result is accepted; a finished run reaches a terminal state without the parent having to send a status message (#11079).
  • Fixed /loop never 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 with ENOTEMPTY; 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, --model and the other dynamic value flags work again. (#12113 by @Huang-404-Q)
  • Leftover child .git directories 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/sse MCP 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).
  • /tan now 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: /plugin in the TUI and omp plugins on 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, RPC compact, extension ctx.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: false still 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 repeatGap has 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/--continue combined with --no-session now fail with --resume requires session persistence instead 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/chalk reimplementation instead of the undeclared npm chalk package (#12001).
  • Fixed edit.modelVariants and 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 serve now 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 implement pollExternalChanges(), 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 bench and omp if-bench rejecting models that omp models lists (e.g. llama.cpp, Ollama, LM Studio, models.yml servers) by retrying model resolution through a live discovery pass when the local cache can't restore their credentials (#11598 by @yomgui1).
  • omp --fork with a missing session path now fails with Session "<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 reporting No MCP server has resource when the connect outlasts the startup race (#11950).
  • memory://root is now advertised in URL completion only on memory.backend=local, and reading it on hindsight/mnemopi reports the file-backed root as local-only (pointing at recall/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 --resume startup (#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 reload remains the explicit in-session refresh), and volatile last_refreshed_at metadata 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).
  • /extensions now 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 context extension 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 cwd is a secondary Git worktree no longer inherit the agent's own GIT_DIR/GIT_WORK_TREE and 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 start failing with a raw connect ENOENT …/broker.sock when 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 /pin toggles 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 ExtensionExitError unhandled-rejection storm (#11789).
  • The legacy @earendil-works/pi-coding-agent shim now exports findCutPoint (adapted to upstream Pi's tokenizer-less 4-arg signature) and sessionEntryToContextMessages, so extensions targeting upstream Pi 0.84.2's compaction/session APIs (e.g. NVlabs/SoL-Pi) install instead of failing validation (#11796).
  • write now 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 resolve modelRoles.vision/@default like 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 through oauth.modifyModels (pi-provider-kiro and friends); projected models are now materialized like every other catalog source.
  • Legacy agent.db settings rows are deleted after a successful config.yml migration write, so deleting config.yml no longer silently resurrects stale values (#11568).
  • Subagents (including /vibe workers) that write their report in one turn and then finalize with a data-less yield in the next no longer come back as SYSTEM WARNING: Subagent called yield with null data stapled 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 /force and other forced tool choices refusing every OpenRouter model: buildNamedToolChoice did not recognise the openrouter api. 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 baseUrl overrides now scope by API: custom models inheriting the provider URL define which APIs it covers (a provider-level api covers override-only providers), transport: pi-native keeps its gateway baseUrl provider-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.fallbackChains when 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.modelFallback is disabled.
  • Session title generation now expands the appended active session model's own retry.fallbackChains after that model fails, without merging tiny/commit/smol role defaults onto it (#10938).
  • /export HTML 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 stale Exit 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-hint frontmatter as inline autocomplete ghost text and ACP input.hint, not only in the /extensions inspector (#11647).
  • Extensions authored against upstream Pi (e.g. pi-fabric) no longer crash every session at startup: registered tools now carry the upstream-shaped sourceInfo provenance that getAllRegisteredTools() consumers read (#11661).
  • Custom openai-responses / openai-codex-responses providers can now set compat.supportsConfigurationUpdate: false in models.yml so auto-thinking effort changes on gpt-6-astra are sent as the top-level reasoning.effort instead of a configuration_update input 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-ask with an empty policy map (no user grant) instead of silently resolving as yolo with empty policies. The former copies (ExtensionToolWrapper.execute, Cursor refuseByWritePolicy, 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 set instead of silently disappearing (#11579).
  • ast_edit, search, and ast_grep no longer fan out into overlapping scans when paths mixes a directory with a file inside it and the directory is spelled as an absolute path; ast_edit previously 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 /tmp to the system temporary directory instead of a drive-root tmp directory (#11603).
  • Shared-session guests can no longer fetch private advisor transcripts by agent ID.
  • Fixed /restart and 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 found result 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-run now 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 share now reports missing session paths instead of creating and publishing empty sessions (#11483).
  • omp gc --blobs no longer deletes image blobs still referenced by a session stored via --session-dir/--session, including exact paths without a .jsonl suffix; relocated transcript files are now recorded in a persistent registry the blob reachability scan reads (issue #11551).
  • --export now 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 lone AgentRegistry reset, 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 advisor model roles now honor the configured @slow fallback 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_compaction and set_auto_retry RPC commands are now session-scoped like set_thinking_level, so a short-lived RPC client no longer silently writes compaction.enabled/retry.enabled to the machine-global config.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 update now bypasses mise's minimum_release_age gate 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 /move or 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's memory.backend and 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 /move and /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:low selector no longer matches a configured model:max key (or vice versa), so a 429 retry stays on the same effort instead of escalating to an unrelated chain (#11192).
  • Fixed computer.capabilities() returning undefined when called before any computer.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_modules symlink, 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 .astro files 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 mnemopi backend persists a memory, covering the retain/learn tools, the automatic transcript retention path, and memory_edit update. Previously only the local and sharpshooter backends redacted, so a token pasted into a session could be stored verbatim and handed to any provider by a later recall.
  • Fixed /tan forking 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).
  • /tan keeps its assigned request after automatic compaction instead of returning an empty-request question (#11119).
  • plugin doctor now flags a plugin whose omp-plugins.lock.json version differs from the version installed in node_modules, instead of reporting the stale copy healthy; --fix reconciles it by reinstalling (#11090).
  • plugin upgrade on an npm-installed plugin (e.g. a scoped @scope/pkg) now points to omp plugin install <pkg> --force instead of the opaque "Expected name@marketplace" parse error (#11090).
  • plugin install --force now forwards the force request to Bun so stale cached package contents are actually replaced (#11090).
  • Fixed retry.waitForUsageReset scheduling 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/write approval modes leaving a granted tool call stuck pending: 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-marketplace install and update instead of failing with Missing 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_docsmcp__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). User tools.approval deny/prompt policies written against the old digit-stripped names keep applying to the renamed tools; allow entries and exact (non-glob) tools.xdevInlineDevices patterns need updating to the new names.
  • Fixed one-shot CLI runs (omp --help | head, omp --version | true, omp <command> | grep -m1) crashing with a fatal EPIPE: broken pipe, write when the stdout consumer closed early; a vanished stdout peer now exits cleanly like any other Unix tool (#10930).
  • Sticky RULES.md and other discovered rules are now re-read from disk on /clear and /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 — bytes for streamed bash/eval output, chars for read/grep — instead of always claiming chars, which overstated visible content for multibyte text (#10888).
  • The per-line column-truncation notice now names the unit it enforces — bytes for streamed bash/eval and grep output, chars for read — instead of always claiming chars, which overstated visible content for multibyte text (#10888).
  • A custom modelRoles entry that references another role (e.g. fast_worker: "@task") now resolves to the referenced role's model even when retry.modelFallback is 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 the ask dialog 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 --continue resuming 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 Other option are answered before the original choice is shown again (#10672 by @Giardi77).
  • Fixed /collab hiding 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_pin sha-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_pin hash) 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 createAgentSession calls with the default agent id failing initialization with Agent "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 exported AgentRegistry, 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 /tan agents being unable to read parent-session local:// 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.softRequestBudget configuration 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 C locale 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 test silently 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.maxDelayMs not being forwarded into Anthropic retry handling, so over-budget server retry delays fail fast.
  • Added tokens-per-second throughput to RPC get_state responses for non-TUI clients.
  • Added the RPC set_fast_mode command and typed TypeScript/Python client methods for live fast-mode control.
  • Added fastModeEnabled and fastModeActive to RPC get_state responses.
  • 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, and manage_skill when explicitly listed in an agent definition's tools: frontmatter. Listing one of checkpoint/rewind auto-includes the other. Settings (checkpoint.enabled, autolearn.enabled) remain master toggles.
  • Added a browser.cdpUrl setting that points browser automation at an already-running CDP endpoint by default, so app.cdp_url no longer has to be repeated on every call. Explicit app options 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's offset/limit were ignored, so a ranged read returned the whole file; pi_grep's literal was 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 onto read's :N+K inline selector, literal patterns are escaped, and the join uses node:path. These are optional int32 fields, so a present 0 is honored rather than folded into a default: pi_read with limit: 0 answers with empty output instead of the entire file, and pi_find with limit: 0 clamps to 1 the way the reference client does.
  • pi_grep's context and limit are honored. Neither is expressible in the model-facing grep schema — context width comes from grep.contextBefore/grep.contextAfter fixed at tool construction — so the bridge builds a per-call grep for frames that supply them. GrepTool accepts 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's limit is still not mapped, now deliberately: it caps directory entries, while the local read tool 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+K would 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_edit frame failing instead of editing. Two independent causes: the session drops edit from the tool registry for Cursor so the model uses full-file write, 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, while PiEditExecArgs carries old_text/new_text pairs that only replace accepts (the default hashline takes a single input string). The bridge now resolves a replace-mode instance through its fallback resolver, still wrapped for approval.
  • Fixed a pi_grep frame carrying context or limit escaping the approval gate. Honoring those fields needs a per-call grep, and the per-call instance was built raw while every registry tool is wrapped, so such calls bypassed tools.approval.grep and 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's context and limit. Only the primary session supplied the per-call grep factory, so advisor frames silently fell back to session defaults. Advisors now receive the same factory, gated on the advisor actually having been granted grep.
  • Fixed Cursor advisors failing every pi_edit. The advisor roster handed the bridge the edit instance built for the advisor's own loop, which follows the configured edit.mode (hashline by default) and rejects the frame's old_text/new_text pairs — the same mode mismatch the primary bridge already fixed, on the path it missed. The exec map now substitutes a replace-mode instance, gated on the advisor actually having been granted edit, while the advisor's own loop keeps the tool it was given.
  • Fixed pi_bash killing commands that explicitly asked for no deadline. timeout is optional int32 and bash documents 0 as "disables the command deadline", but a truthiness check folded a supplied 0 into unset, applying the 300s default instead. A present 0 now 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 edit and grep to sessions that withheld them. Both bridge-only tools are constructed rather than looked up, and executeTool prefers a constructed override over the registry, so a restricted tool set (toolNames without them, or restrictToolNames) still got a working pi_edit/pi_grep — native frames arrive regardless of the advertised catalog. Both are now gated on the session having actually granted the tool, matching the delete frame's existing check (issue #5680).
  • Fixed Cursor advisor bridge tools bypassing approval settings. The advisor's pi_edit/pi_grep instances are approval-wrapped, but the wrapper reads tools.approvalMode, per-tool tools.approval.<tool> policies and autoApprove only from the execute-time tool context — which the advisor bridge never supplied, so every native advisor frame resolved as yolo with empty policies and ran past a configured ask or deny. Advisors now receive the same context store as the primary bridge.
  • Fixed Cursor's list_mcp_resources/read_mcp_resource frames answering as though the client hosted no MCP servers. The bridge hardcoded an empty catalog and not_found, so resources from servers the session held live connections to were invisible to the model even while the same session read them through mcp://. Both frames now answer from the session's MCPManager — 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 carrying download_path writes 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 opens O_NOFOLLOW and 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 needs openat/dirfd walking, which this does not attempt.
  • Fixed the Cursor native delete frame 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's allowDirectFileMutation grant answers whether a mutating tool was granted, which is a different question from whether the user's policy allows the call. A configured tools.approval.delete: deny, or an always-ask session 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_resource frame carrying download_path creates and overwrites workspace files without running a registry tool — the same hole the native delete frame had — so a session that withheld write/edit, or one whose write tier is deny/always-ask, still had files written. Both frames now share one grant (allowDirectFileMutation, renamed from allowNativeDelete now that it gates more than deletion) and one write-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 moves edit out of the tool map and write may be auto-registered later, so reading the map at bridge-construction time would have misjudged both.
  • Fixed pi_ls never reporting that a listing was clipped. The bridge read the entry cap from a flat details.resultLimitReached, which glob sets but read — the tool serving pi_ls — does not: it records the cap through OutputMeta at details.meta.limits.resultLimit.reached. Every capped listing therefore reached Cursor with entry_limit_reached unset, 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's offset/limit returning more lines than the frame asked for. The range is composed onto the local read tool's inline selector, and a plain :N+K deliberately 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_grep returning fewer matches than it asked for when they spread across many files. The local grep windows results to the first 20 files and tells the caller to paginate with skip, but PiGrepExecArgs has no skip field — so a frame asking for 100 matches over 25 one-match files got 20, match_limit_reached unset, 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_edit failing after a session switched onto Cursor. The replace-mode edit instance 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-mode edit in the registry, which the bridge resolves before its fallback, and the frame's old_text/new_text pairs failed validation against a hashline schema. The instance is now built from the edit grant regardless of the session's initial provider (lazily, so a session that never reaches Cursor never constructs one) and pi_edit asks for it explicitly through a dedicated accessor. A session that was never granted edit is 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 serving edit from 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_edit uses its own accessor.
  • Fixed the legacy Cursor read frame ignoring the offset/limit modern 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 sets range_applied to describe whether a window was actually composed.
  • Fixed the legacy Cursor grep frame ignoring its pagination offset. The local grep paginates by file through skip and 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 in offset_applied.
  • Fixed a paginated Cursor read or grep frame 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 a limit: 0 read, 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's list_mcp_resources reported an empty catalog and its read_mcp_resource a not_found even 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 granted write or bash executed them regardless of a configured ask or deny. They now carry the same ExtensionToolWrapper as every other tool.
  • Added mcp_notification extension event and multi-listener MCPManager.addNotificationListener API. 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 on tools/list_changed sees fresh getTools(). Notifications received before any listener attaches are buffered (bounded FIFO, cap 100, drop-oldest — matches IrcBus's MAILBOX_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 via pi.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 /tree now 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 output while the footer said Artifact: N+1. The streaming sink's head and tail windows each had a full budget, so a middle-elided inline body could reach headBytes + spillThreshold and 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 foo with enabled: false keeps the user-level foo off 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. read and omp read now resolve server-advertised native resource URIs such as ags://capabilities/current-host, while preserving the existing mcp://<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 the read and omp read resolver gates instead of falling through to filesystem handling; and a failing resources/templates/list no longer discards a successful resources/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-server languageId in lsp.json for 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.model getter, so a handler calling pi.setModel() and then reading ctx.model saw 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.parse stack 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 /usage and 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 via present() instead of deferring it until the turn ends via presentCommandOutput() (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 ModelRegistry when restricted sessions intentionally skip extension loading (#6783).
  • Fixed /live sideband WebSockets ignoring standard proxy environment variables and NO_PROXY, which left proxied sessions stuck while the rest of the Codex connection succeeded (#6770).
  • Fixed the bash tool's kill builtin rejecting numeric signals and multiple process operands, stopping after the first failed target, and defaulting to SIGKILL instead of the standard SIGTERM. Negative PID operands (process groups per kill(2)) and the -- end-of-options marker are now handled instead of being misparsed as signals (#6779).
  • Fixed learned.md saves 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 glob rejecting safe memory://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, write when an LSP server closed its stdin between filesystem mutations; LSP writes now observe asynchronous FileSink.write() failures and route them through the existing request/notification failure path.
  • Fixed the bash tool's stat builtin failing on native Windows with stat: unsupported on this platform (exit 1) for every invocation. The vendored uu-stat now ships a Windows-native backend that maps the GNU format directives onto std::fs::Metadata, the windows_by_handle metadata extensions (inode, hard-link count, and device via GetFileInformationByHandle), and the Win32 volume APIs for --file-system mode; 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 missed but the retry still scheduled continue(), which rejected the terminal assistant error message locally (Cannot continue from message role: assistant) before any provider request — auto_retry_end never fired, the TUI kept showing retry progress, and the in-flight prompt() 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 failed auto_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.yml files 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 Windows EPERM replacement, concurrent startup failures are fully observed and quarantine races fail closed, and omp config set/reset waits 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_image blocking indefinitely when the vision-model API stalls by combining the caller's abort signal with an AbortSignal.timeout() and surfacing a distinct timeout ToolError (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 omp refusing to start on Windows when no bash.exe is discoverable — most visibly with scoop-installed Git, whose manifest shims sh.exe/git.exe but never bash.exe, so PATH lookup missed it. Startup threw No bash shell found while 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 checks GIT_INSTALL_ROOT, scoop and per-user Git for Windows install roots, and sh.exe on PATH, then falls back to cmd.exe for 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 /live realtime 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.setOnNotification single-slot setter, which had no callers in the runtime. Replaced by MCPManager.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 maxBytes to VcsGitRepo.diffText options: rendering stops and the call rejects with an OutputTooLarge VcsError 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 .git directory (no HEAD) as a checkout, which made /wt and 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, matching git 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 using vcsDiscover (#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 made git run in a secondary worktree mutate the primary one (#11082).
  • Added a vendored Astro grammar so .astro files 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-argument record() 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 stats blocked by an opaque Bun listener.

@oh-my-pi/pi-tui

Added

  • Editor.deleteCharForward() exposes the tui.editor.deleteCharForward operation 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's x in 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 H with 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 the ResizeScrollbackMode rebuild, and skip that unattributable anchor probe — except inside a multiplexer, which answers the DSR from its own grid, and under PI_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: like readSseJson, but a data: frame that is not valid JSON is yielded as its raw text instead of raising a SyntaxError, 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. readSseJson is 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 filterChildShellEnv forwarding the host process's GIT_DIR, GIT_WORK_TREE, and related repo-location overrides to child shells, where git would ignore the command's cwd.
  • ACP JSON-RPC now drains accepted inbound requests on clean stdin EOF before resolving closed, so in-flight methods such as session/new still receive a success or explicit error response instead of being dropped on exit 0 (#11567).
  • Fixed provider-local usage-limit reset timestamps making waitForUsageReset sessions resume up to eight hours late while preserving longest-window semantics for naive UTC timestamps (#11014).
  • registerStdioDisconnectHandling() now drives graceful shutdown from process.stdout's own error event, so a closed stdout consumer exits cleanly while an unrelated write EPIPE (subprocess stdin, socket) stays fatal (#10930).
  • Fixed Linux ptree timeout 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

Don't miss a new oh-my-pi release

NewReleases is sending notifications on new releases.