Shell Tool
Execute arbitrary shell commands in the user's environment.
Overview
The shell tool allows agents to execute arbitrary shell commands synchronously. This is one of the most powerful tools — it lets agents run builds, install dependencies, query APIs, and interact with the system. Each call runs in a fresh, isolated shell session — no state persists between calls.
Commands have a default 30-second timeout and require user confirmation unless --yolo is used. For servers, watchers, and other long-running commands, add the background_jobs toolset alongside shell.
Configuration
toolsets:
- type: shell
Options
| Property | Type | Description |
|---|---|---|
env |
object | Environment variables to set for all shell commands |
safer |
boolean | Deprecated and ignored — shell commands are always classified now (see Command classification). Kept so existing YAMLs still parse. |
sudo_askpass |
boolean | Opt in to prompting for a sudo password (see Sudo support). Default false. |
Custom Environment Variables
toolsets:
- type: shell
env:
MY_VAR: "value"
PATH: "${env.PATH}:/custom/bin"
Command classification
Every shell command is classified against an embedded taxonomy before the approval decision — no opt-in required:
- Destructive matches (
rm -rf <path>,docker volume rm,mkfs,dd if=… of=/dev/<disk>, …) are labelleddestructivewith ablast_radius(low/medium/high) and acategorytag. The TUI confirmation dialog renders the blast radius with a color badge. - Known-safe reads (
ls,cat,git status,git diff,docker ps,docker logs,kubectl get, …) are labelledsafe. - Everything else is labelled
unknown.
The session's safety mode decides what each label means: strict asks about everything, balanced auto-runs safe commands and asks about destructive/unknown ones, autonomous runs everything. Custom permission rules always win over the mode.
Compound shell (a && b, a; b, a | b) is never matched against the safe allowlist; any destructive segment falls through to ask. The full taxonomy lives in pkg/safety/safety_patterns.json.
See examples/safety_modes.yaml for a full example. The legacy safer: true toolset flag is deprecated and ignored.
Sudo support
By default a shell command has no controlling terminal, so a sudo command that needs a password hangs until it times out (the agent usually gives up and falls back to printing manual instructions).
Set sudo_askpass: true to enable a sudo privilege escalation flow:
toolsets:
- type: shell
sudo_askpass: true
When enabled, sudo commands prompt you for your password through the host UI (the input is masked). The password is handed to sudo over a private, per-session socket via the standard SUDO_ASKPASS mechanism — it is never written to the command line, the logs, or stored by the agent.
The bridge environment variables (SUDO_ASKPASS, CAGENT_ASKPASS_SOCKET, CAGENT_ASKPASS_TOKEN) are added only to commands that invoke sudo, but within such a command they are visible to every child process, not just sudo. They carry a socket path and a session token, not the password; the socket lives in a 0700 directory, so only your own user can reach it.
Notes and limitations:
- Unix only. The flag has no effect on Windows.
- Interactive UI only. In headless / non-interactive runs the prompt is declined automatically and
sudofails as before. - Only a bare
sudo ...invocation in a POSIX shell (sh,bash,zsh, ...) is handled.sudocalled by absolute path (/usr/bin/sudo), viaenv sudo, from inside a nested script, or under a non-POSIX shell (e.g.fish) is not intercepted and behaves as before. - Caching is
sudo's own. Because each shell tool call runs in a fresh shell with no controlling terminal,sudo's credential cache does not persist across separate tool calls: you are prompted once per shell command that usessudo. Within a single command, multiplesudocalls (e.g.sudo a && sudo b) usually share one prompt, subject tosudo's own timestamp configuration. - The prompt must be answered within the command's timeout; raise the
timeoutparameter forsudocommands that may wait on input. - Prompts are serialized: if a single command runs two
sudocalls in parallel (e.g.sudo a & sudo b), the second waits for the first prompt to be answered rather than opening two dialogs at once.
Available Tools
The shell toolset exposes one tool:
| Tool Name | Description |
|---|---|
shell |
Run a command synchronously and return its combined output when it finishes. |
shell parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
cmd |
string | ✓ | The shell command to execute. |
cwd |
string | ✗ | Working directory to run the command in (default: .). |
timeout |
integer | ✗ | Per-call execution timeout in seconds (default: 30). |
The shell tool gives agents full access to the system shell. Always set max_iterations on agents that use the shell tool to prevent infinite loops. A value of 20–50 is typical for development agents. Use Sandbox Mode for additional isolation.
By default, Docker Agent asks for user confirmation before executing shell commands. Use --yolo to auto-approve all tool calls.