Claude-skill-registry claude-headless-mode
Guide for using claude CLI in headless mode with --print, output formats, and JSON schema
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/claude-headless-mode" ~/.claude/skills/majiayu000-claude-skill-registry-claude-headless-mode && rm -rf "$T"
manifest:
skills/data/claude-headless-mode/SKILL.mdsource content
Claude Headless Mode
Use
claude -p (or --print) for non-interactive execution in scripts, CI, and automation.
Basic Usage
# Simple prompt claude -p "Summarize this repo" # With file input claude -p "Review this code" < file.py # Pipe output claude -p "List all functions" | grep "def "
Output Formats
| Format | Flag | Use Case |
|---|---|---|
| Text | | Human-readable (default) |
| JSON | | Single JSON result |
| Stream JSON | | Real-time streaming |
Text Output (Default)
claude -p "What is 2+2?" # Output: 4
JSON Output
claude -p "What is 2+2?" --output-format json
Returns wrapper with metadata:
{ "type": "result", "subtype": "success", "result": "4", "duration_ms": 1234, "total_cost_usd": 0.01, "session_id": "...", "structured_output": null }
Extract just the result:
claude -p "What is 2+2?" --output-format json | jq -r '.result'
Stream JSON Output
claude -p "Long analysis" --output-format stream-json --verbose
- Streams newline-delimited JSON as execution progresses
- Shows tool calls, messages, progress in real-time
- Final line contains the result
- Requires
flag--verbose
Extract final result:
claude -p "Analyze code" --output-format stream-json --verbose \ | tee /dev/stderr \ | tail -1 \ | jq -r '.result'
Structured Output with JSON Schema
Force Claude to return data matching a specific schema:
claude -p "Extract function names from auth.py" \ --output-format json \ --json-schema '{ "type": "object", "properties": { "functions": { "type": "array", "items": { "type": "string" } } }, "required": ["functions"] }'
Result appears in
structured_output field:
{ "result": "...", "structured_output": { "functions": ["login", "logout", "verify_token"] } }
Schema Examples
Simple object:
{ "type": "object", "properties": { "answer": { "type": "integer" } }, "required": ["answer"] }
Task result (success/failure):
{ "type": "object", "properties": { "status": { "type": "string", "enum": ["success", "failure"] }, "summary": { "type": "string" }, "files_changed": { "type": "array", "items": { "type": "string" } }, "error_category": { "type": "string" }, "suggestion": { "type": "string" } }, "required": ["status", "summary"] }
Extract from schema result:
OUTPUT=$(claude -p "$PROMPT" --output-format json --json-schema "$SCHEMA") STATUS=$(echo "$OUTPUT" | jq -r '.structured_output.status') SUMMARY=$(echo "$OUTPUT" | jq -r '.structured_output.summary')
Common Options
| Option | Description |
|---|---|
| Headless mode (required) |
| text, json, stream-json |
| Enforce output schema |
| Required for stream-json |
| Select model (sonnet, opus, haiku) |
| Limit agentic turns |
| bypassPermissions, plan, etc. |
| Restrict available tools |
Permission Modes
# Skip all permission prompts (trusted environments only) claude -p "Fix all linting errors" --permission-mode bypassPermissions # Plan mode (read-only exploration) claude -p "Analyze architecture" --permission-mode plan
Examples
CI/CD Integration
# Run tests and get structured result RESULT=$(claude -p "Run tests and report results" \ --output-format json \ --json-schema '{"type":"object","properties":{"passed":{"type":"boolean"},"failures":{"type":"array","items":{"type":"string"}}},"required":["passed"]}') if [ "$(echo $RESULT | jq '.structured_output.passed')" = "true" ]; then echo "Tests passed" else echo "Tests failed" exit 1 fi
Batch Processing
for file in src/*.py; do claude -p "Review $file for security issues" \ --output-format json \ --json-schema '{"type":"object","properties":{"issues":{"type":"array"}},"required":["issues"]}' \ | jq ".structured_output.issues" done
Fresh Context Task Execution
# Each invocation is independent (no conversation history) claude -p "Task 1: Create migration" --output-format json claude -p "Task 2: Add model" --output-format json claude -p "Task 3: Write tests" --output-format json
Task Coordination
Share TaskList across headless invocations using
CLAUDE_CODE_TASK_LIST_ID.
Environment Variable
# All invocations share the same TaskList export CLAUDE_CODE_TASK_LIST_ID="my-project" claude -p "Use TaskCreate to add: Setup database" claude -p "Use TaskCreate to add: Write migrations" claude -p "Use TaskList to show all tasks" # Shows both tasks
Pattern: Orchestrator + Workers
TASK_LIST_ID="epic-$(date +%Y%m%d)" export CLAUDE_CODE_TASK_LIST_ID="$TASK_LIST_ID" # Orchestrator creates tasks claude -p "Use TaskCreate for each: Task 1, Task 2, Task 3" # Workers execute (each sees shared TaskList) for task_id in 1 2 3; do claude -p "Use TaskUpdate to mark task #$task_id as in_progress, implement it, then mark completed" done # Check final state claude -p "Use TaskList to show status"
Task Tools
| Tool | Purpose |
|---|---|
| Create new task with subject, description |
| List all tasks with status |
| Update task status (in_progress, completed) or add blockedBy |
| Get full details of a specific task |
Dependencies
# Task 2 depends on Task 1 claude -p "Use TaskUpdate on task #2 to set blockedBy: [1]"
Tasks persist to
~/.claude/tasks/ and survive session restarts.
Notes
- Each
invocation starts fresh (no context from previous runs)-p - Use
for programmatic parsing--output-format json
field contains schema-validated datastructured_output
field contains raw text responseresult- Stream JSON requires
flag--verbose - Cost info available in JSON output:
total_cost_usd