Changes
-
CI: add a non-blocking
plugin-inspector-advisoryartifact to Plugin Prerelease so release runs capture bundled plugin compatibility triage without changing the blocking gate. -
Runtime/Fly: detect Fly Machines as container environments from their runtime env vars, so gateway bind and Bonjour defaults match remote container launches. (#80209) Thanks @liorb-mountapps.
-
Providers/fal: route GPT Image 2 and Nano Banana 2 reference-image edit requests to
/editwithimage_urlsarray, enforce NB2 edit geometry usingaspect_ratioandresolutionparams, lift Fal edit mode input-image caps to 10 for GPT Image 2 and 14 for Nano Banana 2, and allow aspect-ratio hints in edit mode. (#77295) Thanks @leoge007. -
Control UI: show a plain HTML recovery panel when the app module never registers, giving blank dashboard pages a retry path and browser-extension troubleshooting link. Fixes #44107. Thanks @BunsDev.
-
Build: enable additional low-churn oxlint rules for promise, TypeScript, and runtime footgun checks.
-
Build: enable stricter Vitest lint rules for focused, disabled, conditional, hook, matcher, and expectation hazards.
-
Build: pin explicit oxfmt defaults in the shared formatter config to keep formatting behavior stable across upgrades.
-
TypeScript: enable stricter compiler checks for implicit returns, side-effect imports, overrides, and unused production code.
-
Logging: add targeted model transport, payload, SSE, and code-mode diagnostics with redacted URL handling.
-
Agents: allow
session.agentToAgent.maxPingPongTurnsup to 20 while keeping the default at 5 for longer agent-to-agent reply chains. Fixes #52382. (#52400) Thanks @thirumaleshp. -
Agents: add per-agent
tools.message.crossContextoverrides so sandboxed/public agents can restrict message sends to the current conversation without changing the global bot policy. -
Agents: add per-agent
tools.message.actions.allowoverrides so sandboxed/public agents can expose and enforce send-only message tools. -
Agents: omit the sandbox workspace marker from compact command progress previews while keeping internal sandbox diagnostics unchanged.
-
Agents: widen progress draft command preview lines by 50% so Discord inline tool updates preserve more useful command context.
-
Codex app-server: retire timed-out app-server clients after bounded turn interrupts so Discord agents do not reuse a CPU-spinning Codex process after an attempt timeout.
-
Build: upgrade workspace package management to pnpm 11 and keep Docker, install, update, and release workflows on the pnpm 11 config surface. (#79414) Thanks @altaywtf.
-
Build: align Telegram QA workflows and git source installs with the pnpm 11 workspace build allowlist surface. (#80588) Thanks @altaywtf.
-
Models: add provider-level
localServicestartup for on-demand local model servers before OpenAI-compatible requests, including one-shot model probes. -
Agents: trim default system prompt guidance and send-only message tool schemas to reduce prompt tokens while preserving GPT-5 personality guidance.
-
Context: add
/context mapto send a treemap image of the current session context contributors. (#79867) -
Slack: add
unfurlLinksandunfurlMediaconfig for botchat.postMessagereplies, including per-account overrides, so Slack link and media previews can be suppressed without workspace-wide settings. Fixes #48435. (#80145) Thanks @esegev1 and @HemantSudarshan. -
Slack: add explicit
replyBroadcastsupport for text and Block Kit thread replies so agents can opt into Slack's parent-channelreply_broadcastbehavior. (#64365) Thanks @tony88331. -
Slack: preserve mention target/source metadata in inbound prompt context so agents can distinguish direct bot mentions from implicit thread wakes that mention someone else. Fixes #79025. (#75356) Thanks @tmimmanuel.
-
Slack: canonicalize outbound delivery-mirror routes for native DM channel IDs to the peer user session so
message.sendcalls toD...targets do not split the same Slack DM thread into a channel session. Fixes #80091. (#80111) Thanks @bek91. -
Plugin SDK: deprecate public subpaths that existed for at least one month and have no bundled extension production imports, keep legacy barrel/test/zod subpath package exports for backwards compatibility, and track both sets in the SDK surface report.
-
Plugin SDK: deprecate public subpaths currently used by only one or two bundled plugin owners, keeping them importable while steering new plugin code to focused shared SDK seams or plugin-owned APIs.
-
Plugin SDK: remove the owner-specific
provider-auth-loginpublic subpath after moving Chutes, GitHub Copilot, and OpenAI Codex auth flows back to provider-owned modules. -
Plugin SDK: remove provider-specific model, stream, and xAI compatibility helpers from public exports after moving bundled callers to provider-owned modules.
-
Plugin SDK: expose runtime-supplied active model metadata to native plugin tool factories for diagnostics and plugin-owned policy decisions. Fixes #77857. Thanks @jamiezigelbaum.
-
QA/Mantis: add Telegram live PR evidence automation with Convex-leased credentials, Crabbox transcript capture, motion GIF previews, and inline PR comments.
-
QA/Mantis: add a Telegram desktop scenario builder that leases Crabbox, installs native Telegram Desktop, configures an OpenClaw Telegram gateway with leased bot credentials, and records VNC screenshot/video artifacts.
-
Discord/voice: add realtime voice diagnostics for speaker turns, playback resets, barge-in detection, and audio cutoff analysis.
-
Talk: add
talk.realtime.instructionsso operators can append realtime voice style instructions while preserving OpenClaw's built-in agent-consult guidance. (#79081) Thanks @VACInc. -
Discord/voice: default test and source installs to the pure-JS
opusscriptdecoder by ignoring optional native@discordjs/opusbuilds, avoiding slow native addon compiles outside dedicated voice-performance lanes. -
Discord/voice: add an opt-in native
@discordjs/opusinstall script and decoder preference for live voice-performance lanes without charging unrelated Docker/tests for native addon builds. -
Discord/voice: add
voice.allowedChannelsto restrict voice joins and bot voice-state moves to configured channels while preserving open voice behavior when unset. -
Gateway/skills: add an opt-in private skill archive upload install path gated by
skills.install.allowUploadedArchives, so trusted Gateway clients can stage and install zip-backed skills only when operators explicitly enable the code-install surface. (#74430) Thanks @samzong. -
Codex app-server: enable Codex native code-mode-only for harness threads so deferred OpenClaw dynamic tools run through Codex's own searchable code execution surface instead of a PI-style wrapper.
-
Dependencies: refresh workspace pins and patch targets, including ACPX
@agentclientprotocol/claude-agent-acp0.33.1, Codex ACP0.14.0, Baileys7.0.0-rc10, Google GenAI2.0.1, OpenAI6.37.0, AWS SDK3.1045.0, Kysely0.29.0, Tlon skill0.3.6, Aimock1.19.5, and tsdown0.22.0. -
Dependencies: move embedded Pi packages to the
@earendil-worksnamespace, refresh Twitch Twurple packages, and move@openclaw/fs-safefrom the GitHub release pin to the published npm package. -
Build: route Testbox changed-check delegation through Crabbox and remove the OpenClaw-specific Blacksmith Testbox helper scripts.
-
Agents/compaction: preserve scoped background exec/process session references across embedded compaction and after-turn runtime contexts without exposing sessions from unrelated scopes. Fixes #79284. (#79307) Thanks @TurboTheTurtle.
-
Agents/process: tell agents to inspect background sessions with
process logbefore sending interactive input and to usewaitingForInput/stdinWritablehints fromlog/poll. -
CLI/onboarding: improve setup, onboarding, configure, and channel command wayfinding so terminal flows explain the next useful command instead of relying on terse setup labels.
-
Agents/Codex: remove the configurable Codex dynamic-tools profile so Codex app-server always owns workspace, edit, patch, exec, process, and plan tools while OpenClaw integration tools remain available.
-
macOS app: update the Peekaboo bridge dependency to Peekaboo 3.0.0.
-
Dependencies: refresh workspace pins and move the WhatsApp plugin from
@whiskeysockets/baileystobaileyswhile keeping the7.0.0-rc10runtime. -
Plugin SDK: add bundled-plugin session actions,
sendSessionAttachment, and Cron-backedscheduleSessionTurn/tag cleanup under the grouped session namespace. Replaces #75578/#75581/#75588 and part of #73384/#74483. Thanks @100yenadmin. -
Plugin SDK/media-understanding: add
extractStructuredWithModel(...)plus the optional provider-sideextractStructured(...)seam so trusted plugins can run bounded image-first structured extraction with optional supplemental text context through provider-owned runtimes such as Codex.
Fixes
- Bonjour/Gateway: treat active ciao probing and fresh name-conflict renames as in-progress so the mDNS watchdog waits for probe settlement before retrying, preventing rapid re-advertise loops on Windows, WSL, and other multicast-hostile hosts. (#74778) Refs #74242. Thanks @fuller-stack-dev.
- Providers/MiniMax: send a minimal Anthropic-compatible user fallback when message conversion filters a turn to an empty payload, so MiniMax M2.7 no longer returns
chat content is emptyafter tool-heavy sessions. Fixes #74589. Thanks @neeravmakwana and @DerekEXS. - Cron: keep long manual cron runs active in the task registry until completion, preventing transient
lostmarkers before durable recovery reconciles. Fixes #78233. (#78243) Thanks @Feelw00. - Doctor/GitHub CLI: surface a
GH_CONFIG_DIRhint when the GitHub skill is usable butghauth lives under a different operator HOME than the agent process, without warning for disabled or filtered skills. Fixes #78063. (#78095) Thanks @tmimmanuel. - Gateway: dedupe concurrent
send,poll, andmessage.actionrequests while delivery is still in flight, preventing duplicate outbound work for the same idempotency key. (#68341) Thanks @thesomewhatyou. - Cron: keep main-session
systemEventheartbeat wakes on their bound session route for both direct and queued wake paths by dropping inherited explicit heartbeat destinations when forcingtarget: "last". Fixes #73900. Thanks @richardmqq. - Telegram: honor forced document delivery for video media so
--force-documentsends MP4s as documents instead of typed videos. Fixes #80389. (#80405) Thanks @jbetala7. - Gateway: clear speculative node wake state when APNs registration is missing, preventing unregistered or mistyped node IDs from retaining wake throttle entries. Fixes #68847. (#68848) Thanks @Feelw00.
- Auto-reply: keep late follow-up queue drain finalizers from deleting a replacement queue registered after
/stop, preventing immediate follow-up messages from being orphaned. Fixes #68838. (#68839) Thanks @Feelw00. - Feishu: make manual App ID/App Secret setup the default channel-binding path while keeping QR scan-to-create as an optional best-effort flow, and document the manual fallback for domestic Feishu mobile clients that do not react to the QR code. Fixes #80591. Thanks @wei-wei-zhao.
- Memory: cap dreaming promotion writes to
MEMORY.mdby compacting oldest auto-promoted sections while preserving user-authored notes, keeping active memory below the bootstrap budget. Fixes #73691. (#74088) Thanks @YB0y. - Telegram: show resolved thinking defaults in native
/statusand/thinkmenus while preserving explicit session overrides. (#80341) Thanks @VACInc. - Channels: cache selected channel registry lookups against the active fallback snapshot so pinned-empty registries refresh native command and alias routing after active registry swaps. (#80333) Thanks @samzong.
- Codex app-server: reuse native Codex CLI OAuth for isolated app-server harness login, refresh, and app inventory cache keys so ChatGPT-authenticated Codex runs no longer fall back to unauthenticated OpenAI API calls. (#79877) Thanks @jeffjhunter.
- Gateway: scope
sessions.resolvesessionId and label store loads to the requested agent so large unrelated agent stores are not parsed for scoped lookups. Fixes #51264. (#79474) Thanks @samzong. - Gateway: share serialized streaming event envelopes across eligible WebSocket and node subscribers while preserving per-client sequence numbers. (#80299) Thanks @samzong.
- Gateway: consolidate duplicate
openclaw doctorservice config panels while preserving the declined-repair--forcehint. Fixes #80287. (#78688) Thanks @YB0y. - Browser: report Chrome MCP existing-session page readiness in browser status without letting status probes exceed the client timeout. Fixes #80268. (#80280) Thanks @ai-hpc.
- WhatsApp: route opening-phase Baileys 428 connectionClosed through the WhatsApp reconnect policy and keep post-open 428 closes retryable, so transient setup socket closes retry with WhatsApp diagnostics instead of escaping as a bare
channel exitederror. Fixes #75736; mitigates #77443. Thanks @dataCenter430. - Agents: disable Pi's default filesystem resource discovery for embedded runs while keeping OpenClaw inline extension factories active, avoiding Windows event-loop stalls during first WhatsApp-triggered agent startup. Fixes #77443. Thanks @dataCenter430.
- Providers/self-hosted: read model-scoped llama.cpp runtime context from
/props.default_generation_settings.n_ctxwhile keeping top-leveln_ctxas a fallback, so session budgeting reflects the loaded context window. Fixes #73664. (#74057) Thanks @brokemac79. - Memory: reject symlinked directory components in configured extra memory paths before reading Markdown files. (#80331) Thanks @samzong.
- Sessions/transcripts: replace whole-file
readFilescans with shared streaming helpers (streamSessionTranscriptLinesandstreamSessionTranscriptLinesReverse) for idempotency lookup, latest/tail assistant text reads, delivery-mirror dedupe, and compaction fork loading, so long-running sessions no longer materialize the full transcript in memory. Forward scans usereadlineover a boundedcreateReadStream; reverse scans read bounded chunks from the file end and decode complete JSONL lines newest-first without a fixed tail cap. Synthetic 200 MiB transcript: peak RSS delta drops from +252 MiB to +27 MiB while preserving malformed-line tolerance and idempotency-key return semantics. Fixes #54296. Thanks @jack-stormentswe. - WhatsApp: apply hot-reloaded
dmPolicyandallowFromsettings to the active Web listener before processing new inbound DMs. Fixes #80538. Thanks @Ampaskopi129. - Plugins: let
openclaw doctor --fixrepair managed plugin installs whose package entrypoints fail package-directory boundary validation after local state moves. Fixes #80592. Thanks @wei-wei-zhao. - Voice-call: resume voice-originated exec approval follow-ups as internal non-delivery turns instead of rejecting them as
unknown channel: voice. Fixes #80540. Thanks @patrickmch. - Control UI: preserve the composer draft when Stop is tapped during an active chat run, preventing accidental prompt loss on mobile. Fixes #80586. Thanks @KCALLC.
- Infra/retry: keep jittered retry delays at or above server-supplied Retry-After lower bounds when the hint can be honored. Fixes #68541. (#68543) Thanks @Feelw00.
- Docs: clarify that
/model provider/modelis an exact session route, while duplicate bare model ids only use configured fallback order on non-session override paths. Refs #80562. Thanks @gaodaabao. - Redact persisted secret-shaped payloads [AI]. (#79006) Thanks @pgondhi987.
- Agents: label
.openclaw/sandboxesexec workdirs as sandbox runs in compact tool summaries instead of showing the full path. - OpenAI Codex: surface browser OAuth and device-code login failures instead of treating failed logins as empty successful auth results. Refs #80363.
- CLI agents: carry runtime-only current-turn sender/reply context into CLI model prompts while keeping prompt-build hook input and transcript text clean.
- Control UI: keep workspace file presence checks from treating
fs-safestat helper failures as missing files, restoring Agents file status for existing Windows workspace files. Fixes #79953. Thanks @lovelefeng-glitch. - Microsoft Foundry: report an explicit error when the Azure subscription prompt returns an id that is not present in the enabled subscription list, instead of continuing from an unsafe subscription assertion. (#62742) Thanks @oliviareid-svg.
- fix(matrix): gate name-based allowlist resolution [AI]. (#79007) Thanks @pgondhi987.
- Slack: include the bot's own root/parent message in new thread sessions so in-thread replies reach the agent with the parent text the user is responding to, instead of only
reply_to_idmetadata. Fixes #79338. Thanks @sxxtony. - Docker: keep image builds on the source pnpm workspace policy so pnpm 11 can prune production dependencies without a Docker-only workspace rewrite.
- Agents/compaction: restore info-level gateway logs for embedded compaction start, completion, and incomplete outcomes. (#71961) Thanks @rubencu.
- Telegram: build reply-aware inbound turns through the shared channel context path so agents see the current reply target inline with the current message.
- Telegram: recover legacy message cache files that mixed JSON-array and line-delimited entries so restarted gateways preserve reply-window context. (#80567)
- Telegram: update the reply-context cache when messages are edited, so streamed bot replies appear in later agent context with their final text instead of the first draft.
- Skills/Windows: normalize compacted skill prompt locations to forward slashes after home-prefix compaction so Windows skill paths remain readable by model file tools. (#52200) Thanks @chienchandler.
- Control UI/Windows: update
@openclaw/fs-safeso agent workspace file presence checks fall back correctly on Windows, preventing existing AGENTS.md, SOUL.md, TOOLS.md, IDENTITY.md, USER.md, HEARTBEAT.md, and MEMORY.md files from showing as missing. Fixes #79953. Thanks @lovelefeng-glitch. - Memory: skip managed dreaming cron reconciliation warnings for ordinary cron and heartbeat hook contexts that cannot manage Gateway cron. (#77027) Thanks @rubencu.
- Cron: treat Codex app-server turn acceptance, CLI process spawn, and tool starts as execution milestones, preventing isolated runs from tripping the early startup watchdog after work has begun.
- Codex app-server: treat current-turn
<turn_aborted>raw markers as terminal so interrupted native-tool turns release Discord agent sessions instead of waiting for the outer timeout. - Yuanbao: bump
openclaw-plugin-yuanbaoto 2.13.1 to supportsourceReplyDeliveryMode: "automatic"for group chat. (#79814) Thanks @loongfay. - Memory: keep
memory_searchresultcorpuslabels aligned with the hit source, so session transcript hits surface assessionsand memory-file hits staymemory. Fixes #72885. (#71898, #72886) Thanks @rubencu. - Codex app-server: default native plugin app tool approvals to automatic so non-destructive read tools run when destructive actions are disabled.
- Google/Gemini: normalize retired nested Gemini 3 Pro Preview ids while converting manifest catalog rows into emitted provider config, so
google/gemini-3.1-pro-previewis used for testing instead ofgoogle/gemini-3-pro-preview. - Google/Gemini: normalize retired nested Gemini 3 Pro Preview ids in configured proxy/provider-auth model catalogs, so regenerated config keeps testing
google/gemini-3.1-pro-previewinstead ofgoogle/gemini-3-pro-preview. - Google/Gemini: normalize retired nested Gemini 3 Pro Preview ids while onboarding provider catalog presets, so setup-emitted proxy configs test
google/gemini-3.1-pro-previewinstead ofgoogle/gemini-3-pro-preview. - Google/Gemini: normalize retired Gemini 3 Pro Preview ids in provider catalog rows during generic config writes, so unrelated config changes keep testing
google/gemini-3.1-pro-preview. - Models: keep configured fallback chains ahead of configured primary models for override selections with duplicate model ids, preventing fallback jumps to the wrong provider. Fixes #80562.
- Native apps: advertise the Gateway protocol compatibility range so chat and node sessions can connect to v3 gateways after additive v4 client updates.
- Gateway/agents: keep stale
sessions_sendACP manager andweb_fetchruntime chunks importable after package updates, preventing live gateways from breaking before restart. Fixes #78804. Thanks @Gomesy72. - Gateway/install: preserve service environment value-source metadata in
openclaw gateway install, so systemd reinstall paths keep env-file-backed secrets out of inline unit metadata. Refs #77406, #77427. Thanks @stainlu and @brokemac79. - Auto-reply/reset: include inbound sender context in bare
/newand/resetmodel prompts while keeping startup instructions out of transcript prompts, so agents see sender identity on the first reset turn. Fixes #77360. Thanks @srb11e. - Gateway: avoid synchronous restart-sentinel state probes during post-attach startup, preventing slow Windows or redirected state directories from blocking channel turns. Fixes #79264. Thanks @liyi58.
- Agents/auth: update successful model auth profile status with one locked store write, reducing post-model reply latency from duplicate
auth-profiles.jsonsaves. Thanks @mcaxtr. - Agents/image: honor explicit
imagetool model overrides even whenagents.defaults.imageModelis unset, restoring one-off vision calls for configured multimodal providers. Fixes #79341. Thanks @haumanto. - Doctor/update: leave live systemd gateway units unchanged during noninteractive update-mode service repair, so update-time doctor does not silently overwrite operator-owned unit directives. Refs #80462.
- Update: accept optional leading
vprefixes when verifying exact npm package install targets, soopenclaw update --tag v2026...does not roll back after installing the matching bare package version. Refs #74069; #80480. Thanks @Kaspre. - Doctor: treat missing plugin ids in
plugins.denyas stale config warnings instead of fatal validation errors, and remove them during stale plugin cleanup so update repair does not restore last-known-good config for deny-only stale plugin refs. Refs #77802. Thanks @Kaspre. - Codex app-server: preserve prompt-local current-turn context through context-engine prompt projection, so replied-to Telegram messages stay visible to the Codex model input.
- Telegram: pass agent-scoped media roots through gateway message actions so workspace-local media from the active agent is not rejected as cross-agent access. Thanks @frankekn.
- CLI/gateway: keep
gateway status --deepplugin-aware so configured plugin manifest warnings, including missing channel config metadata, stay visible during install and update smoke checks. - Doctor/status: clarify gateway token source conflict warnings and suppress them inside the managed Gateway service credential context.
- Feishu: accept Schema 2 card callbacks whose operator identity is nested under
operator.user_id, so card buttons dispatch instead of being dropped as malformed. Fixes #71670. (#71787) Thanks @rubencu. - Feishu: fall back to a top-level group send when normal group quoted replies target a withdrawn or missing message, preventing replies from disappearing silently while preserving native topic safety. Fixes #79349. Thanks @arlen8411.
- Doctor: stop flagging the live compatibility agent directory as orphaned when the configured default agent is not
main. Fixes #74313. (#74438) Thanks @carlos4s. - Auth/Claude CLI: persist fresher managed external CLI OAuth credentials back to
auth-profiles.json, preventing staleanthropic:claude-cliprofiles from repeatedly bootstrapping and flooding debug logs. Fixes #80129. Thanks @Caulderein. - Context: render
/context maponly from actual run context and persist Codex app-server run reports without counting deferred tool-search schemas as prompt-loaded tool schemas. - Codex app-server: report Codex-native tool execution to diagnostics so long-running native
bash, web, file, and MCP tools no longer look like stale embedded runs to the watchdog. (#80217) - Codex app-server: refresh Codex account rate limits after subscription usage-limit failures so Discord and other channel replies can show the next reset time instead of saying Codex returned none. Thanks @pashpashpash.
- Agents/auth: let Codex-backed OpenAI agent turns use
auth.order.openaientries for Codex-compatible OAuth and API-key profiles while keeping existingopenai-codexprofile ordering valid. - Codex app-server: emit async
after_tool_callobservations for native tool completions not covered by the native hook relay so observability plugins can record Codex-native tools. (#80372) Thanks @VACInc. - Tasks: route group and channel task completions through the requester session so the parent agent can send the visible summary instead of stopping at a generic task-status line. Fixes #77251. (#77365) Thanks @funmerlin.
- Telegram: preserve blank lines between manually indented bullet blocks and following numbered sections in rendered replies. Fixes #76998. Thanks @evgyur.
- Agents/sandbox: allow read-only sandbox sessions to read the
/agentworkspace mount while keeping write/edit/apply_patch workspace-only guarded, restoringread /agent/...forworkspaceAccess: "ro". Fixes #39497. Thanks @stainlu and @teosborne. - Slack: pass configured agent identity through draft preview sends so partial streaming replies keep custom username/avatar on the initial Slack message. Fixes #38235. (#38237) Thanks @lacymorrow.
- Slack: support
allowBots: "mentions"for bot-authored messages that mention the receiving bot, matching the documented Discord-style mode without accepting every bot message. Fixes #43587. (#43588) Thanks @raw34. - Slack: refresh private file URLs with
files.infowhen inbound DM file events omit or stale attachment URLs, preventing file attachments from being dropped before media hydration. Fixes #50129. (#50200) Thanks @smartchainark. - Slack: add scoped message-tool formatting hints so agents use Markdown for plain sends and direct mrkdwn for Block Kit fields. Fixes #34609. (#50979) Thanks @carrotRakko.
- Slack: describe
download-filefile ids separately from message timestamps and return a targeted recovery error when agents passmessageIdinstead offileId. (#74155) Thanks @jarvis-ai-gregmoser. - Slack: retain processed room messages for
requireMention=falsechannels so always-on Slack rooms keep recent conversation context between turns. (#38658) Thanks @syedamaann. - Slack: compile interactive reply directives for direct outbound sends without bypassing the
interactiveRepliescapability gate, preserving Block Kit for Slack CLI and cron deliveries. (#78220) Thanks @kazamak. - Slack: keep DM last-route updates scoped to the active non-main DM session, including threaded DM turns, so isolated Slack DM sessions do not overwrite the shared main route. (#73085) Thanks @clawSean.
- Slack/ACP: route Slack channel and DM messages through configured ACP bindings when no runtime binding exists, keeping bound thread replies pinned to the persistent ACP session and dropping unavailable configured targets instead of falling back to
main. (#73101) Thanks @Raasl. - Slack: mark unresolved thread replies as ambiguous and skip them instead of treating them as root channel messages, keeping thread continuation on the SDK-backed participation store. (#75630) Thanks @soichiyo.
- Slack: let same-channel message tool sends opt out of inherited thread context with
topLevel: trueorthreadId: null, allowing agents to post a new parent-channel message from inside a Slack thread. Fixes #79807. Thanks @vexclawx31. - Slack: prefer full rich-text block content over truncated socket-mode message previews so long inbound Slack messages reach agents intact. Fixes #79027. Thanks @BobAccentWebDev.
- Slack: include structured Slack API error details in setup, probe, streaming, and reply logs while preserving token redaction. (#53966) Thanks @deucemask.
- Gateway/agents: keep structured reasons when active-run queueing fails and deprecate the legacy boolean queue helper, so steering and subagent wake diagnostics distinguish completed, non-streaming, and compacting runs. Fixes #80156. Thanks @markus-lassfolk.
- System events: dedupe keyed events across the queue while preserving unkeyed, delivery-route, and trust-boundary event identity. (#73040) Thanks @statxc.
- Agents/UI: compact exec and tool progress rows by hiding redundant shell tool names, replacing known workspace paths with short context markers, and preserving Discord trace scrubbing for compact command lines.
- ACPX: run and await the embedded ACP backend startup probe by default so the gateway
readysignal no longer fires before the acpx runtime has either become usable or reported a probe failure; setOPENCLAW_ACPX_RUNTIME_STARTUP_PROBE=0to restore lazy startup. Fixes #79596. Thanks @bzelones. - Gateway/status: surface model-pricing bootstrap and refresh failures as degraded health/status warnings while keeping Gateway liveness healthy. Fixes #79599. Thanks @bzelones.
- OpenAI-compatible models: strip prior assistant reasoning fields from replayed Chat Completions history by default, preventing oMLX/vLLM Qwen follow-up turns from rejecting or stalling on stale
reasoningpayloads. Fixes #46637. Thanks @zipzagster and @lexhoefsloot. - CLI/onboarding: give non-Azure custom providers a safe generated context window and heal legacy 4k wizard entries without overwriting explicit valid small model limits, preventing first-turn compaction loops. Fixes #79428. (#79911) Thanks @Jefsky.
- OpenAI-compatible models: add
compat.strictMessageKeysto strip Chat Completions replay messages toroleandcontentfor strict providers that reject OpenAI-style tool and metadata keys. Fixes #50374. Thanks @choutos. - Bedrock Mantle: add
plugins.entries.amazon-bedrock-mantle.config.discovery.enabled=falseto suppress automatic Mantle discovery and IAM bearer-token generation while keeping the plugin enabled. Fixes #67288. Thanks @kanekoh. - Ollama: stop native
/api/chatrequests from copying catalogcontextWindowormaxTokensintooptions.num_ctxunlessparams.num_ctxis explicitly configured, avoiding pathological prompt-ingestion latency on local large-context models. Fixes #62267. Thanks @BenSHPD. - Ollama: keep the model idle watchdog enabled for
*:cloudmodels routed through a local Ollama host, so cloud-backed tool-loop stalls fail over visibly instead of inheriting local-model no-idle behavior. Fixes #79350. Thanks @geek111. - Voice/Ollama: honor routed voice agent
tools.allowfor classic embedded voice responses, including empty allowlists, so no-tool Ollama agents do not receive tool schemas. Fixes #79506. Thanks @donkeykong91. - Gateway: reread config from disk after the first in-process restart loop startup, preventing SIGUSR1 restarts from reusing a stale startup snapshot and dropping config written after boot. Fixes #79947. Thanks @TheLevti.
- Codex app-server: deliver native image-generation outputs from Codex
savedPathevents as reply media, so blank-text image generation turns still attach the generated file. Thanks @keshavbotagent. - Network/SSRF: keep pinned automatic DNS lookups on IPv4 when dual-stack hosts also publish AAAA records, and treat
EADDRNOTAVAILas a transient gateway network failure instead of a fatal crash. Fixes #80078. Thanks @takamasa-aiso. - Control UI: show compact one-line live/idle/terminal run status badges in the Sessions table and rename the active-minute filter to its updated-within meaning. Fixes #78307. Thanks @BunsDev.
- Control UI: scope chat session-list refreshes by agent and skip disk-only agent store discovery for configured-only lists, preventing post-first-message session switching stalls on large Windows stores. Fixes #79675. Thanks @lovelefeng-glitch, @BunsDev.
- Control UI: allow Appearance tweakcn theme imports through the served CSP so browser-local custom theme links no longer fail with a
connect-srcviolation. Fixes #78504. Thanks @BunsDev. - Control UI/config: remove plugin allowlist entries that the form auto-added when a plugin enable toggle is reverted before saving, so reverting the visible toggle clears dirty state without persisting unintended allowlist changes. (#78329) Thanks @samzong.
- Media/host-read: allow buffer-verified gzip, tar, and 7z archives in the shared host-local media validator alongside ZIP and document attachments.
- Plugins/doctor: invalidate persisted plugin registry snapshots when plugin diagnostics point at deleted source paths, so
openclaw doctorstops repeating stale warnings after a local extension is replaced by a managed npm plugin. Fixes #80087. (#80134) Thanks @hclsys. - Doctor/OpenAI Codex: preserve Codex auth intent when auto-repairing legacy
openai-codex/*model refs to canonicalopenai/*by adding provider/model-scoped Codex runtime policy, preventing repaired configs from falling through to direct OpenAI API-key auth. Fixes #78533 and #78570. Thanks @superck110 and @Azmodump. - CLI/agents: surface durable message delivery status from
sendDurableMessageBatchindeliverAgentCommandResultandopenclaw agent --json --deliver, preserving suppressed hook outcomes as terminal no-retry results while exposing partial and failed sends for automation. Supersedes #53961 and #57755. Thanks @Kaspre. - Agents: apply the LLM idle watchdog while provider stream setup is still pending, preventing silent pre-stream model hangs from waiting for the full agent timeout.
- Cron: let isolated self-cleanup runs inspect their own job run history while keeping other cron jobs and mutation actions blocked. Fixes #80019. Thanks @hclsys.
- Cron: report isolated agent-turn setup and pre-model stalls with phase-specific timeout errors instead of waiting for the full job budget when no model call starts. Fixes #74803. Thanks @jeffsteinbok-openclaw and @dgkim311.
- CLI/plugins: treat arbitrary unknown subcommands outside plugin CLI metadata as normal unknown commands instead of suggesting
plugins.allow, while preserving allowlist guidance for real plugin command roots. Fixes #80109. (#80123) Thanks @kagura-agent. - CLI/config: persist explicit
config setandconfig patchvalues that equal runtime defaults instead of reporting success while dropping them. Fixes #79856. (#80106) Thanks @abodanty and @hclsys. - OpenAI/realtime voice: accept Codex-compatible legacy audio and transcript event aliases so provider protocol drift does not drop assistant audio or captions.
- Discord/voice: keep default agent-proxy realtime sessions from auto-speaking filler before the forced OpenClaw consult answer, finish Discord playback on realtime response completion, and queue later exact-speech answers until playback idles to avoid mid-sentence replacement.
- Gateway: return deterministic
400 invalid_request_errorresponses for malformed encoded session-kill HTTP paths instead of letting route-shaped requests fall through to later Gateway handlers. (#72439) Thanks @rubencu. - Control UI: serve root PWA and favicon assets from
/__openclaw__/SPA routes so tab icons, install metadata, and the service worker do not 404 after internal navigation. Fixes #80072. Thanks @CodeNovice2017. - Exec/safe bins: compare trusted safe-bin dirs with path-specific case folding on case-insensitive filesystems so Windows and default macOS paths match without weakening case-sensitive mounts. (#42131) Thanks @hkochar.
- OpenAI/realtime voice: honor disabled input-audio interruption locally so server VAD speech-start events do not clear Discord playback after operators set
interruptResponseOnInputAudio: false. - Telegram: keep no-response DM turns quiet instead of rewriting them into visible silent-reply chatter. Fixes #78188. (#78228) Thanks @Beandon13.
- Telegram: handle managed select button callbacks before the raw callback fallback while preserving delimiter-containing option values such as
env|prod. (#79816) Thanks @moeedahmed. - OpenAI-compatible models: handle JSON chat-completion bodies returned to streaming requests, preserving reasoning fields and visible text instead of completing an empty agent turn. Fixes #77870.
- Discord/models: defer model picker component interactions before loading route, model, and preference data, preventing "This interaction failed" timeouts under gateway load. Fixes #77283. Thanks @colin-chang.
- xAI: expose
/think low|medium|highfor reasoning-capable Grok models and keepreasoning.efforton native Responses payloads while preserving off-only behavior for non-reasoning routes. Fixes #79210. Thanks @colinmcintosh. - CLI/media: let explicit image description model refs use bundled static provider catalogs and generic model-backed image hooks, so
openclaw infer image describe --model zai/glm-4.6vworks like direct model runs and Anthropic auth probes avoid stale Claude 3 Haiku catalog entries. - Models/Anthropic: add
anthropic/claude-haiku-4-5to Anthropic API-key agent allowlist defaults when an Anthropic default model is configured, so cron model overrides can select the current Haiku alias. Fixes #78000. - Agents/compaction: initialize built-in context engines before CLI transcript compaction resolves the default engine, preventing clean-process
legacyengine registration failures during CLI session persistence. Fixes #79446. Thanks @TurboTheTurtle. - Agents/Anthropic-compatible: strip replayed thinking blocks for custom Anthropic-compatible models that explicitly declare
supportsReasoningEffort: false, preventing Kimi-compatible providers from resending unsupportedthinkingcontent. Fixes #47452. - Kimi: keep Anthropic-compatible thinking streams valid by supplying required thinking budgets and enough output room for hidden reasoning plus final text. (#80481) Thanks @InTheCloudDan.
- Browser: wait longer for existing-session Chrome MCP status and non-deep doctor probes so slow first attaches do not falsely report offline while keeping raw CDP status probes short. (#77473) Thanks @rubencu.
- Gateway/logging: install console capture before foreground Gateway fast-path parsing and suppress known libsignal session dumps even in verbose mode, preventing raw terminal logs from printing WhatsApp session key material. (#76306) Thanks @rubencu.
- Exec approvals: keep
exec.approval.liston the lightweight policy-summary path so listing pending approvals no longer loads the rich tree-sitter command explainer. (#76943) Thanks @rubencu. - Agents: surface concise default-visible warnings when
exec/bashtool calls fail after the assistant claims success, while keeping raw stderr hidden unless verbose details are enabled. Fixes #60497. (#80003) Thanks @jbetala7. - Agents: stop blank model-emitted tool calls before dispatch while preserving id-based tool-name recovery, preventing Kimi/NVIDIA blank-name retry loops without creating a callable
_blanksentinel. Fixes #34129. (#56391) Thanks @smartchainark. - Agents/Telegram: deliver the canonical final assistant answer instead of replaying accumulated pre-tool text blocks, preventing duplicate Telegram replies and raw-looking tool-output fragments from leaking into chat delivery. Fixes #79621 and #79986. Thanks @nonzeroclaw and @dudaefj.
- Auto-reply/TUI: keep fallback timeout recovery deliverable after a primary model lifecycle error by emitting fallback progress and deferring terminal TUI errors until recovery has a chance to finish. Fixes #80000. (#80009) Thanks @TurboTheTurtle.
- Heartbeat: clear stale auto fallback model overrides when the configured default model changes, so heartbeat runs follow updated
agents.defaults.model.primarywithout requiring a manual reset. Fixes #74284. Thanks @brtkwr and @bitloi. - CLI/agent: let
openclaw agent --modeluse the backend/admin Gateway scope without cached device-token scopes silently downscoping the request. (#78837) Thanks @VACInc. - CLI/help: keep help and version invocations configless while improving shared port, channel, plugin, task, session, message, pairing, and auth recovery text.
- CLI/config: explain strict JSON parse failures with a valid example and the plain-string escape hatch.
- CLI/secrets: turn offline Gateway reload failures into actionable recovery text.
- CLI/channels: explain missing or ambiguous channel selections with next commands.
- CLI/channels: defer guided channel status collection until a channel is selected, keeping
openclaw channels addfirst screen quieter. - CLI/channels: exit guided channel setup cleanly on cancellation instead of printing the internal wizard error.
- Plugins/CLI: route disabled Matrix and LanceDB memory command roots to plugin-enable guidance instead of generic unknown-command errors.
- Browser/Docker: detect Playwright-managed Chromium from
PLAYWRIGHT_BROWSERS_PATHand the default Playwright cache on Linux, so Docker installs that persist/home/node/.cache/ms-playwrightno longer needbrowser.executablePath. - Ollama: keep DeepSeek V4 cloud models thinking-capable even when Ollama Cloud
/api/showomits thethinkingcapability, so/think highno longer rejectsollama/deepseek-v4-*:cloud. - ACPX/Claude ACP: keep foreground prompts waiting for their own result when autonomous task-notification results arrive during the same session, and retarget the patch for Claude Agent ACP
0.33.1. - WhatsApp: keep Baileys media uploads from passing non-Dispatcher agents to undici in
7.0.0-rc10, and patch the bundled Baileys declaration so the latest tsdown build stays warning-clean. - Build: keep tsdown
0.22.0warning-clean by externalizing known third-party declaration edges and replacing relative channel config module augmentations with explicit built-in channel fields. - ACP sessions: map canonical runtime options to backend-advertised ACP config keys like Claude's
effortwhile keeping persisted OpenClaw state canonical. (#79926) Thanks @InTheCloudDan. - Models/Discord: support
provider/*entries inagents.defaults.modelsso/model,/models, and model pickers can show dynamically discovered models for selected providers without exact model allowlists. Fixes #79485. Thanks @rendrag-git. - Gateway/watch: rebuild or restage missing bundled-plugin dist and runtime-postbuild outputs before launching the Gateway from a source checkout, preventing incomplete watch-mode runtime trees. (#70805) Thanks @rubencu.
- CLI/update: allow restart health probes from the previous gateway protocol during self-update, and make plugin dry-runs report exact npm target versions instead of
unknownwhile preserving unchanged status. - OpenAI/Codex: forward persisted
openai-codexOAuth profile metadata into Codex plugin harness attempts after canonicalopenai/*migration, so OAuth-only installs keep using native Codex auth instead of falling through to direct OpenAI API-key auth. Fixes #79978. - OpenAI/Codex: point gateway missing-key recovery and wizard docs at the canonical
openai/gpt-5.5plus Codex OAuth route, and fix trajectory export errors so they suggest the validopenclaw sessionscommand. - Google/Gemini: normalize retired
google/gemini-3-pro-previewprimary, fallback, and model-map refs during config load and unrelated config writes so saved config keeps targeting Gemini 3.1 Pro Preview. - Google/Gemini: normalize retired Gemini 3 Pro Preview ids inside emitted Google provider model config, so regenerated models.json rows test
google/gemini-3.1-pro-preview. - Google/Gemini: normalize retired Gemini 3 Pro Preview ids for explicit OpenAI-compatible Google and Gemini CLI provider configs, so emitted config targets
google/gemini-3.1-pro-preview. - Google/Gemini: normalize retired Gemini 3 Pro Preview ids preserved from existing merged models.json providers so config emission keeps targeting
google/gemini-3.1-pro-preview. - Google/Gemini: normalize retired Gemini 3 Pro Preview ids inside provider auth config patches so setup-emitted provider catalogs test
google/gemini-3.1-pro-preview. - GitHub Copilot: mint short-lived Copilot API tokens with the same
vscode-chatintegration identity used by runtime requests, and refresh legacy cached tokens missing that identity so image-capable Copilot models no longer inherit thecopilot-language-serverscope. Fixes #79946, #80074. Thanks @TurboTheTurtle. - Plugins/doctor: drop stale managed npm install records when
openclaw doctor --fixremoves npm packages that shadow bundled plugins, so the rebuilt registry no longer resurrects the removed package metadata. - Doctor: warn when a per-agent model config omits the
fallbackskey andagents.defaults.model.fallbacksis non-empty. Covers both string-form ("model": "...") and partial-object form ("model": { "primary": "..." }) — both silently clobber the defaults chain at runtime. Use"fallbacks": []to explicitly opt out of fallbacks, or add"fallbacks": [...]to inherit or override. Fixes #79369. Thanks @Kaspre. - Discord/voice: reuse or suppress late realtime consult tool calls without stealing newer speaker context or speaking forced fallback answers twice.
- Discord/voice: skip likely incomplete realtime forced-consult transcript fragments and non-actionable closings so stale partial speech does not queue delayed answers over the next turn.
- Discord/voice: keep realtime forced consults from clearing active exact-speech playback, so back-to-back voice answers queue instead of cutting each other off.
- Discord/voice: synthesize realtime playback timestamps from emitted Discord PCM so OpenAI realtime barge-in truncation no longer sees
audioEndMs=0and skips legitimate interruptions. - Plugin SDK: keep activated linked plugin runtime facades loadable when bundled plugin fallback is disabled. Thanks @shakkernerd.
- Feishu: auto-thread
message(action="send")replies inside the topic when the active session is group_topic or group_topic_sender, and propagatereplyInThreadthrough text, card, and media outbound adapters so topic-scoped sessions no longer post at the group root. Fixes #74903. (#77151) Thanks @ai-hpc. - WhatsApp: pass routing context into voice-note transcript echo preflight so echoed transcripts can deliver to the originating chat. Fixes #79778. (#79788) Thanks @hclsys.
- Cron/failover: classify structured OpenAI-compatible
server_errorpayloads asserver_error, expose that reason in cron state, and let one-shot cron retry policy honorretryOn: ["server_error"]without requiring raw5xxtext. (#45594) Thanks @clovericbot. - Slack: wake the resolved thread session after interactive reply button/select clicks and carry Slack delivery context through the queued interaction event, so clicks continue the visible conversation. Fixes #79676 and #61502. (#79836) Thanks @velvet-shark, @tianxiaochannel-oss88, and @Saicheg.
- WhatsApp/streaming: send only the new suffix when text-end block replies repeat prior preambles across tool-call cycles, preventing cumulative WhatsApp preamble messages. Fixes #78946. (#79120) Thanks @brokemac79 and @papawattu.
- Tests/security audit: sandbox
audit-exec-surface.test.tsunder a per-case OpenClaw home tempdir, redirectingOPENCLAW_HOME(which wins overHOME/USERPROFILEinresolveRawHomeDir) alongsideHOMEandUSERPROFILE, so itssaveExecApprovals(...)calls never touch the live~/.openclaw/exec-approvals.jsonon the host running the suite. Sibling exec-approvals tests already used the tempdir pattern; this file did not, so runningpnpm testagainst a contributor's local checkout was silently truncating their real approvals to{ "version": 1, "agents": {} }. (#79885) Thanks @omarshahine. - ACP/gateway: preserve
AcpRuntimeErrorcause chain (code/method/JSON-RPC detail) through the lifecycle boundary so gateway logs, telegram replies, and tool-result text show the actual upstream failure instead of opaqueInternal error/[object Object], with redaction applied before the chain reaches log or reply surfaces. - Channels/iMessage: wire
action: "reply"attachments throughimsg send-rich --filewhen the installed imsg build advertises that capability (probed once viaimsg send-rich --helpand cached on the private-API status). Reply now hydratesmedia/mediaUrl/fileUrl/mediaUrls[0]/filePath/path/base64buffer+filenamethrough the shared outbound resolver, stages buffers via the existingwithTempFilehelper, rejectshttp(s)://URL attachments with a targeted error pointing callers atsend's full attachment-resolver pipeline, and falls back to the explicitimsg#114 not landed yeterror on older imsg builds. Depends on the upstreamopenclaw/imsg#114capability landing in an installable release; until then the new path stays gated and users see the same explicit fallback#79822introduced. (#79864) Thanks @omarshahine. - Telegram: preserve the first-preview debounce while appending true partial-stream deltas, so edited draft previews no longer duplicate earlier text when providers emit incremental output. (#80045) Thanks @TurboTheTurtle.
- Agents/Anthropic: report 1M session context for Claude Opus/Sonnet 4 models even when local model config still advertises 200k, matching model discovery and preventing premature status/UI overflow. Fixes #66766.
- Models/OpenRouter: hide missing-auth direct provider rows in
/model statuswhen they are only duplicated by a nested OpenRouter model id such asopenrouter/google/..., while preserving explicitly configured direct providers. Fixes #62317. - Models: preserve an explicitly selected provider/model such as
opencode-go/deepseek-v4-prowhen another provider owns the same bare model alias. Fixes #79325. - Models/config: explain missing
models.providers.<provider>.models[]registration when a model exists only inagents.defaults.models, instead of returning a bare unknown-model error. Fixes #80089. - MCP/tools: prefix bundle MCP server/tool fragments that would start with digits, keeping generated tool names valid for Moonshot/Kimi and other strict providers. Fixes #79179.
- Models/OpenRouter: treat
403 API key budget limit exceededas billing so model fallback advances instead of retrying the exhausted primary. Fixes #60191. Thanks @omgitsgela. - Models/OpenRouter: repair stale session overrides that lost the outer
openrouter/provider wrapper, so sessions return to the configured OpenRouter model instead of failing as an unknown direct-provider model. Fixes #78161. Thanks @hjamal7-bit. - Google/Gemini: default API-key onboarding back to
google/gemini-3.1-pro-previewso fresh Gemini test configs exercise Gemini 3.1 Pro Preview. - Telegram: show full provider/model labels for nested OpenRouter model ids in the model picker, so
openrouter/openai/gpt-5.4-minino longer displays asopenai/gpt-5.4-mini. Fixes #67792. (#72752) Thanks @iot2edge. - Models/OpenRouter: preserve live
supported_parameterstool support metadata so non-tool Perplexity Sonar models no longer receive agent tool payloads and fall back unnecessarily. Fixes #64175. Thanks @Catfish-75. - Models/OpenRouter: add MoonshotAI Kimi K2.5 to the bundled OpenRouter catalog so onboarding/model pickers can offer it without waiting for live discovery. Fixes #14601.
- Models/OpenRouter: keep keyRef/tokenRef-backed auth profiles visible to read-only PI model discovery, so OpenRouter models stay available in model pickers without storing plaintext keys. Fixes #58106. Thanks @ThalynLabs.
- Models/list: include explicit configured provider rows and read-only auth-backed catalog rows in the default configured view without loading PI's full registry, keeping Control UI pickers aligned with usable model auth. Refs #79381. Thanks @ismael-81.
- Security/audit: honor
tools.byProvider["provider/model"].denywhen reporting small-model web/browser exposure, so per-model OpenRouter mitigations clear themodels.small_paramsexposure signal. Fixes #80118. - Models/Moonshot: accept direct
moonshotai/...andmoonshot-ai/...refs as aliases for canonicalmoonshot/..., so copied OpenRouter Kimi ids no longer fail as unknown direct models. Fixes #73876. (#74946) Thanks @jeffrey701. - Kimi Code: use Kimi's stable
kimi-for-codingAPI model id in bundled catalog, onboarding, and docs while normalizing legacykimi-codeandk2p5refs. Fixes #79965. - Telegram: render cached reply targets and nearby group chatter as one selected conversation context window, so stale replies no longer split JSON reply chains from local chat context.
- Volcengine/Kimi: strip provider-unsupported tool schema length and item constraint keywords for direct and coding-plan models so hosted Kimi runs do not reject message tools with
minLength. Fixes #38817. - DeepSeek: backfill V4
reasoning_contentreplay fields for unowned OpenAI-compatible proxy providers, preventing follow-up request failures outside the bundled DeepSeek and OpenRouter routes. Fixes #79608. - iMessage: emit a WARN log when an action is blocked because the imsg private API bridge is not attached, so operators see the silent-drop in
~/.openclaw/logs/openclaw.loginstead of having to read per-session trajectory JSONLtool.resultpayloads. Common after a gateway restart un-injects the dylib from Messages.app. (#80035) Thanks @omarshahine. - Codex: cross-fill missing
thread.idandthread.sessionIdbefore schema validation so live Codex app-server responses that omitsessionIdno longer failthread/startorthread/resume. Fixes #80124. (#80137) Thanks @kagura-agent. - Agents/Pi: wait for embedded abort cleanup to settle before releasing the session write lock, preventing follow-up turns from racing previous prompt teardown. (#80239) Thanks @samzong.
- WhatsApp: downgrade OpenClaw watchdog-triggered Web reconnects from runtime errors to recovery warnings and clear the recovered reconnect status after the next healthy connection. (#77026) Thanks @rubencu.
- ACPX/Windows: hide the MCP proxy target child process window on Windows so ACP-backed agents do not flash or fail because of terminal window handling. Fixes #60672. (#60678) Thanks @KChow-ctrl.