UnattendedClaude Code Guides

Claude Code Headless Mode: Flags, Auth and Cost (2026)

By Aoba Works · Published · Sources checked · 18 min read

How this guide was made: drafted with AI assistance from the official sources linked below, then passed an automated editorial check before publishing. Our process

Claude Code headless mode means running Claude Code with no one at the keyboard. You call claude -p "your task", it does the work, prints a result and exits, the same way any shell command does. The official docs put it this way: "Add the -p (or --print) flag to any claude command to run it non-interactively" (Claude Code docs: Run Claude Code programmatically). The -p flag alone isn't enough for a reliable cron or CI job, though. You also need credentials that never ask for a browser login, permission settings that never wait for a human, a hard stop on turns and spend, and output your script can parse. This guide covers each of those.

Which option is right for you?

Use local claude -p with an API key for cron jobs on your own machine or server. Use the GitHub Action for anything triggered by repository events. Use a subscription token only for light personal automation.

Which option is right for you?
Your situationWhat to pick firstFirst page to open
Beginner, trying one scheduled task on a laptopclaude -p with your existing Pro/Max login, no --bareRun Claude Code programmatically
Daily work: nightly cron on a VPS or home serverclaude --bare -p + ANTHROPIC_API_KEY + --max-budget-usdCLI reference
PR reviews, issue triage, scheduled repo reportsanthropics/claude-code-action@v1 in GitHub ActionsClaude Code GitHub Actions
Tight budget, already paying for Pro or Maxclaude setup-token → CLAUDE_CODE_OAUTH_TOKEN (not with --bare)Authentication
Shared repos or a team secretConsole API key stored as an org-level secretAuthentication

The reasoning in one line each:

What is Claude Code headless mode?

Claude Code headless mode is the non-interactive way to run Claude Code. There's no terminal UI and no prompts. Each run takes one task, prints the result and exits. It is the same agent with the same tools as the interactive app, but it runs inside a different execution context, and that context has its own rules.

The docs describe it as the Agent SDK "available as a CLI for scripts and CI/CD" (headless docs). Several behaviors change when you add -p:

That last point is the one people most often miss. If your cron job runs claude -p inside a repository you cloned from someone else, that repository's hooks will run. Bare mode prevents this.

Bare mode is the "real" headless mode

--bare skips auto-discovery of hooks, skills, plugins, MCP servers, auto memory and CLAUDE.md, so every machine produces the same result. The docs say plainly that "--bare is the recommended mode for scripted and SDK calls, and will become the default for -p in a future release" (headless docs). If you need any of that context, pass it in explicitly: --append-system-prompt-file for instructions, --settings for settings, --mcp-config for MCP servers, --agents for subagents.

The limitation: bare mode never reads OAuth credentials or the keychain. That rules out your subscription login (more on this in the auth section).

How do you run Claude Code in headless mode?

Run claude -p with a non-interactive credential, explicit tool permissions, turn and budget caps, and JSON output. Here is the sequence for a cron job on Linux or macOS.

  1. Install and check the version. Run claude --version. Several flags below need recent builds: --permission-prompts needs v2.1.259 or later, and the Manual-mode default for -p needs v2.1.302 (CLI reference). Update with claude update.
  2. Create an API key. In the Claude Console, create a key. Save it in a file only your user can read, for example ~/.config/claude-cron.env with chmod 600.
  3. Confirm auth works. Run claude auth status. It prints JSON, and authMethod should read api_key (or oauth_token if you use a subscription token). It "Exits with code 0 if logged in, 1 if not" (CLI reference).
  4. Do a dry run by hand. From the project directory:

``bash claude --bare -p "List the TODO comments in src/ and group them by file" \ --allowedTools "Read,Grep,Glob" \ --max-turns 10 \ --output-format json | jq -r '.result' ``

  1. Wrap it in a script (example):

