* refactor: remove stale file-backed shims * fix: harden sqlite state ci boundaries * refactor: store matrix idb snapshots in sqlite * fix: satisfy rebased CI guardrails * refactor: store current conversation bindings in sqlite table * refactor: store tui last sessions in sqlite table * refactor: reset sqlite schema history * refactor: drop unshipped sqlite table migration * refactor: remove plugin index file rollback * refactor: drop unshipped sqlite sidecar migrations * refactor: remove runtime commitments kv migration * refactor: preserve kysely sync result types * refactor: drop unshipped sqlite schema migration table * test: keep session usage coverage sqlite-backed * refactor: keep sqlite migration doctor-only * refactor: isolate device legacy imports * refactor: isolate push voicewake legacy imports * refactor: isolate remaining runtime legacy imports * refactor: tighten sqlite migration guardrails * test: cover sqlite persisted enum parsing * refactor: isolate legacy update and tui imports * refactor: tighten sqlite state ownership * refactor: move legacy imports behind doctor * refactor: remove legacy session row lookup * refactor: canonicalize memory transcript locators * refactor: drop transcript path scope fallbacks * refactor: drop runtime legacy session delivery pruning * refactor: store tts prefs only in sqlite * refactor: remove cron store path runtime * refactor: use cron sqlite store keys * refactor: rename telegram message cache scope * refactor: read memory dreaming status from sqlite * refactor: rename cron status store key * refactor: stop remembering transcript file paths * test: use sqlite locators in agent fixtures * refactor: remove file-shaped commitments and cron store surfaces * refactor: keep compaction transcript handles out of session rows * refactor: derive transcript handles from session identity * refactor: derive runtime transcript handles * refactor: remove gateway session locator reads * refactor: remove transcript locator from session rows * refactor: store raw stream diagnostics in sqlite * refactor: remove file-shaped transcript rotation * refactor: hide legacy trajectory paths from runtime * refactor: remove runtime transcript file bridges * refactor: repair database-first rebase fallout * refactor: align tests with database-first state * refactor: remove transcript file handoffs * refactor: sync post-compaction memory by transcript scope * refactor: run codex app-server sessions by id * refactor: bind codex runtime state by session id * refactor: pass memory transcripts by sqlite scope * refactor: remove transcript locator cleanup leftovers * test: remove stale transcript file fixtures * refactor: remove transcript locator test helper * test: make cron sqlite keys explicit * test: remove cron runtime store paths * test: remove stale session file fixtures * test: use sqlite cron keys in diagnostics * refactor: remove runtime delivery queue backfill * test: drop fake export session file mocks * refactor: rename acp session read failure flag * refactor: rename acp row session key * refactor: remove session store test seams * refactor: move legacy session parser tests to doctor * refactor: reindex managed memory in place * refactor: drop stale session store wording * refactor: rename session row helpers * refactor: rename sqlite session entry modules * refactor: remove transcript locator leftovers * refactor: trim file-era audit wording * refactor: clean managed media through sqlite * fix: prefer explicit agent for exports * fix: use prepared agent for session resets * fix: canonicalize legacy codex binding import * test: rename state cleanup helper * docs: align backup docs with sqlite state * refactor: drop legacy Pi usage auth fallback * refactor: move legacy auth profile imports to doctor * refactor: keep Pi model discovery auth in memory * refactor: remove MSTeams legacy learning key fallback * refactor: store model catalog config in sqlite * refactor: use sqlite model catalog at runtime * refactor: remove model json compatibility aliases * refactor: store auth profiles in sqlite * refactor: seed copied auth profiles in sqlite * refactor: make auth profile runtime sqlite-addressed * refactor: migrate hermes secrets into sqlite auth store * refactor: move plugin install config migration to doctor * refactor: rename plugin index audit checks * test: drop auth file assumptions * test: remove legacy transcript file assertions * refactor: drop legacy cli session aliases * refactor: store skill uploads in sqlite * refactor: keep subagent attachments in sqlite vfs * refactor: drop subagent attachment cleanup state * refactor: move legacy session aliases to doctor * refactor: require node 24 for sqlite state runtime * refactor: move provider caches into sqlite state * fix: harden virtual agent filesystem * refactor: enforce database-first runtime state * refactor: rename compaction transcript rotation setting * test: clean sqlite refactor test types * refactor: consolidate sqlite runtime state * refactor: model session conversations in sqlite * refactor: stop deriving cron delivery from session keys * refactor: stop classifying sessions from key shape * refactor: hydrate announce targets from typed delivery * refactor: route heartbeat delivery from typed sqlite context * refactor: tighten typed sqlite session routing * refactor: remove session origin routing shadow * refactor: drop session origin shadow fixtures * perf: query sqlite vfs paths by prefix * refactor: use typed conversation metadata for sessions * refactor: prefer typed session routing metadata * refactor: require typed session routing metadata * refactor: resolve group tool policy from typed sessions * refactor: delete dead session thread info bridge * Show Codex subscription reset times in channel errors (#80456) * feat(plugin-sdk): consolidate session workflow APIs * fix(agents): allow read-only agent mount reads * [codex] refresh plugin regression fixtures * fix(agents): restore compaction gateway logs * test: tighten gateway startup assertions * Redact persisted secret-shaped payloads [AI] (#79006) * test: tighten device pair notify assertions * test: tighten hermes secret assertions * test: assert matrix client error shapes * test: assert config compat warnings * fix(heartbeat): remap cron-run exec events to session keys (#80214) * fix(codex): route btw through native side threads * fix(auth): accept friendly OpenAI order for Codex profiles * fix(codex): rotate auth profiles inside harness * fix: keep browser status page probe within timeout * test: assert agents add outputs * test: pin cron read status * fix(agents): avoid Pi resource discovery stalls Co-authored-by: dataCenter430 <titan032000@gmail.com> * fix: retire timed-out codex app-server clients * test: tighten qa lab runtime assertions * test: check security fix outputs * test: verify extension runtime messages * feat(wake): expose typed sessionKey on wake protocol + system event CLI * fix(gateway): await session_end during shutdown drain and track channel + compaction lifecycle paths (#57790) * test: guard talk consult call helper * fix(codex): scale context engine projection (#80761) * fix(codex): scale context engine projection * fix: document Codex context projection scaling * fix: document Codex context projection scaling * fix: document Codex context projection scaling * fix: document Codex context projection scaling * chore: align Codex projection changelog * chore: realign Codex projection changelog * fix: isolate Codex projection patch --------- Co-authored-by: Eva (agent) <eva+agent-78055@100yen.org> Co-authored-by: Josh Lehman <josh@martian.engineering> * refactor: move agent runtime state toward piless * refactor: remove cron session reaper * refactor: move session management to sqlite * refactor: finish database-first state migration * chore: refresh generated sqlite db types * refactor: remove stale file-backed shims * test: harden kysely type coverage # Conflicts: # .agents/skills/kysely-database-access/SKILL.md # src/infra/kysely-sync.types.test.ts # src/proxy-capture/store.sqlite.test.ts # src/state/openclaw-agent-db.test.ts # src/state/openclaw-state-db.test.ts * refactor: remove cron store path runtime * refactor: keep compaction transcript handles out of session rows * refactor: derive embedded transcripts from sqlite identity * refactor: remove embedded transcript locator handoff * refactor: remove runtime transcript file bridges * refactor: remove transcript file handoffs * refactor: remove MSTeams legacy learning key fallback * refactor: store model catalog config in sqlite * refactor: use sqlite model catalog at runtime # Conflicts: # docs/cli/secrets.md # docs/gateway/authentication.md # docs/gateway/secrets.md * fix: keep oauth sibling sync sqlite-local # Conflicts: # src/commands/onboard-auth.test.ts * refactor: remove task session store maintenance # Conflicts: # src/commands/tasks.ts * refactor: keep diagnostics in state sqlite * refactor: enforce database-first runtime state * refactor: consolidate sqlite runtime state * Show Codex subscription reset times in channel errors (#80456) * fix(codex): refresh subscription limit resets * fix(codex): format reset times for channels * Update CHANGELOG with latest changes and fixes Updated CHANGELOG with recent fixes and improvements. * fix(codex): keep command load failures on codex surface * fix(codex): format account rate limits as rows * fix(codex): summarize account limits as usage status * fix(codex): simplify account limit status * test: tighten subagent announce queue assertion * test: tighten session delete lifecycle assertions * test: tighten cron ops assertions * fix: track cron execution milestones * test: tighten hermes secret assertions * test: assert matrix sync store payloads * test: assert config compat warnings * fix(codex): align btw side thread semantics * fix(codex): honor codex fallback blocking * fix(agents): avoid Pi resource discovery stalls * test: tighten codex event assertions * test: tighten cron assertions * Fix Codex app-server OAuth harness auth * refactor: move agent runtime state toward piless * refactor: move device and push state to sqlite * refactor: move runtime json state imports to doctor * refactor: finish database-first state migration * chore: refresh generated sqlite db types * refactor: clarify cron sqlite store keys * refactor: remove stale file-backed shims * refactor: bind codex runtime state by session id * test: expect sqlite trajectory branch export * refactor: rename session row helpers * fix: keep legacy device identity import in doctor * refactor: enforce database-first runtime state * refactor: consolidate sqlite runtime state * build: align pi contract wrappers * chore: repair database-first rebase * refactor: remove session file test contracts * test: update gateway session expectations * refactor: stop routing from session compatibility shadows * refactor: stop persisting session route shadows * refactor: use typed delivery context in clients * refactor: stop echoing session route shadows * refactor: repair embedded runner rebase imports # Conflicts: # src/agents/pi-embedded-runner/run/attempt.tool-call-argument-repair.ts * refactor: align pi contract imports * refactor: satisfy kysely sync helper guard * refactor: remove file transcript bridge remnants * refactor: remove session locator compatibility * refactor: remove session file test contracts * refactor: keep rebase database-first clean * refactor: remove session file assumptions from e2e * docs: clarify database-first goal state * test: remove legacy store markers from sqlite runtime tests * refactor: remove legacy store assumptions from runtime seams * refactor: align sqlite runtime helper seams * test: update memory recall sqlite audit mock * refactor: align database-first runtime type seams * test: clarify doctor cron legacy store names * fix: preserve sqlite session route projections * test: fix copilot token cache test syntax * docs: update database-first proof status * test: align database-first test fixtures * docs: update database-first proof status * refactor: clean extension database-first drift * test: align agent session route proof * test: clarify doctor legacy path fixtures * chore: clean database-first changed checks * chore: repair database-first rebase markers * build: allow baileys git subdependency * chore: repair exp-vfs rebase drift * chore: finish exp-vfs rebase cleanup * chore: satisfy rebase lint drift * chore: fix qqbot rebase type seam * chore: fix rebase drift leftovers * fix: keep auth profile oauth secrets out of sqlite * fix: repair rebase drift tests * test: stabilize pairing request ordering * test: use source manifests in plugin contract checks * fix: restore gateway session metadata after rebase * fix: repair database-first rebase drift * fix: clean up database-first rebase fallout * test: stabilize line quick reply receipt time * fix: repair extension rebase drift * test: keep transcript redaction tests sqlite-backed * fix: carry injected transcript redaction through sqlite * chore: clean database branch rebase residue * fix: repair database branch CI drift * fix: repair database branch CI guard drift * fix: stabilize oauth tls preflight test * test: align database branch fast guards * test: repair build artifact boundary guards * chore: clean changelog rebase markers --------- Co-authored-by: pashpashpash <nik@vault77.ai> Co-authored-by: Eva <eva@100yen.org> Co-authored-by: stainlu <stainlu@newtype-ai.org> Co-authored-by: Jason Zhou <jason.zhou.design@gmail.com> Co-authored-by: Ruben Cuevas <hi@rubencu.com> Co-authored-by: Pavan Kumar Gondhi <pavangondhi@gmail.com> Co-authored-by: Shakker <shakkerdroid@gmail.com> Co-authored-by: Kaspre <36520309+Kaspre@users.noreply.github.com> Co-authored-by: dataCenter430 <titan032000@gmail.com> Co-authored-by: Kaspre <kaspre@gmail.com> Co-authored-by: pandadev66 <nova.full.stack@outlook.com> Co-authored-by: Eva <admin@100yen.org> Co-authored-by: Eva (agent) <eva+agent-78055@100yen.org> Co-authored-by: Josh Lehman <josh@martian.engineering> Co-authored-by: jeffjhunter <support@aipersonamethod.com>
15 KiB
summary, read_when, title
| summary | read_when | title | ||
|---|---|---|---|---|
| Exec tool usage, stdin modes, and TTY support |
|
Exec tool |
Run shell commands in the workspace. exec is a mutating shell surface: commands can create, edit, or delete files wherever the selected host or sandbox filesystem permits. Disabling OpenClaw filesystem tools such as write, edit, or apply_patch does not make exec read-only.
Supports foreground + background execution via process. If process is disallowed, exec runs synchronously and ignores yieldMs/background.
Background sessions are scoped per agent; process only sees sessions from the same agent.
Parameters
Shell command to run. Working directory for the command. Key/value environment overrides merged on top of the inherited environment. Auto-background the command after this delay (ms). Background the command immediately instead of waiting for `yieldMs`. Override the configured exec timeout for this call. Set `timeout: 0` only when the command should run without the exec process timeout. Run in a pseudo-terminal when available. Use for TTY-only CLIs, coding agents, and terminal UIs. Where to execute. `auto` resolves to `sandbox` when a sandbox runtime is active and `gateway` otherwise. Ignored for normal tool calls. `gateway` / `node` security is controlled by `tools.exec.security` and `~/.openclaw/exec-approvals.json`; elevated mode can force `security=full` only when the operator explicitly grants elevated access. Approval prompt behavior for `gateway` / `node` execution. Node id/name when `host=node`. Request elevated mode — escape the sandbox onto the configured host path. `security=full` is forced only when elevated resolves to `full`.Notes:
hostdefaults toauto: sandbox when sandbox runtime is active for the session, otherwise gateway.hostonly acceptsauto,sandbox,gateway, ornode. It is not a hostname selector; hostname-like values are rejected before the command runs.autois the default routing strategy, not a wildcard. Per-callhost=nodeis allowed fromauto; per-callhost=gatewayis only allowed when no sandbox runtime is active.- With no extra config,
host=autostill "just works": no sandbox means it resolves togateway; a live sandbox means it stays in the sandbox. elevatedescapes the sandbox onto the configured host path:gatewayby default, ornodewhentools.exec.host=node(or the session default ishost=node). It is only available when elevated access is enabled for the current session/provider.gateway/nodeapprovals are controlled by host-local SQLite approvals state.noderequires a paired node (companion app or headless node host).- If multiple nodes are available, set
exec.nodeortools.exec.nodeto select one. exec host=nodeis the only shell-execution path for nodes; the legacynodes.runwrapper has been removed.timeoutapplies to foreground, background,yieldMs, gateway, sandbox, and nodesystem.runexecution. If omitted, OpenClaw usestools.exec.timeoutSec; explicittimeout: 0disables the exec process timeout for that call.- On non-Windows hosts, exec uses
SHELLwhen set; ifSHELLisfish, it prefersbash(orsh) fromPATHto avoid fish-incompatible scripts, then falls back toSHELLif neither exists. - On Windows hosts, exec prefers PowerShell 7 (
pwsh) discovery (Program Files, ProgramW6432, then PATH), then falls back to Windows PowerShell 5.1. - Host execution (
gateway/node) rejectsenv.PATHand loader overrides (LD_*/DYLD_*) to prevent binary hijacking or injected code. - OpenClaw sets
OPENCLAW_SHELL=execin the spawned command environment (including PTY and sandbox execution) so shell/profile rules can detect exec-tool context. openclaw channels loginis blocked fromexecbecause it is an interactive channel-auth flow; run it in a terminal on the gateway host, or use the channel-native login tool from chat when one exists.- Important: sandboxing is off by default. If sandboxing is off, implicit
host=autoresolves togateway. Explicithost=sandboxstill fails closed instead of silently running on the gateway host. Enable sandboxing or usehost=gatewaywith approvals. - Script preflight checks (for common Python/Node shell-syntax mistakes) only inspect files inside the
effective
workdirboundary. If a script path resolves outsideworkdir, preflight is skipped for that file. - For long-running work that starts now, start it once and rely on automatic
completion wake when it is enabled and the command emits output or fails.
Use
processfor logs, status, input, or intervention; do not emulate scheduling with sleep loops, timeout loops, or repeated polling. - For work that should happen later or on a schedule, use cron instead of
execsleep/delay patterns.
Config
tools.exec.notifyOnExit(default: true): when true, backgrounded exec sessions enqueue a system event and request a heartbeat on exit.tools.exec.approvalRunningNoticeMs(default: 10000): emit a single "running" notice when an approval-gated exec runs longer than this (0 disables).tools.exec.timeoutSec(default: 1800): default per-command exec timeout in seconds. Per-calltimeoutoverrides it; per-calltimeout: 0disables the exec process timeout.tools.exec.host(default:auto; resolves tosandboxwhen sandbox runtime is active,gatewayotherwise)tools.exec.security(default:denyfor sandbox,fullfor gateway + node when unset)tools.exec.ask(default:off)- No-approval host exec is the default for gateway + node. If you want approvals/allowlist behavior, tighten both
tools.exec.*and the host approvals state; see Exec approvals. - YOLO comes from the host-policy defaults (
security=full,ask=off), not fromhost=auto. If you want to force gateway or node routing, settools.exec.hostor use/exec host=.... - In
security=fullplusask=offmode, host exec follows the configured policy directly; there is no extra heuristic command-obfuscation prefilter or script-preflight rejection layer. tools.exec.node(default: unset)tools.exec.strictInlineEval(default: false): when true, inline interpreter eval forms such aspython -c,node -e,ruby -e,perl -e,php -r,lua -e, andosascript -ealways require explicit approval.allow-alwayscan still persist benign interpreter/script invocations, but inline-eval forms still prompt each time.tools.exec.commandHighlighting(default: false): when true, approval prompts can highlight parser-derived command spans in the command text. Set totrueglobally or per agent to enable command text highlighting without changing exec approval policy.tools.exec.pathPrepend: list of directories to prepend toPATHfor exec runs (gateway + sandbox only).tools.exec.safeBins: stdin-only safe binaries that can run without explicit allowlist entries. For behavior details, see Safe bins.tools.exec.safeBinTrustedDirs: additional explicit directories trusted forsafeBinspath checks.PATHentries are never auto-trusted. Built-in defaults are/binand/usr/bin.tools.exec.safeBinProfiles: optional custom argv policy per safe bin (minPositional,maxPositional,allowedValueFlags,deniedFlags).
Example:
{
tools: {
exec: {
pathPrepend: ["~/bin", "/opt/oss/bin"],
},
},
}
PATH handling
host=gateway: merges your login-shellPATHinto the exec environment.env.PATHoverrides are rejected for host execution. The daemon itself still runs with a minimalPATH:- macOS:
/opt/homebrew/bin,/usr/local/bin,/usr/bin,/bin - Linux:
/usr/local/bin,/usr/bin,/bin
- macOS:
host=sandbox: runssh -lc(login shell) inside the container, so/etc/profilemay resetPATH. OpenClaw prependsenv.PATHafter profile sourcing via an internal env var (no shell interpolation);tools.exec.pathPrependapplies here too.host=node: only non-blocked env overrides you pass are sent to the node.env.PATHoverrides are rejected for host execution and ignored by node hosts. If you need additional PATH entries on a node, configure the node host service environment (systemd/launchd) or install tools in standard locations.
Per-agent node binding (use the agent list index in config):
openclaw config get agents.list
openclaw config set agents.list[0].tools.exec.node "node-id-or-name"
Control UI: the Nodes tab includes a small "Exec node binding" panel for the same settings.
Session overrides (/exec)
Use /exec to set per-session defaults for host, security, ask, and node.
Send /exec with no arguments to show the current values.
Example:
/exec host=auto security=allowlist ask=on-miss node=mac-1
Authorization model
/exec is only honored for authorized senders (channel allowlists/pairing plus commands.useAccessGroups).
It updates session state only and does not write config. To hard-disable exec, deny it via tool
policy (tools.deny: ["exec"] or per-agent). Host approvals still apply unless you explicitly set
security=full and ask=off.
Exec approvals (companion app / node host)
Sandboxed agents can require per-request approval before exec runs on the gateway or node host.
See Exec approvals for the policy, allowlist, and UI flow.
When approvals are required, the exec tool returns immediately with
status: "approval-pending" and an approval id. Once approved (or denied / timed out),
the Gateway emits system events (Exec finished / Exec denied). If the command is still
running after tools.exec.approvalRunningNoticeMs, a single Exec running notice is emitted.
On channels with native approval cards/buttons, the agent should rely on that
native UI first and only include a manual /approve command when the tool
result explicitly says chat approvals are unavailable or manual approval is the
only path.
Allowlist + safe bins
Manual allowlist enforcement matches resolved binary path globs and bare command-name
globs. Bare names match only commands invoked through PATH, so rg can match
/opt/homebrew/bin/rg when the command is rg, but not ./rg or /tmp/rg.
When security=allowlist, shell commands are auto-allowed only if every pipeline
segment is allowlisted or a safe bin. Chaining (;, &&, ||) and redirections
are rejected in allowlist mode unless every top-level segment satisfies the
allowlist (including safe bins). Redirections remain unsupported.
Durable allow-always trust does not bypass that rule: a chained command still requires every
top-level segment to match.
autoAllowSkills is a separate convenience path in exec approvals. It is not the same as
manual path allowlist entries. For strict explicit trust, keep autoAllowSkills disabled.
Use the two controls for different jobs:
tools.exec.safeBins: small, stdin-only stream filters.tools.exec.safeBinTrustedDirs: explicit extra trusted directories for safe-bin executable paths.tools.exec.safeBinProfiles: explicit argv policy for custom safe bins.- allowlist: explicit trust for executable paths.
Do not treat safeBins as a generic allowlist, and do not add interpreter/runtime binaries (for example python3, node, ruby, bash). If you need those, use explicit allowlist entries and keep approval prompts enabled.
openclaw security audit warns when interpreter/runtime safeBins entries are missing explicit profiles, and openclaw doctor --fix can scaffold missing custom safeBinProfiles entries.
openclaw security audit and openclaw doctor also warn when you explicitly add broad-behavior bins such as jq back into safeBins.
If you explicitly allowlist interpreters, enable tools.exec.strictInlineEval so inline code-eval forms still require a fresh approval.
For full policy details and examples, see Exec approvals and Safe bins versus allowlist.
Examples
Foreground:
{ "tool": "exec", "command": "ls -la" }
Background + poll:
{"tool":"exec","command":"npm run build","yieldMs":1000}
{"tool":"process","action":"poll","sessionId":"<id>"}
Polling is for on-demand status, not waiting loops. If automatic completion wake is enabled, the command can wake the session when it emits output or fails.
Send keys (tmux-style):
{"tool":"process","action":"send-keys","sessionId":"<id>","keys":["Enter"]}
{"tool":"process","action":"send-keys","sessionId":"<id>","keys":["C-c"]}
{"tool":"process","action":"send-keys","sessionId":"<id>","keys":["Up","Up","Enter"]}
Submit (send CR only):
{ "tool": "process", "action": "submit", "sessionId": "<id>" }
Paste (bracketed by default):
{ "tool": "process", "action": "paste", "sessionId": "<id>", "text": "line1\nline2\n" }
apply_patch
apply_patch is a subtool of exec for structured multi-file edits.
It is enabled by default for OpenAI and OpenAI Codex models. Use config only
when you want to disable it or restrict it to specific models:
{
tools: {
exec: {
applyPatch: { workspaceOnly: true, allowModels: ["gpt-5.5"] },
},
},
}
Notes:
- Only available for OpenAI/OpenAI Codex models.
- Tool policy still applies;
allow: ["write"]implicitly allowsapply_patch. deny: ["write"]does not denyapply_patch; denyapply_patchexplicitly or usedeny: ["group:fs"]when patch writes should also be blocked.- Config lives under
tools.exec.applyPatch. tools.exec.applyPatch.enableddefaults totrue; set it tofalseto disable the tool for OpenAI models.tools.exec.applyPatch.workspaceOnlydefaults totrue(workspace-contained). Set it tofalseonly if you intentionally wantapply_patchto write/delete outside the workspace directory.
Related
- Exec Approvals — approval gates for shell commands
- Sandboxing — running commands in sandboxed environments
- Background Process — long-running exec and process tool
- Security — tool policy and elevated access