Background Exec and Process Tool for Shell Commands
Learn how OpenClaw uses the exec tool to run shell commands and the process tool to manage background sessions. This guide is for developers needing to execute and control long-running tasks.
Read this when
- Adding or modifying background exec behavior
- Debugging long-running exec tasks
OpenClaw uses the exec tool to execute shell commands and holds long running tasks in memory. Background sessions are managed by the process tool.
exec tool
Parameters:
| Parameter | Description |
|---|---|
command | Mandatory. The shell command that will be executed. |
workdir | Sets the working directory; if not provided, the default cwd is used. |
env | Additional environment variables passed to the command. |
yieldMs | Time in milliseconds before the process is moved to the background (default is 10000). |
background | Forces the command to run in the background right away. |
timeout | A timeout value in seconds (default tools.exec.timeoutSeconds); the process is killed when this time expires. To disable the exec process timeout for a specific call, use timeout: 0. |
pty | When a pseudo-terminal is available, runs inside one (useful for TTY requiring CLIs and coding agents). |
elevated | If elevated mode is enabled and permitted, runs outside the sandbox (gateway by default, or node when the exec target is node). |
host | Specifies the exec target: auto, sandbox, gateway, or node. |
node | A node ID or name, used together with host: "node". |
Behavior:
- Direct output is returned for foreground executions.
- When a command is backgrounded (either explicitly or after the
yieldMstimeout), the tool providesstatus: "running"plussessionIdalong with a short tail of the output. - Backgrounded and
yieldMsruns adopttools.exec.timeoutSecondsunless an explicittimeoutis provided in the call. - Output remains in memory until the session is either polled or cleared.
- If the
processtool is not allowed,execexecutes synchronously andyieldMsandbackgroundare ignored. - Exec commands that are spawned receive
OPENCLAW_SHELL=execto support context aware shell and profile rules. - For long running work that must begin immediately: start it once and let automatic completion wake (when enabled) trigger when the command produces output or fails.
- If automatic completion wake is not available, or you need confirmation of a clean exit for a command that produces no output, use
processto poll. - Do not use
sleeploops or repeated polling to simulate reminders or delayed follow ups; use cron for future scheduled tasks.
Env overrides
| Variable | Effect |
|---|---|
OPENCLAW_BASH_YIELD_MS | Default delay before backgrounding, in milliseconds. Default is 10000, clamped between 10 and 120000. |
OPENCLAW_BASH_MAX_OUTPUT_CHARS | Maximum number of characters kept in memory for output. |
OPENCLAW_BASH_PENDING_MAX_OUTPUT_CHARS | Per stream cap for pending stdout and stderr, measured in characters. |
OPENCLAW_BASH_JOB_TTL_MS | Time to live for finished sessions, in milliseconds, bounded between 1 minute and 3 hours. |
OPENCLAW_PROCESS_INPUT_WAIT_IDLE_MS | Idle output threshold in milliseconds; writable background sessions that exceed this are marked as likely waiting for input. Default is 15000. |
Config (preferred over env overrides)
| Key | Default | Effect |
|---|---|---|
tools.exec.backgroundMs | 10000 | Identical to OPENCLAW_BASH_YIELD_MS. |
tools.exec.timeoutSeconds | 1800 | Default timeout applied per call. |
tools.exec.cleanupMs | 1800000 | Identical to OPENCLAW_BASH_JOB_TTL_MS. |
tools.exec.notifyOnExit | true | When a backgrounded exec exits, enqueues a system event and requests a heartbeat. |
tools.exec.notifyOnExitEmptySuccess | false | Also enqueues completion events for backgrounded runs that succeed but produce no output. |
Child process bridging
When long running child processes are spawned outside the exec or process tools (such as CLI respawns or gateway helpers), attach the child process bridge helper. This ensures termination signals are forwarded and listeners are detached on exit or error. Orphaned processes on systemd are prevented, and shutdown remains consistent across all platforms.
process tool
Actions:
| Action | Effect |
|---|---|
list | Sessions that are running or have completed. |
poll | Pull fresh output from a session (also provides the exit code). |
log | Retrieve combined output together with input recovery suggestions. Works with offset and limit. |
write | Feed data to stdin (data, optionally eof). |
send-keys | Transmit explicit key codes or byte sequences to a PTY session. |
submit | Dispatch an Enter or carriage return to a PTY session. |
paste | Send plain text, optionally enclosed in bracketed paste mode. |
kill | Stop a background session. |
clear | Erase a completed session from memory. |
remove | Stop it if active; otherwise delete it if done. |
Notes:
- Only background sessions are tracked and retained, kept solely in memory, never written to disk. They disappear when the process restarts.
- An active background session prevents cooperative host suspension and a safe Gateway restart until the process owner confirms the session has actually exited.
process removecan conceal a running session right after a termination request; suspension and restart remain blocked until exit is confirmed.- Session logs enter the chat history only when you run
process poll/logand the tool's result gets recorded. processis agent scoped; it only sees sessions that agent itself launched.- Use
poll/logto check status, logs, or completion confirmation when automatic completion wake is not available. - Use
logbefore resuming an interactive CLI so the current transcript, stdin state, and input wait hint are all visible at once. - Use
write/send-keys/submit/paste/killwhen you need to supply input or take action. process listcontains a generatedname(command verb plus target) for quick scanning.process list,poll, andlogreportwaitingForInputonly when the session still has writable stdin and has been idle longer than the input wait threshold (default 15000 ms,OPENCLAW_PROCESS_INPUT_WAIT_IDLE_MS).process loguses line orientedoffset/limit. When both are omitted, it returns the last 200 lines with a paging hint. Whenoffsetis set andlimitis not, it returns fromoffsetto the end (not limited to 200).poll'stimeoutwaits up to that many milliseconds before returning; values above 30000 are clamped to 30000.- Polling is meant for on demand status checks, not for loop based waiting. If the work should run later, use cron.
Examples
Run a long task and check back later:
{ "tool": "exec", "command": "sleep 5 && echo done", "yieldMs": 1000 }
{ "tool": "process", "action": "poll", "sessionId": "<id>" }
Examine an interactive session before sending input:
{ "tool": "process", "action": "log", "sessionId": "<id>" }
Launch immediately in background:
{ "tool": "exec", "command": "npm run build", "background": true }
Send stdin:
{ "tool": "process", "action": "write", "sessionId": "<id>", "data": "y\n" }
Send PTY keys:
{ "tool": "process", "action": "send-keys", "sessionId": "<id>", "keys": ["C-c"] }
Submit current line:
{ "tool": "process", "action": "submit", "sessionId": "<id>" }
Paste literal text:
{ "tool": "process", "action": "paste", "sessionId": "<id>", "text": "line1\nline2\n" }