``bash #!/usr/bin/env bash set -euo pipefail source ~/.config/claude-cron.env # exports ANTHROPIC_API_KEY cd /home/you/projects/my-app mkdir -p logs /home/you/.local/bin/claude --bare -p "Run the test suite and fix failing tests in src/ only" \ --allowedTools "Read,Edit,Bash(npm test *)" \ --permission-mode dontAsk \ --max-turns 20 \ --max-budget-usd 3.00 \ --output-format json > "logs/run-$(date +%F).json" ``

  1. Schedule it. Run crontab -e and add a line such as 0 3 * /home/you/bin/nightly-claude.sh >> /home/you/logs/cron.log 2>&1. For scheduling details and overnight patterns, see Claude Code Cron Job Setup: Run Automations Overnight.

Common mistakes and fixes

Which Claude Code CLI flags matter in headless mode?

Besides -p, six flags matter most: --bare, --output-format, --allowedTools, --permission-mode, --max-turns and --max-budget-usd. They decide whether a headless run is safe and parseable, and everything else is optional tuning. All of the following come from the CLI reference as of October 2026.

Which Claude Code CLI flags matter in headless mode?
FlagWhat it does in a headless runDefault / note
-p, --printNon-interactive run, then exitRequired
--bareSkips hooks, skills, plugins, MCP, CLAUDE.md discoveryOff today; planned default for -p
--output-formattext, json, or stream-jsontext
--json-schemaValidated structured output in structured_outputPrint mode only
--allowedToolsTools that run without approval, e.g. "Bash(git diff *)"Uses permission rule syntax
--disallowedToolsDeny rules; a bare name removes the tool entirely"mcp__*" removes all MCP tools
--permission-modedefault/manual, acceptEdits, plan, auto, dontAsk, bypassPermissionsManual for -p (v2.1.302+)
--permission-prompts noneDenies anything that would prompt; tells Claude not to retryv2.1.259+
--max-turnsCaps agentic turns; "Exits with an error when the limit is reached""No limit by default"
--max-budget-usdStops once estimated spend hits the capPrint mode only; spend can pass the cap
--model / --fallback-modelPick a model; fall back when overloadede.g. --model sonnet
--no-session-persistenceDon't save the session to diskPrint mode only
--continue / --resume <id>Chain several -p calls into one conversationUse session_id from JSON

A few of these have traps:

What is headless/CI mode in Claude Code?

Headless/CI mode is claude -p running inside a CI pipeline, usually via the official GitHub Action or a GitLab CI job. The pipeline supplies the credentials, the checkout and the trigger. Claude Code has no separate "CI mode" switch. In CI the runner is disposable and shared, so reproducibility and secret handling matter more than they do on your own machine.

The Claude Code GitHub Action (anthropics/claude-code-action@v1) has two modes:

The fastest setup is to run /install-github-app inside Claude Code. It installs the GitHub App, saves your secret as ANTHROPIC_API_KEY or CLAUDE_CODE_OAUTH_TOKEN, and opens a pull request with the workflow. You need admin access to the repository, and the command works only for github.com repositories (GitHub Actions docs).

Example scheduled workflow, adapted from the official daily-report example:

name: Nightly triage
on:
  schedule:
    - cron: "0 9 * * *"
jobs:
  triage:
    runs-on: ubuntu-latest
    timeout-minutes: 20
    permissions:
      contents: read
      issues: read
      id-token: write
    steps:
      - uses: anthropics/claude-code-action@v1
        with:
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
          prompt: "Summarize yesterday's commits and open issues"
          claude_args: |
            --model sonnet
            --max-turns 8
            --allowedTools "mcp__github__list_commits,mcp__github__list_issues"

CI-specific pitfalls from the official docs:

How do you authenticate Claude Code for cron and CI runs?

Use an environment variable, either ANTHROPIC_API_KEY (Console billing) or CLAUDE_CODE_OAUTH_TOKEN (subscription). Never rely on an interactive browser login, because a cron job has no browser to finish it.

When more than one credential is present, Claude Code checks them in this order (Authentication docs):

  1. Cloud provider variables (CLAUDE_CODE_USE_BEDROCK, _VERTEX, _FOUNDRY)
  2. ANTHROPIC_AUTH_TOKEN, used for LLM gateways
  3. ANTHROPIC_API_KEY
  4. apiKeyHelper script output, for rotating keys from a vault
  5. CLAUDE_CODE_OAUTH_TOKEN
  6. Anthropic profile / federation credentials
  7. Subscription login from /login
  1. Create a key in the Claude Console.
  2. Export it in your job's environment, or store it as a CI secret.
  3. Works with --bare.

