Headless Mode
Run Command Code non-interactively in scripts, CI/CD pipelines, and automation workflows. Headless mode executes a single query, outputs the response to stdout, and exits.
Use the -p (or --print) flag to run in headless mode:
Direct Argument
Pass your query directly after the -p flag:
Piped Stdin
Pipe input from another command or file:
Command Code auto-detects piped input when no query argument is provided. If stdin is a TTY and no query is given, it exits with an error.
By default, headless mode blocks tools that modify your system - file writes, file edits, and shell commands are denied. This keeps automated runs safe.
To enable all tools, pass --yolo:
--dangerously-skip-permissionsis also accepted as an alias.
| Tool | Default (no flag) | With --yolo |
|---|---|---|
| File reads, grep, glob | Allowed | Allowed |
| File edits and writes | Blocked | Allowed |
| Shell commands | Blocked | Allowed |
Headless runs still go through the permission engine. The complete guide
covers dont-ask — the fail-closed allowlist mode built for CI — plus rule
syntax and the decision ladder.
Headless mode supports multi-turn tool execution. Command Code can read files, search code, and (with permissions) edit files and run commands, just like interactive mode.
The conversation loop runs for up to 100 turns by default. Raise or lower it with --max-turns. If the limit is reached, a warning is printed to stderr and the partial response is returned.
--output-format json turns print mode into a machine-readable stream. Use it when a script needs to react to the run, not just read the final answer.
The stream is newline-delimited JSON (NDJSON), one object per line, in two shapes.
Event frames, one per AgentEvent as the run progresses:
One final result line, always last:
| Field | Always present? | Notes |
|---|---|---|
subtype | yes | success, error, or max_turns - comes first so a consumer can peek the outcome cheaply |
usage | yes | Token usage totals for the run |
durationMs | yes | Wall-clock duration |
finalText | yes | The assistant's final answer, same text --output-format text would print. Empty string on an error result |
sessionId | optional | Omitted when the run fails before a session is resolved (bad input, auth failure) |
stopReason | optional | Why the loop ended (end_turn, max_turns, …). Omitted entirely on an error result |
error | optional | Present only when subtype is error - stderr keeps the human-readable copy |
--output-format text (the default) keeps the classic behavior: just the final answer on stdout.
Each headless run persists its transcript to disk, so you can chain follow-up queries that keep prior context. Headless sessions are tagged separately and stay hidden from the interactive /resume menu and from interactive --continue - automation never pollutes your interactive history.
Continue the most recent run
--continue (or -c) resumes the most recent headless session in the current directory:
If no headless session exists yet, --continue starts a fresh one - so a -p --continue loop works from the first iteration.
Resume a specific session
Print the session id with --verbose (written to stderr, so stdout stays clean for piping):
Then resume that exact session by id:
Open a headless session in interactive mode
Pass a headless session id to plain cmd --resume <id> (without -p) to load that transcript into a full interactive session:
Use exit codes to handle results in scripts and CI/CD:
| Code | Meaning | Constant |
|---|---|---|
0 | Success | EXIT_SUCCESS |
1 | General error | EXIT_ERROR |
3 | Not authenticated | EXIT_AUTH_ERROR |
4 | Permission denied | EXIT_PERMISSION_DENIED |
5 | Rate limit exceeded | EXIT_RATE_LIMITED |
6 | Network failure | EXIT_CONNECTION_ERROR |
7 | API server error (5xx) | EXIT_SERVER_ERROR |
8 | Max turns reached before final answer | EXIT_MAX_TURNS_REACHED |
9 | Model produced no response | EXIT_NO_RESPONSE |
10 | Insufficient credits | EXIT_INSUFFICIENT_CREDITS |
130 | Interrupted (SIGINT/SIGTERM) | EXIT_INTERRUPTED |
Example usage in a script:
Headless mode is pipe-friendly. Output goes to stdout, errors and warnings go to stderr:
Flags useful for headless and automated workflows:
| Flag | Description |
|---|---|
-p, --print [query] | Run in headless mode |
--output-format <format> | Print-mode output: text (default) or json - see JSON output |
-c, --continue | Resume the most recent headless session in this directory |
-r, --resume <id> | Resume a specific headless session by id (no bare picker in print mode) |
--verbose | Print the resolved session id to stderr (for chaining --resume) |
--max-turns <number> | Maximum conversation turns in print mode (default: 100, no upper bound) |
-m, --model <model> | Run on a specific model this session |
--effort <level> | Set reasoning effort (low, medium, high, …) |
--theme <theme> | Set the color theme (dark or light) |
--config <key=value> | Set any setting headlessly (repeatable) - see below |
--yolo | Allow file writes and shell commands |
--auto-accept | Start in auto-accept mode (alias for --permission-mode auto-accept) |
--skip-onboarding | Skip taste onboarding (for CI/automated runs) |
-t, --trust | Auto-trust project (skip initial permission prompt) |
--plan | Start in plan mode (read-only exploration) |
--permission-mode <mode> | Set permission mode: standard, plan, auto-accept |
Slash commands are interactive-only, but the settings behind them are available as flags -
never as a /slash string on the command line. The common ones have dedicated flags
(--model, --effort, --theme), and --config key=value reaches any setting the /config
UI can change:
--config is the headless equivalent of the interactive /config UI, so a new setting becomes
scriptable automatically. Confirmations print to stderr, keeping -p stdout clean.
| Limitation | Details |
|---|---|
| No interactive prompts | No keyboard shortcuts or interactive UI. Slash commands aren't typed here - use flags instead (see Configuring settings); session-lifecycle commands like /clear and /reload have no meaning in one-shot mode |
| No resume picker | A bare --resume errors in print mode; resume by explicit id or use --continue |
| Stdin timeout | Piped stdin times out after 30 seconds if no data is received |
- See CLI Reference for the full list of flags and commands
- Learn about Interactive Mode for full-featured sessions
- Join our Discord community for support