8.8 KiB
Headless mode
Run Claude Code programmatically without interactive UI
Overview
The headless mode allows you to run Claude Code programmatically from command line scripts and automation tools without any interactive UI.
Basic usage
The primary command-line interface to Claude Code is the claude command. Use the --print (or -p) flag to run in non-interactive mode and print the final result:
claude -p "Stage my changes and write a set of commits for them" \
--allowedTools "Bash,Read" \
--permission-mode acceptEdits
Configuration Options
Headless mode leverages all the CLI options available in Claude Code. Here are the key ones for automation and scripting:
| Flag | Description | Example |
|---|---|---|
--print, -p |
Run in non-interactive mode | claude -p "query" |
--output-format |
Specify output format (text, json, stream-json) |
claude -p --output-format json |
--resume, -r |
Resume a conversation by session ID | claude --resume abc123 |
--continue, -c |
Continue the most recent conversation | claude --continue |
--verbose |
Enable verbose logging | claude --verbose |
--append-system-prompt |
Append to system prompt (only with --print) |
claude --append-system-prompt "Custom instruction" |
--allowedTools |
Space-separated list of allowed tools, or string of comma-separated list of allowed tools |
claude --allowedTools mcp__slack mcp__filesystemclaude --allowedTools "Bash(npm install),mcp__filesystem" |
--disallowedTools |
Space-separated list of denied tools, or string of comma-separated list of denied tools |
claude --disallowedTools mcp__splunk mcp__githubclaude --disallowedTools "Bash(git commit),mcp__github" |
--mcp-config |
Load MCP servers from a JSON file | claude --mcp-config servers.json |
--permission-prompt-tool |
MCP tool for handling permission prompts (only with --print) |
claude --permission-prompt-tool mcp__auth__prompt |
For a complete list of CLI options and features, see the CLI reference documentation.
Multi-turn conversations
For multi-turn conversations, you can resume conversations or continue from the most recent session:
# Continue the most recent conversation
claude --continue "Now refactor this for better performance"
# Resume a specific conversation by session ID
claude --resume 550e8400-e29b-41d4-a716-446655440000 "Update the tests"
# Resume in non-interactive mode
claude --resume 550e8400-e29b-41d4-a716-446655440000 "Fix all linting issues" --no-interactive
Output Formats
Text Output (Default)
claude -p "Explain file src/components/Header.tsx"
# Output: This is a React component showing...
JSON Output
Returns structured data including metadata:
claude -p "How does the data layer work?" --output-format json
Response format:
{
"type": "result",
"subtype": "success",
"total_cost_usd": 0.003,
"is_error": false,
"duration_ms": 1234,
"duration_api_ms": 800,
"num_turns": 6,
"result": "The response text here...",
"session_id": "abc123"
}
Streaming JSON Output
Streams each message as it is received:
claude -p "Build an application" --output-format stream-json
Each conversation begins with an initial init system message, followed by a list of user and assistant messages, followed by a final result system message with stats. Each message is emitted as a separate JSON object.
Input Formats
Text Input (Default)
# Direct argument
claude -p "Explain this code"
# From stdin
echo "Explain this code" | claude -p
Streaming JSON Input
A stream of messages provided via stdin where each message represents a user turn. This allows multiple turns of a conversation without re-launching the claude binary and allows providing guidance to the model while it is processing a request.
Each message is a JSON 'User message' object, following the same format as the output message schema. Messages are formatted using the jsonl format where each line of input is a complete JSON object. Streaming JSON input requires -p and --output-format stream-json.
echo '{"type":"user","message":{"role":"user","content":[{"type":"text","text":"Explain this code"}]}}' | claude -p --output-format=stream-json --input-format=stream-json --verbose
Agent Integration Examples
SRE Incident Response Bot
#!/bin/bash
# Automated incident response agent
investigate_incident() {
local incident_description="$1"
local severity="${2:-medium}"
claude -p "Incident: $incident_description (Severity: $severity)" \
--append-system-prompt "You are an SRE expert. Diagnose the issue, assess impact, and provide immediate action items." \
--output-format json \
--allowedTools "Bash,Read,WebSearch,mcp__datadog" \
--mcp-config monitoring-tools.json
}
# Usage
investigate_incident "Payment API returning 500 errors" "high"
Automated Security Review
# Security audit agent for pull requests
audit_pr() {
local pr_number="$1"
gh pr diff "$pr_number" | claude -p \
--append-system-prompt "You are a security engineer. Review this PR for vulnerabilities, insecure patterns, and compliance issues." \
--output-format json \
--allowedTools "Read,Grep,WebSearch"
}
# Usage and save to file
audit_pr 123 > security-report.json
Multi-turn Legal Assistant
# Legal document review with session persistence
session_id=$(claude -p "Start legal review session" --output-format json | jq -r '.session_id')
# Review contract in multiple steps
claude -p --resume "$session_id" "Review contract.pdf for liability clauses"
claude -p --resume "$session_id" "Check compliance with GDPR requirements"
claude -p --resume "$session_id" "Generate executive summary of risks"
Best Practices
-
Use JSON output format for programmatic parsing of responses:
# Parse JSON response with jq result=$(claude -p "Generate code" --output-format json) code=$(echo "$result" | jq -r '.result') cost=$(echo "$result" | jq -r '.cost_usd') -
Handle errors gracefully - check exit codes and stderr:
if ! claude -p "$prompt" 2>error.log; then echo "Error occurred:" >&2 cat error.log >&2 exit 1 fi -
Use session management for maintaining context in multi-turn conversations
-
Consider timeouts for long-running operations:
timeout 300 claude -p "$complex_prompt" || echo "Timed out after 5 minutes" -
Respect rate limits when making multiple requests by adding delays between calls
Related Resources
- CLI usage and controls - Complete CLI documentation
- Common workflows - Step-by-step guides for common use cases