When you first authenticate with Console, a workspace called "Claude Code" is created automatically. You can set spend limits on it (Costs docs).

Option B: subscription token

  1. On a machine with a browser, run claude setup-token and approve access.
  2. Copy the printed token. The command "does not save the token anywhere".
  3. Set export CLAUDE_CODE_OAUTH_TOKEN=your-token in the job's environment.

The token lasts one year and is meant for "CI pipelines and scripts where browser login isn't available". It requires a Pro, Max, Team or Enterprise plan (Authentication docs).

Pitfalls with fixes:

How much does Claude Code headless mode cost?

Claude Code headless mode costs exactly what interactive use costs for the same tokens. You pay per token on an API key, or the usage comes out of your plan's limits on a subscription. There is no headless surcharge. What makes it expensive is repetition: a job that runs nightly, retries on failure, or has no turn cap can multiply spend without anyone noticing.

Official numbers (as of October 2026; check the official page):

How much does Claude Code headless mode cost?
ItemPriceSource
Opus 5.5$4 input / $20 output per million tokensClaude API pricing
Sonnet 5.5$2 input / $10 output per million tokensClaude API pricing
Haiku 5.5$0.10–$0.50 input / $0.50–$2.50 output per million tokens, depending on prompt lengthClaude API pricing
Pro plan$20/month ($17/month billed annually)Claude pricing
Max plansfrom $100/monthClaude pricing
Enterprise average~$13 per developer per active day; $150–250 per monthCosts docs

Model choice matters a lot here. Pro, Max, Team, Enterprise and the Anthropic API all default to Opus 5.5 (Model configuration), so a headless job without --model runs on the most expensive of the three. The Costs docs note that Sonnet "handles most coding tasks well and costs less than Opus".

Example estimate (illustrative, not a measurement). Suppose a nightly job reads 200,000 input tokens and writes 20,000 output tokens on Sonnet 5.5, ignoring caching. That's 0.2 × $2 + 0.02 × $10 = $0.60 per run, or about $18 for 30 nights. The same job on Opus 5.5 would be about $1.20 per run. Prompt caching usually lowers the input side, so treat this as an upper-bound sketch.

Cost controls that actually apply to headless runs:

For more ways to cut token use, see Claude Code: How to See Token Usage (and Reduce It).

Does Claude Code headless mode work with a Pro or Max subscription?

Yes. Claude Code headless mode works on Pro and Max through claude setup-token. Every automated run then draws from the same limits as your chat and interactive coding. Anthropic's help center says the limits "are shared across Claude and Claude Code", and both plans have "a five-hour session limit and a weekly limit" (Claude Help Center).

Does Claude Code headless mode work with a Pro or Max subscription?
Subscription token (CLAUDE_CODE_OAUTH_TOKEN)API key (ANTHROPIC_API_KEY)
BillingIncluded plan usagePer token, pay as you go
Works with --bareNoYes
Hits limits5-hour session and weekly windows, shared with your chatsOrganization rate limits
Good forA few light personal jobsNightly jobs, CI, anything shared
Shared team secretNot recommended (tied to one person)Recommended
Spend capPlan limits; optional usage-credit spend limit--max-budget-usd plus Console workspace limits

How to choose:

When a scheduled job hits a limit, retry logic matters more than the plan. See Claude Code Rate Limit Reached: Retry Setup for Cron Jobs. In stream-json output, retries show up as system/api_retry events, with an error field such as rate_limit or billing_error (headless docs).

How do hooks work in Claude Code headless runs?

Claude Code hooks run in headless -p runs the same way they do in interactive sessions, unless you pass --bare, which skips hook discovery. That makes hooks the main way to add guardrails and logging to a job nobody watches.

The events most useful for unattended runs, per the hooks reference:

