Headless commands at a glance
| Harness | Command | Machine output | Least-privilege default |
|---|---|---|---|
| Codex CLI | codex exec "…" | --json (JSONL), -o file for the final message | Read-only sandbox unless you pass --sandbox workspace-write |
| Claude Code | claude -p "…" | --output-format json (includes total_cost_usd) | --permission-mode dontAsk denies anything not pre-approved |
| OpenCode | opencode run "…" | --format json | Config-driven; most tools default to allow, so set permission |
| goose | goose run --recipe r.yaml | recipe response.json_schema | Cap the loop with --max-turns |
| Gemini CLI | gemini -p "…" | --output-format json or stream JSON | — |
| Aider | aider --message "…" file | — | Edits only the files you name |
Codex
codex exec --sandbox workspace-write \
-o summary.md \
"Run npm run lint, fix the errors, and summarize what you changed"
# machine-readable events instead:
codex exec --json "summarize the repo structure" | jqClaude Code
claude --bare -p "Run the tests and fix any failures" \
--permission-mode dontAsk \
--allowedTools "Read,Edit,Bash(npm test *)" \
--output-format json > result.json--bare skips auto-discovery of hooks, skills, plugins, MCP servers, auto memory and CLAUDE.md, so every machine gets the same run. It doesn't use your subscription login: set ANTHROPIC_API_KEY. Anthropic calls it the recommended mode for scripted calls.
OpenCode
{
"$schema": "https://opencode.ai/config.json",
"permission": { "*": "deny", "read": "allow", "grep": "allow", "glob": "allow", "edit": "allow", "bash": { "*": "deny", "npm test*": "allow" } }
}opencode run --format json -m <provider>/<model> "Run npm test and fix failures"Explicit deny rules stay enforced even with --auto, which only auto-approves requests that would otherwise ask. To avoid MCP cold starts on every run, start opencode serve once and use opencode run --attach http://localhost:4096. OpenCode also has opencode github run for GitHub Actions.
goose
goose run --recipe weekly-report.yaml \
--params week=2026-W42 \
--no-session --max-turns 10Recipes can declare a response JSON schema so the final output is structured. See the literature review recipe for a full recipe file.
Gemini CLI and Aider
gemini -p "Summarize open TODOs in src/" --output-format json
aider --message "add descriptive docstrings to all the functions" src/utils.pyExample: nightly GitHub Actions job (Codex)
name: nightly-agent
on:
schedule: [{ cron: "0 9 * * 1-5" }]
jobs:
run:
runs-on: ubuntu-latest
permissions: { contents: read }
steps:
- uses: actions/checkout@v4
- run: npm install -g @openai/codex
- run: codex exec -o report.md "Read the repo and list the 5 riskiest TODOs with file and line"
env: { CODEX_API_KEY: "${{ secrets.CODEX_API_KEY }}" }
- uses: actions/upload-artifact@v4
with: { name: report, path: report.md }This job is read-only by design: Codex's default sandbox is read-only and the workflow token can only read. Grant write access only for jobs that open pull requests.
FAQ
How do I run Codex non-interactively?
Use codex exec "task". It's read-only by default; add --sandbox workspace-write to allow edits, --json for JSONL events, or -o file to save the final message. --full-auto is no longer supported.
How do I run Claude Code in CI?
Use claude --bare -p "task" with --allowedTools for what it may do, --permission-mode dontAsk to deny everything else, and --output-format json. Bare mode needs ANTHROPIC_API_KEY.
Which harness is safest unattended?
The one whose defaults you've locked down. Codex starts read-only; Claude Code's dontAsk mode denies anything not pre-approved; OpenCode starts permissive, so set explicit deny rules.
Get new rigs by email
New job recipes and harness changes, a few times a month. Each one with copy-ready config and dated sources.
Sources
- Codex docs: non-interactive mode · checked Oct 18, 2026
- Claude Code docs: run Claude Code programmatically · checked Oct 18, 2026
- Claude Code docs: MCP · checked Oct 18, 2026
- OpenCode 1 docs: CLI · checked Oct 18, 2026
- OpenCode 1 docs: permissions · checked Oct 18, 2026
- goose docs: CLI commands · checked Oct 18, 2026
- goose docs: recipe reference · checked Oct 18, 2026
- Gemini CLI docs: headless mode · checked Oct 18, 2026
- Aider docs: scripting · checked Oct 18, 2026
Spotted something out of date? Email sternberg@mail.grokbot.com.