Bounded Automation with Claude Code CLI
Build safe autonomous jobs around claude -p with structured output, turn and cost limits, permission boundaries, and external orchestration.
What You’ll Learn
Claude Code does not need to run as an unbounded daemon to automate useful work. The supported foundation is print mode:
claude -p "Review the current diff"
It accepts a prompt, runs an agentic turn, prints the result, and exits. A scheduler, CI runner, or small wrapper owns retries and timing. This separation makes the job observable and killable.
The Safe Automation Envelope
Define five boundaries for every job:
- scope — repository and allowed directories;
- authority — permission mode and tool restrictions;
- time — maximum turns and outer process timeout;
- cost — maximum budget;
- output — text, JSON, stream JSON, or a JSON Schema.
A read-only review job:
claude -p \
--permission-mode plan \
--max-turns 8 \
--max-budget-usd 1.50 \
"Review the current diff. Do not edit files. Return findings by severity."
-p means print mode in Claude Code. Do not assume it means the same thing in another CLI: in Codex, -p selects a configuration profile.
Machine-Readable Results
Use JSON when another program consumes the final response:
claude -p \
--output-format json \
"Summarize the current git diff"
Constrain the result with a schema:
claude -p \
--output-format json \
--json-schema '{
"type": "object",
"properties": {
"verdict": {"type": "string"},
"findings": {"type": "array", "items": {"type": "string"}}
},
"required": ["verdict", "findings"]
}' \
"Audit the current diff without changing files"
For event-by-event consumers, use --output-format stream-json. Add --include-partial-messages only when your consumer is prepared to process partial streaming events.
Session Continuity
Give a job a name when later work must target it:
claude -p --name nightly-review "Review the repository status"
Resume a known session:
claude -p --resume nightly-review "Re-check only the unresolved findings"
Continue the most recent eligible session:
claude -p --continue "Run the affected tests and report the result"
Use --no-session-persistence for stateless jobs that must not create resumable history.
Put the Loop Outside Claude Code
An external scheduler should decide when to run and whether to retry:
#!/usr/bin/env bash
set -euo pipefail
claude -p \
--permission-mode plan \
--max-turns 6 \
--max-budget-usd 1.00 \
--output-format json \
"Inspect the repository and report whether the documented verification command should run."
The wrapper can enforce an OS timeout, capture exit status, store logs, and notify a human. Claude Code remains one bounded process per attempt.
Do not place --dangerously-skip-permissions into unattended templates. It removes an important safety boundary and should require a separately reviewed environment.
CI Pattern
A reliable CI job has explicit input and a non-mutating prompt:
git diff --exit-code -- . >/dev/null || true
claude -p \
--permission-mode plan \
--max-turns 10 \
--output-format json \
--json-schema '{"type":"object","properties":{"pass":{"type":"boolean"},"reason":{"type":"string"}},"required":["pass","reason"]}' \
"Review the checked-out change against AGENTS.md. Do not modify files."
Then let CI interpret the structured result. Do not treat a fluent text response as a passing build; tests, lint, type checks, and deployment verifiers remain the authoritative gates.
Operational Checklist
- pin or record the Claude Code version;
- run in a clean, scoped checkout;
- choose a permission mode explicitly;
- cap turns, budget, and outer runtime;
- request structured output for machine consumers;
- retain stderr and exit status;
- retry only failures known to be safe;
- escalate ambiguous results instead of looping forever.
Next Session
Session 12 adds Git worktree isolation so multiple Claude Code sessions can operate without sharing the same writable checkout.