Steps to attach a hook to a headless job:

  1. Write the hook command into a settings file, for example ci-settings.json, under "hooks": { "PreToolUse": [...] }.
  2. Without bare mode, put it in the project's .claude/settings.json. With --bare, pass it explicitly: --settings ./ci-settings.json (the documented way to load settings in bare mode).
  3. Add --output-format stream-json --verbose --include-hook-events to a test run, and confirm that hook_started / hook_response events appear.
  4. Keep hooks fast. The docs' cost example uses a PreToolUse hook to rewrite test commands so only failures reach Claude, cutting context "from tens of thousands of tokens to hundreds" (Costs docs).

Ready-made scripts are in Claude Code Hooks Examples: 7 Copy-Paste Scripts, and event order is covered in Claude Code Hooks Lifecycle: Every Event, Explained.

How do you track Claude Code usage from cron jobs?

Track Claude Code usage from cron jobs by saving the --output-format json result of every run. Each one includes total_cost_usd, a per-model cost breakdown and the session_id. Unattended runs have no screen, so if you don't log this, nobody sees it.

Example log line extraction (illustrative):

jq -c '{date: now|todate, session: .session_id, cost: .total_cost_usd, ok: (.is_error|not)}' \
  logs/run-$(date +%F).json >> logs/costs.jsonl

The session_id, result and total_cost_usd fields are documented. For any other field name (such as is_error above), check one real output file before you depend on it.

What to watch:

To get alerts when something breaks rather than just a log, see AI Agent Monitoring in Claude Code: Catch Silent Failures.

Next steps

Do today:

  1. Run claude --version and claude auth status. Confirm you're on v2.1.302 or later and see which authMethod your scripts would actually use.
  2. Take one task you do by hand every week and run it once as claude --bare -p "..." --allowedTools "Read" --max-turns 10 --max-budget-usd 1 --output-format json. Read the JSON before you schedule anything.
  3. Add --model sonnet and a --max-budget-usd cap to every existing scheduled call that lacks them.

If you'd rather not build this yourself: Anthropic's Code Review gives you automatic PR reviews "without writing a workflow", and the Claude Code GitHub Action covers scheduled repo tasks with a one-command setup (/install-github-app). Both run on your API key or subscription. The Action also uses GitHub Actions minutes. They suit people whose recurring work lives in GitHub. They don't fit jobs that touch local files, private servers or non-GitHub data, where a local cron script is still simpler. If what holds you back is subscription limits rather than setup, a Max plan (from $100/month as of October 2026; check claude.com/pricing) raises the ceiling. It is only worth it if you also use Claude Code interactively most days. For automation alone, pay-as-you-go API billing is usually easier to cap.

Related guides on this site:

FAQ

Can Claude Code run headless?

Yes. Claude Code runs headless with claude -p "task", which runs the full agent without the terminal UI and exits when done. It works on macOS, Linux and Windows, in cron, systemd timers, Docker and CI runners. For repeatable results, add --bare and authenticate with ANTHROPIC_API_KEY.

What is the code for headless mode?

The minimal command is claude -p "your prompt". A safer unattended version is claude --bare -p "your prompt" --allowedTools "Read,Edit" --max-turns 15 --max-budget-usd 2 --output-format json. Pipe data in with cat file | claude -p "explain".

What is headless mode, in general?

Outside Claude Code, "headless" means software running without its graphical or interactive interface, like headless Chrome for browser automation or a headless server with no monitor. Claude Code uses the word the same way: the agent works, but there's no interface for a person to watch or answer.

What does Claude Code headless plan mode mean?

It means running claude -p "..." --permission-mode plan. In plan mode, "Claude reads files, runs shell commands to explore, and writes a plan, but does not edit your source" (Permission modes). Headless, that gives you a read-only report, such as a refactor proposal written to a log, with no risk of file changes. Shell commands outside the read-only set still need approval, so in -p they're denied unless allowed.

Does Claude Code headless mode use a different model than interactive mode?

No. Headless runs use the same default as interactive sessions, which is Opus 5.5 for Pro, Max, Team, Enterprise and Anthropic API accounts (Model configuration). Override it per run with --model sonnet or --model haiku, and add --fallback-model sonnet,haiku for when the primary model is overloaded.

Sources

Spotted something out of date or wrong? Tell us at shigoto.ai.note@gmail.com. Guides are re-checked against official sources on a rolling schedule.