# Claude Code Headless mode

> Run Claude Code non-interactively in scripts and CI with bare mode, structured output, tool permissions, and session continuation.

URL: https://docs.passion8.cc/en/docs/claude-code/headless
Language: en
Publisher: Passion8

Headless mode takes a prompt, performs work, and prints results without the interactive TUI. Use claude -p or --print for scripts, CI, review bots, and one-off automation.

For GitHub Actions, GitLab CI, official Code Review, and cloud comparisons, see [Platforms and integrations](https://docs.passion8.cc/en/docs/claude-code/platforms-integrations).




For a CLI script, print mode is enough. For message objects, approval callbacks, structured events, and long-running agents inside a product, use the [Agent SDK](https://docs.passion8.cc/en/docs/claude-code/sdk).




## Minimal usage

```bash
claude -p "What does the auth module do?"
```

| Command | Purpose |
| --- | --- |
| claude -p "Summarize this project" | One text result |
| claude -p "Explain this error" < build.log | Read logs from stdin |
| claude -p "Focus on queries" --continue | Continue latest local session |
| claude -p "Continue review" --resume "$session_id" | Resume a selected session |
| claude -p "Fix test failures" --allowedTools "Bash,Read,Edit" | Pre-approve tools |
| claude -p "Summarize" --output-format json | JSON result and metadata |

Print mode supports ordinary flags including model, settings, mcp-config, append-system-prompt, allowedTools, output-format, and json-schema.

## Prefer bare mode for scripts

Bare mode skips automatic discovery of hooks, skills, plugins, MCP, auto memory, and CLAUDE.md, using explicit configuration. This makes CI less dependent on a developer's local setup.

```bash
claude --bare -p "Summarize this file" --allowedTools "Read"
```

Built-in Bash, file reads, and edits remain available. Load extra context explicitly:

| Need | Flag |
| --- | --- |
| Additional system prompt | --append-system-prompt or --append-system-prompt-file |
| Settings | --settings <file-or-json> |
| MCP | --mcp-config <file-or-json> |
| Agents | --agents <json> |
| Plugin | --plugin-dir or --plugin-url |




Bare mode skips OAuth/keychain discovery. Supply Passion8's ANTHROPIC_BASE_URL=https://passion8.cc and ANTHROPIC_AUTH_TOKEN explicitly in the run environment or passed settings.




The official guide recommends bare mode for scripts/SDK use and describes a transition toward making it the print-mode default. Explicitly choosing it avoids relying on implicit discovery.

## Pipe input and output

```bash
cat build-error.txt | claude --bare -p "Explain the root cause concisely" > output.txt
```

Since v2.1.128, piped stdin has a 10 MB limit; oversized input produces a nonzero exit. Save larger material as a file and reference its path instead.

A package script can use Claude as a project checker:

```json title="package.json"
{
  "scripts": {
    "lint:claude": "git diff main | claude --bare -p \"you are a typo linter. for each typo in this diff, report filename:line on one line and the issue on the next. return nothing else.\""
  }
}
```

A diff supplied on stdin does not require Bash access to obtain that diff.

## Structured output

| Format | Meaning |
| --- | --- |
| text | Final text, default |
| json | Result, session ID, usage, cost, metadata |
| stream-json | Line-delimited events for live UI/logging |

Ordinary JSON:

```bash
claude --bare -p "Summarize this project" --output-format json
```

Constrain the result with JSON Schema:

```bash
claude --bare -p "Extract the main function names from auth.py" \
  --output-format json \
  --json-schema '{"type":"object","properties":{"functions":{"type":"array","items":{"type":"string"}}},"required":["functions"]}'
```

Natural-language output is in result; schema-constrained output is in structured_output. For example:

```bash
claude --bare -p "Summarize this project" --output-format json | jq -r '.result'
```

## Streaming events

```bash
claude --bare -p "Explain recursion" \
  --output-format stream-json \
  --verbose \
  --include-partial-messages
```

| Event | Purpose |
| --- | --- |
| system/init | Session, model, tools, MCP, plugins |
| system/api_retry | Retry count, delay, error category |
| system/plugin_install | Marketplace installation progress when synchronization is enabled |
| stream_event | Model and tool-call deltas |

Display text deltas only:

```bash
claude --bare -p "Write a short release note" --output-format stream-json --verbose --include-partial-messages | \
  jq -rj 'select(.type == "stream_event" and .event.delta.type? == "text_delta") | .event.delta.text'
```

## Tool approval and modes

AllowedTools pre-approves tools; it does not limit the available set. Combine it with permissions for restricted CI.

| Configuration | Behavior |
| --- | --- |
| --allowedTools "Read,Edit,Bash" | No interactive approval for these tools |
| --permission-mode dontAsk | Reject actions not allowed by rules |
| --permission-mode acceptEdits | Automatically accept edits/common filesystem operations |
| permissions.allow | Precisely allow commands, paths, or MCP tools |

```bash
claude --bare -p "Run the test suite and fix failures" \
  --allowedTools "Bash,Read,Edit" \
  --permission-mode acceptEdits
```

For automated commits, narrow Bash patterns:

```bash
claude --bare -p "Review staged changes and create a commit" \
  --allowedTools "Bash(git diff *),Bash(git log *),Bash(git status *),Bash(git commit *)"
```

Spaces matter: git diff followed by a wildcard has a narrower command boundary than git diff immediately followed by a wildcard.

## Custom system prompt

Append instructions to retain Claude Code's default behavior:

```bash
gh pr diff "$1" | claude --bare -p \
  --append-system-prompt "You are a security engineer. Review for vulnerabilities." \
  --output-format json
```

System-prompt replacement replaces the default instructions. Prefer append unless deliberately taking over the whole agent behavior.

## Continue sessions

```bash
claude --bare -p "Review this codebase for performance issues"
claude --bare -p "Now focus on database queries" --continue
claude --bare -p "Generate a summary of all issues found" --continue
```

For precise resumption, save the session ID:

```bash
session_id=$(claude --bare -p "Start a review" --output-format json | jq -r '.session_id')
claude --bare -p "Continue that review" --resume "$session_id"
```

Run from the same directory. Session lookup is scoped by project and Git worktree.

## Background task exit behavior

Background Bash processes such as development servers are terminated about five seconds after print mode produces the final result and stdin closes. The grace period lets nearly completed output finish.

Subagents and workflows are different because their results belong to the final output. Claude waits for them, with a documented default ceiling of ten minutes since v2.1.182. CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS changes that ceiling; zero removes it.

## Commands and skills

User-invoked skills and custom commands can appear directly in a print prompt:

```bash
claude -p "/my-skill Review this module's release risks"
```

Bare mode does not discover local skills/plugins automatically. Omit bare mode or explicitly load the required plugin.

Interactive built-in commands such as /login are unsuitable for headless runs. Configuration changes that support noninteractive syntax can use forms such as /config key=value.

## Official references

- [Run Claude Code programmatically](https://code.claude.com/en/docs/en/headless.md)
- [Agent SDK overview](https://code.claude.com/en/docs/en/agent-sdk/overview.md)
- [CLI reference](https://code.claude.com/en/docs/en/cli-reference.md)
- [Manage sessions](https://code.claude.com/en/docs/en/sessions.md)
