mcpField
C
claude-headless-mode

claude-headless-mode

github.com/majesticlabs-devAgent workflows5057 installsUpdated 7w ago
Repository

About claude-headless-mode

claude-headless-mode is a skill for running Claude non-interactively with `claude -p` in scripts, CI, and automation. It covers text, JSON, and streaming output, schema-constrained results, permission settings, and task coordination across invocations.

Key features

  1. 01Non-interactive `claude -p` execution
  2. 02Text, JSON, and streaming output
  3. 03JSON Schema-constrained responses
  4. 04Permission and tool controls
  5. 05Shared task coordination

Use cases

  1. 01Parsing structured results in CI
  2. 02Reviewing multiple files in a batch
  3. 03Coordinating scripted tasks across invocations

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/majesticlabs-dev/majestic-marketplace --skill claude-headless-mode

After installing, type/claude-headless-modein Claude Code to confirm it loaded.

Details

From the project README

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

FormatFlagUse Case
Text--output-format textHuman-readable (default)
JSON--output-format jsonSingle JSON result
Stream JSON--output-format stream-json --verboseReal-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 --verbose flag

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

OptionDescription
-p, --printHeadless mode (required)
--output-formattext, json, stream-json
--json-schemaEnforce output schema
--verboseRequired for stream-json
--modelSelect model (sonnet, opus, haiku)
--max-turnsLimit agentic turns
--permission-modebypassPermissions, plan, etc.
--allowedToolsRestrict 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
ToolPurpose
TaskCreateCreate new task with subject, description
TaskListList all tasks with status
TaskUpdateUpdate task status (in_progress, completed) or add blockedBy
TaskGetGet 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 -p invocation starts fresh (no context from previous runs)
  • Use --output-format json for programmatic parsing
  • structured_output field contains schema-validated data
  • result field contains raw text response
  • Stream JSON requires --verbose flag
  • Cost info available in JSON output: total_cost_usd

Comments

Markdown supported