14.3 Headless Mode: Non-Interactive Automation
Course: Claude Code - Enterprise Development Section: 14 - CI/CD & Automation Length: 4-5 minutes Presenter: Daniel Treasure
Opening Hook
"So far we've shown Claude in interactive mode—you type, Claude responds, you approve actions. But in CI/CD, there's no human watching. Headless mode is Claude running with predefined permissions, outputting structured results, no waiting for approval. It's the foundation of all automation."
Key Talking Points
What to say:
- Headless mode = non-interactive, runs from a single prompt, produces output, exits
- Use the
-pflag to provide a prompt, Claude processes it, prints result, no chat loop - Permission modes control what Claude can do without asking:
dontAsk: Auto-denies anything not explicitly whitelisted (safest for automation)bypassPermissions: Auto-approves everything (only use in sandboxed environments)acceptEdits: Auto-approves file edits but asks about bash (good for scripts with side effects)- Pair
dontAskwith--allowedToolsto whitelist exactly what Claude can do - Structured output with
--output-format jsonmakes automation easier downstream - Cost control with
--max-turnsand--max-budget-usdprevents runaway bills - Ephemeral runs with
--no-session-persistenceleave no trace on disk—useful for CI/CD isolation
What to show on screen:
- Terminal with a simple headless command:
claude -p "analyze this file for bugs" - Output appearing instantly, no prompt
- Example with
--permission-mode dontAsk --allowedTools "Read" "Grep" - Show
--output-format jsonproducing machine-readable output - Compare with interactive mode (Chat loop) vs headless mode (one prompt → output)
- Demo cost control:
--max-turns 3 --max-budget-usd 0.50
Demo Plan (Timed)
Time: 0:00-0:45
- Open a terminal
- Show difference: interactive session (claude) vs headless (claude -p "...")
- Run a simple headless command: claude -p "list all functions in this Python file" piping a file content
- Show output—direct, clean, no back-and-forth
Time: 0:45-1:45
- Explain the 6 permission modes with a reference table on screen
- Highlight dontAsk as the automation workhorse
- Show the default mode: "Each action requires approval"
- Show dontAsk mode: "Claude only uses whitelisted tools"
Time: 1:45-2:45
- Demo --allowedTools in action:
bash
claude \
--permission-mode dontAsk \
--allowedTools "Bash(npm test)" "Read" "Grep" \
-p "Run tests and report pass/fail rate"
- Explain: Claude can call Bash (npm test only), Read files, and Grep—nothing else
- Show Claude refusing to call any tool outside the whitelist
Time: 2:45-3:45
- Show --output-format json with --json-schema for structured output
- Example: Claude outputs JSON that a downstream tool can parse
- Demo piping: claude -p "..." --output-format json | jq .issues | wc -l
- Mention --max-turns 3 to limit loops in complex tasks
Time: 3:45-4:30+
- Cost control: --max-budget-usd 0.50 cap
- Session persistence: --no-session-persistence for ephemeral runs
- Recap: headless is the backbone of CI/CD
- Preview next: Unix utility (piping, chaining)
Code Examples & Commands
Basic Headless Command
# Simple analysis, no interaction
claude -p "Check this file for SQL injection vulnerabilities" < myfile.sql
dontAsk Mode with Whitelisting
claude \
--permission-mode dontAsk \
--allowedTools "Bash(npm:*)" "Read" "Grep" \
-p "Install dependencies and run the test suite, report results"
Structured JSON Output
claude \
--output-format json \
--json-schema '{
"type": "object",
"properties": {
"issues": {
"type": "array",
"items": {"type": "string"}
},
"severity": {
"type": "string",
"enum": ["low", "medium", "high"]
}
}
}' \
-p "Analyze code for security issues. Return JSON."
Cost Control & Budget Limits
claude \
--max-turns 5 \
--max-budget-usd 0.25 \
-p "Refactor this function for performance"
Piping Input from Other Commands
# Pipe file content
cat myapp.py | claude -p "Suggest optimizations"
# Pipe git diff
git diff HEAD~1 | claude -p "Review changes for bugs"
# Piping from curl
curl https://example.com/data.json | claude -p "Extract and summarize users"
Chaining Claude Commands
# First command lists bugs, second command fixes the first bug
claude -p "List all bugs in this codebase" > bugs.txt
head -1 bugs.txt | xargs -I {} claude -p "Fix: {}"
Ephemeral Runs (No Session Persistence)
claude \
--no-session-persistence \
--permission-mode dontAsk \
--allowedTools "Read" \
-p "Quick analysis"
All 6 Permission Modes Comparison
# 1. Default (asks for each action)
claude -p "Check the code"
# 2. acceptEdits (auto-approve file edits, ask for bash)
claude --permission-mode acceptEdits -p "Refactor this file"
# 3. plan (read-only, no changes)
claude --permission-mode plan -p "Suggest improvements"
# 4. dontAsk (auto-deny unless whitelisted)
claude --permission-mode dontAsk --allowedTools "Read" -p "Analyze"
# 5. bypassPermissions (auto-approve everything—DANGEROUS, use in sandbox only)
claude --permission-mode bypassPermissions -p "Full automation"
# 6. delegate (used by SDK, not CLI)
# (SDK only)
Integration in CI/CD Script
#!/bin/bash
set -e
# Run tests with Claude automation
claude \
--permission-mode dontAsk \
--allowedTools "Bash(npm:*)" "Read" "Grep" \
--max-turns 5 \
--max-budget-usd 1.00 \
-p "Run npm test and provide a summary"
# Capture exit code, fail the script if needed
if [ $? -ne 0 ]; then
echo "Claude automation failed"
exit 1
fi
echo "CI/CD step completed successfully"
Gotchas & Tips
- dontAsk Bug #17360: In some versions (Jan 2026),
dontAskmode activated unexpectedly in interactive sessions. If you see "mode changed to dontAsk," it's a known issue. Report it and use a workaround: explicit--permission-modeflag. - Sub-agent Limits (Bug #11934): Sub-agents respect
dontAskeven with--dangerously-skip-permissions. Plan for this if you're using sub-agents in automation. - Tool Patterns:
--allowedTools "Bash(npm test:*)"means any npm test command.Bash(npm:*)means any npm command. Be specific to prevent unwanted access. - Max-turns Impact:
--max-turns 3limits reasoning loops. For simple tasks (analysis, review), 1-2 turns suffice. Complex refactoring may need 5+. - Budget Cap:
--max-budget-usd 0.50stops execution when the cap is hit mid-task. Don't set it too low; monitor costs first. - JSON Escaping: When passing
--json-schemain bash scripts, escape or use a heredoc to avoid shell interpretation. - Output Capture: Use
> output.txtor| jqto capture headless output for downstream processing. - Timeout: If running in CI/CD, set a
timeoutwrapper (e.g.,timeout 10m claude ...) to prevent hanging.
Lead-out
"Headless mode is the engine of automation. With the right permission controls and output formatting, Claude runs reliably in any CI/CD system. But headless mode shines even more when you treat Claude as a Unix utility—piping, chaining, and composing with other tools. That's next."
Reference URLs
- Claude Code Documentation - Headless Mode
- Permission Modes & dontAsk
- GitHub Issue #17360 - dontAsk unexpected activation
- GitHub Issue #11934 - Sub-agent auto-deny
- Anthropic API Docs - Cost & Rate Limits
Prep Reading
- Deep dive: Permissions Documentation — understand all 6 modes
- Review: Both bug reports #17360 and #11934 to know the edge cases
- Test: Run
claude -p "hello"in headless mode—verify it works on your setup - Experiment: Create a
.claudeconfig file with default permission settings, test overrides - Verify:
--output-format json --json-schemaproduces valid JSON for downstream tools
Notes for Daniel
- Conceptual Shift: This video pivots from "Interactive" to "Automation." Tone: technical, matter-of-fact. Viewers are engineers building pipelines.
- Pacing: Permission modes are dense. Use a visual table on screen. Give each mode 15-20 seconds.
- dontAsk Deep Dive: Spend 60 seconds on
dontAsk+--allowedTools. This is the magic that makes automation safe. - Live Demo Risk: Headless commands are fast and deterministic. Safe to demo live.
- Bug Framing: Mention #17360 and #11934 neutrally—"There are known issues we're tracking." Not a weakness, just reality of beta software.
- Smile Point: Show the piping example where git diff flows into Claude, Claude outputs JSON, jq parses it. That chain is elegant.
- Common Q: "Is dontAsk slower?" Answer: Slightly faster—no permission UI. "Can I use dontAsk in interactive mode?" Answer: Not recommended; it disables human oversight.
- Segue: "Now you have Claude running non-interactively. Let's treat it like a Unix tool—pipe, compose, integrate."