Headless Mode
Module 11.1: Headless Mode
Section titled “Module 11.1: Headless Mode”Estimated time: ~30 minutes
Prerequisite: Phase 10 (Team Collaboration)
Outcome: After this module, you will understand headless mode fundamentals, know how to script Claude Code, and be ready for advanced automation.
1. WHY — Why This Matters
Section titled “1. WHY — Why This Matters”You want to run Claude Code as part of a script. Maybe generate tests for all files in a directory. Maybe do code review on every PR automatically. Maybe batch process documentation. But Claude Code is interactive — it waits for your input, shows spinners, expects approval.
Headless mode solves this: Claude executes, outputs result, returns control to your script. No interaction needed. This unlocks automation: cron jobs, CI/CD pipelines, batch processing, and more.
2. CONCEPT — Core Ideas
Section titled “2. CONCEPT — Core Ideas”Interactive vs Headless
Section titled “Interactive vs Headless”| Aspect | Interactive | Headless |
|---|---|---|
| Invocation | claude | claude -p "prompt" |
| Input | Conversation | Single prompt |
| Output | Formatted, spinners | Raw stdout |
| Approval | Required | Skipped or auto |
| Use case | Development | Automation |
The -p Flag
Section titled “The -p Flag”The -p (print) flag is the key to headless mode:
claude -p "Your prompt here"- Executes the prompt
- Outputs result to stdout
- Returns to shell when complete
- Exit code indicates success/failure
Capturing Output
Section titled “Capturing Output”# To variableresult=$(claude -p "Explain this function")
# To fileclaude -p "Generate README" > README.md
# Pipe to another commandclaude -p "List issues in code" | grep "ERROR"Input Methods
Section titled “Input Methods”# Direct promptclaude -p "Explain recursion"
# With file contextclaude -p "Review this code: $(cat file.js)"
# Pipe from stdin ⚠️ Verify supportcat file.js | claude -p "Review this code"Exit Codes
Section titled “Exit Codes”0: Success- Non-zero: Error (check stderr)
- Use in scripts:
if claude -p "..."; then ... fi
3. DEMO — Step by Step
Section titled “3. DEMO — Step by Step”Scenario: Automate documentation generation using headless Claude Code.
Step 1: Basic Headless Execution
Section titled “Step 1: Basic Headless Execution”claude -p "What is 2 + 2?"Output:
4Check exit code:
echo $?Output:
0Step 2: Capture to Variable
Section titled “Step 2: Capture to Variable”explanation=$(claude -p "Explain async/await in one paragraph")echo "$explanation"Output:
Async/await is a JavaScript feature that makes asynchronous codeeasier to write and read by allowing you to write asynchronousoperations in a synchronous-looking style...Step 3: Generate File from Output
Section titled “Step 3: Generate File from Output”claude -p "Generate a README.md for a TypeScript utility library" > README.mdhead -5 README.mdOutput:
# TypeScript Utility Library
A collection of useful TypeScript utilities for common tasks.
## InstallationStep 4: Process Multiple Files
Section titled “Step 4: Process Multiple Files”#!/bin/bashfor file in src/*.ts; do echo "Documenting $file..." doc=$(claude -p "Generate JSDoc comments for: $(cat "$file")") echo "$doc" > "docs/$(basename "$file" .ts).md"done
echo "Documentation complete!"Run the script:
chmod +x generate-docs.sh./generate-docs.shOutput:
Documenting src/utils.ts...Documenting src/helpers.ts...Documenting src/api.ts...Documentation complete!Step 5: Conditional Logic Based on Output
Section titled “Step 5: Conditional Logic Based on Output”#!/bin/bashresult=$(claude -p "Review this code for security issues.Output 'SAFE' if no issues, or 'UNSAFE: [reason]' if issues found.Code: $(cat "$1")")
if [[ "$result" == SAFE* ]]; then echo "✅ $1 passed security check" exit 0else echo "❌ $1 failed: $result" exit 1fiStep 6: Error Handling
Section titled “Step 6: Error Handling”if ! output=$(claude -p "Generate tests for $(cat file.js)" 2>&1); then echo "Error: $output" exit 1fiecho "$output" > tests.js4. PRACTICE — Try It Yourself
Section titled “4. PRACTICE — Try It Yourself”Exercise 1: First Headless Command
Section titled “Exercise 1: First Headless Command”Goal: Execute your first headless Claude command.
Instructions:
- Run:
claude -p "Say hello" - Capture to variable:
greeting=$(claude -p "Say hello") - Echo the variable:
echo "$greeting" - Check exit code:
echo $?
💡 Hint
The output should be a simple greeting. Exit code 0 means success.
Exercise 2: File Generation
Section titled “Exercise 2: File Generation”Goal: Generate code to a file.
Instructions:
- Generate a function:
claude -p "Write a JavaScript function to capitalize strings" > capitalize.js - Verify:
cat capitalize.js - Run:
node -e "$(cat capitalize.js); console.log(capitalize('hello'))"
✅ Solution
claude -p "Write a JavaScript function called capitalize that takes a string and returns it with the first letter capitalized" > capitalize.jscat capitalize.jsnode -e "$(cat capitalize.js); console.log(capitalize('hello'))"# Output: HelloExercise 3: Batch Processing Script
Section titled “Exercise 3: Batch Processing Script”Goal: Process multiple files with a script.
Instructions:
- Create 3 small code files in a test directory
- Write a bash script that loops through files
- For each file, generate a one-line description
- Output all descriptions to summary.txt
✅ Solution
# Create test filesmkdir -p test-batchecho "function add(a, b) { return a + b; }" > test-batch/math.jsecho "const API_URL = 'https://api.example.com';" > test-batch/config.jsecho "class User { constructor(name) { this.name = name; } }" > test-batch/user.js
# Batch processing script (save as batch-describe.sh)#!/bin/bashfor file in test-batch/*.js; do name=$(basename "$file") desc=$(claude -p "Describe in one line: $(cat "$file")") echo "$name: $desc" >> test-batch/summary.txtdone
# Run and verifychmod +x batch-describe.sh./batch-describe.shcat test-batch/summary.txt5. CHEAT SHEET
Section titled “5. CHEAT SHEET”Basic Headless
Section titled “Basic Headless”claude -p "prompt" # Execute and outputresult=$(claude -p "prompt") # Capture to variableclaude -p "prompt" > file.txt # Output to fileclaude -p "prompt" | grep "pattern" # Pipe to commandWith File Input
Section titled “With File Input”claude -p "Review: $(cat file.js)" # Inline file contentIn Scripts
Section titled “In Scripts”# Error handlingif ! result=$(claude -p "..."); then echo "Failed" exit 1fi
# Loop processingfor f in *.js; do claude -p "Document: $(cat "$f")" > "${f%.js}.md"doneExit Codes
Section titled “Exit Codes”| Code | Meaning |
|---|---|
| 0 | Success |
| Non-zero | Error |
Key Flags ⚠️ Verify availability
Section titled “Key Flags ⚠️ Verify availability”| Flag | Purpose |
|---|---|
-p "prompt" | Headless execution |
--help | Show available options |
6. PITFALLS — Common Mistakes
Section titled “6. PITFALLS — Common Mistakes”| ❌ Mistake | ✅ Correct Approach |
|---|---|
| Expecting interactive features | Headless is one-shot. No conversation. |
| Long prompts directly in command | Use variables or files for long prompts |
| Ignoring exit codes | Always check exit codes in scripts |
| Not escaping special characters | Quote variables: "$(cat file)" |
| Assuming same behavior as interactive | Test headless separately. Output format differs. |
| No error handling | Capture stderr, check exit codes |
| Overloading with huge files | Context limits apply. Chunk large files. |
7. REAL CASE — Production Story
Section titled “7. REAL CASE — Production Story”Scenario: Vietnamese startup needed to generate API documentation for 50+ endpoints. Manual process took 2 days per documentation update.
Solution with headless mode:
#!/bin/bashfor endpoint in src/routes/*.ts; do name=$(basename "$endpoint" .ts) echo "Documenting $name..."
claude -p "Generate OpenAPI documentation for this endpoint:$(cat "$endpoint")
Output in YAML format." > "docs/api/$name.yaml"done
# Combine all YAML filesclaude -p "Combine these OpenAPI specs into one:$(cat docs/api/*.yaml)" > docs/openapi.yaml
echo "API documentation generated!"Results:
- 2 days manual → 15 minutes automated
- Runs nightly via cron job
- Documentation always up-to-date
- Human review only when needed
Quote: “Headless mode turned Claude from a chat buddy into a documentation factory.”
Next: Module 11.2: SDK Integration →