mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-19 23:24:46 +00:00
* 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>
282 lines
15 KiB
Markdown
282 lines
15 KiB
Markdown
---
|
|
summary: "Exec tool usage, stdin modes, and TTY support"
|
|
read_when:
|
|
- Using or modifying the exec tool
|
|
- Debugging stdin or TTY behavior
|
|
title: "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
|
|
|
|
<ParamField path="command" type="string" required>
|
|
Shell command to run.
|
|
</ParamField>
|
|
|
|
<ParamField path="workdir" type="string" default="cwd">
|
|
Working directory for the command.
|
|
</ParamField>
|
|
|
|
<ParamField path="env" type="object">
|
|
Key/value environment overrides merged on top of the inherited environment.
|
|
</ParamField>
|
|
|
|
<ParamField path="yieldMs" type="number" default="10000">
|
|
Auto-background the command after this delay (ms).
|
|
</ParamField>
|
|
|
|
<ParamField path="background" type="boolean" default="false">
|
|
Background the command immediately instead of waiting for `yieldMs`.
|
|
</ParamField>
|
|
|
|
<ParamField path="timeout" type="number" default="tools.exec.timeoutSec">
|
|
Override the configured exec timeout for this call. Set `timeout: 0` only when the command should run without the exec process timeout.
|
|
</ParamField>
|
|
|
|
<ParamField path="pty" type="boolean" default="false">
|
|
Run in a pseudo-terminal when available. Use for TTY-only CLIs, coding agents, and terminal UIs.
|
|
</ParamField>
|
|
|
|
<ParamField path="host" type="'auto' | 'sandbox' | 'gateway' | 'node'" default="auto">
|
|
Where to execute. `auto` resolves to `sandbox` when a sandbox runtime is active and `gateway` otherwise.
|
|
</ParamField>
|
|
|
|
<ParamField path="security" type="'deny' | 'allowlist' | 'full'">
|
|
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.
|
|
</ParamField>
|
|
|
|
<ParamField path="ask" type="'off' | 'on-miss' | 'always'">
|
|
Approval prompt behavior for `gateway` / `node` execution.
|
|
</ParamField>
|
|
|
|
<ParamField path="node" type="string">
|
|
Node id/name when `host=node`.
|
|
</ParamField>
|
|
|
|
<ParamField path="elevated" type="boolean" default="false">
|
|
Request elevated mode — escape the sandbox onto the configured host path. `security=full` is forced only when elevated resolves to `full`.
|
|
</ParamField>
|
|
|
|
Notes:
|
|
|
|
- `host` defaults to `auto`: sandbox when sandbox runtime is active for the session, otherwise gateway.
|
|
- `host` only accepts `auto`, `sandbox`, `gateway`, or `node`. It is not a hostname selector; hostname-like values are rejected before the command runs.
|
|
- `auto` is the default routing strategy, not a wildcard. Per-call `host=node` is allowed from `auto`; per-call `host=gateway` is only allowed when no sandbox runtime is active.
|
|
- With no extra config, `host=auto` still "just works": no sandbox means it resolves to `gateway`; a live sandbox means it stays in the sandbox.
|
|
- `elevated` escapes the sandbox onto the configured host path: `gateway` by default, or `node` when `tools.exec.host=node` (or the session default is `host=node`). It is only available when elevated access is enabled for the current session/provider.
|
|
- `gateway`/`node` approvals are controlled by host-local SQLite approvals state.
|
|
- `node` requires a paired node (companion app or headless node host).
|
|
- If multiple nodes are available, set `exec.node` or `tools.exec.node` to select one.
|
|
- `exec host=node` is the only shell-execution path for nodes; the legacy `nodes.run` wrapper has been removed.
|
|
- `timeout` applies to foreground, background, `yieldMs`, gateway, sandbox, and node `system.run` execution. If omitted, OpenClaw uses `tools.exec.timeoutSec`; explicit `timeout: 0` disables the exec process timeout for that call.
|
|
- On non-Windows hosts, exec uses `SHELL` when set; if `SHELL` is `fish`, it prefers `bash` (or `sh`)
|
|
from `PATH` to avoid fish-incompatible scripts, then falls back to `SHELL` if 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`) rejects `env.PATH` and loader overrides (`LD_*`/`DYLD_*`) to
|
|
prevent binary hijacking or injected code.
|
|
- OpenClaw sets `OPENCLAW_SHELL=exec` in the spawned command environment (including PTY and sandbox execution) so shell/profile rules can detect exec-tool context.
|
|
- `openclaw channels login` is blocked from `exec` because 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=auto`
|
|
resolves to `gateway`. Explicit `host=sandbox` still fails closed instead of silently
|
|
running on the gateway host. Enable sandboxing or use `host=gateway` with approvals.
|
|
- Script preflight checks (for common Python/Node shell-syntax mistakes) only inspect files inside the
|
|
effective `workdir` boundary. If a script path resolves outside `workdir`, 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 `process` for 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
|
|
`exec` sleep/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-call `timeout` overrides it; per-call `timeout: 0` disables the exec process timeout.
|
|
- `tools.exec.host` (default: `auto`; resolves to `sandbox` when sandbox runtime is active, `gateway` otherwise)
|
|
- `tools.exec.security` (default: `deny` for sandbox, `full` for 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](/tools/exec-approvals#yolo-mode-no-approval).
|
|
- YOLO comes from the host-policy defaults (`security=full`, `ask=off`), not from `host=auto`. If you want to force gateway or node routing, set `tools.exec.host` or use `/exec host=...`.
|
|
- In `security=full` plus `ask=off` mode, 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 as `python -c`, `node -e`, `ruby -e`, `perl -e`, `php -r`, `lua -e`, and `osascript -e` always require explicit approval. `allow-always` can 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 to `true` globally or per agent to enable command text highlighting without changing exec approval policy.
|
|
- `tools.exec.pathPrepend`: list of directories to prepend to `PATH` for 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-approvals-advanced#safe-bins-stdin-only).
|
|
- `tools.exec.safeBinTrustedDirs`: additional explicit directories trusted for `safeBins` path checks. `PATH` entries are never auto-trusted. Built-in defaults are `/bin` and `/usr/bin`.
|
|
- `tools.exec.safeBinProfiles`: optional custom argv policy per safe bin (`minPositional`, `maxPositional`, `allowedValueFlags`, `deniedFlags`).
|
|
|
|
Example:
|
|
|
|
```json5
|
|
{
|
|
tools: {
|
|
exec: {
|
|
pathPrepend: ["~/bin", "/opt/oss/bin"],
|
|
},
|
|
},
|
|
}
|
|
```
|
|
|
|
### PATH handling
|
|
|
|
- `host=gateway`: merges your login-shell `PATH` into the exec environment. `env.PATH` overrides are
|
|
rejected for host execution. The daemon itself still runs with a minimal `PATH`:
|
|
- macOS: `/opt/homebrew/bin`, `/usr/local/bin`, `/usr/bin`, `/bin`
|
|
- Linux: `/usr/local/bin`, `/usr/bin`, `/bin`
|
|
- `host=sandbox`: runs `sh -lc` (login shell) inside the container, so `/etc/profile` may reset `PATH`.
|
|
OpenClaw prepends `env.PATH` after profile sourcing via an internal env var (no shell interpolation);
|
|
`tools.exec.pathPrepend` applies here too.
|
|
- `host=node`: only non-blocked env overrides you pass are sent to the node. `env.PATH` overrides 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):
|
|
|
|
```bash
|
|
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](/tools/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](/tools/exec-approvals-advanced#safe-bins-stdin-only) and [Safe bins versus allowlist](/tools/exec-approvals-advanced#safe-bins-versus-allowlist).
|
|
|
|
## Examples
|
|
|
|
Foreground:
|
|
|
|
```json
|
|
{ "tool": "exec", "command": "ls -la" }
|
|
```
|
|
|
|
Background + poll:
|
|
|
|
```json
|
|
{"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):
|
|
|
|
```json
|
|
{"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):
|
|
|
|
```json
|
|
{ "tool": "process", "action": "submit", "sessionId": "<id>" }
|
|
```
|
|
|
|
Paste (bracketed by default):
|
|
|
|
```json
|
|
{ "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:
|
|
|
|
```json5
|
|
{
|
|
tools: {
|
|
exec: {
|
|
applyPatch: { workspaceOnly: true, allowModels: ["gpt-5.5"] },
|
|
},
|
|
},
|
|
}
|
|
```
|
|
|
|
Notes:
|
|
|
|
- Only available for OpenAI/OpenAI Codex models.
|
|
- Tool policy still applies; `allow: ["write"]` implicitly allows `apply_patch`.
|
|
- `deny: ["write"]` does not deny `apply_patch`; deny `apply_patch` explicitly or use `deny: ["group:fs"]` when patch writes should also be blocked.
|
|
- Config lives under `tools.exec.applyPatch`.
|
|
- `tools.exec.applyPatch.enabled` defaults to `true`; set it to `false` to disable the tool for OpenAI models.
|
|
- `tools.exec.applyPatch.workspaceOnly` defaults to `true` (workspace-contained). Set it to `false` only if you intentionally want `apply_patch` to write/delete outside the workspace directory.
|
|
|
|
## Related
|
|
|
|
- [Exec Approvals](/tools/exec-approvals) — approval gates for shell commands
|
|
- [Sandboxing](/gateway/sandboxing) — running commands in sandboxed environments
|
|
- [Background Process](/gateway/background-process) — long-running exec and process tool
|
|
- [Security](/gateway/security) — tool policy and elevated access
|