What Claude Code Headless Mode Is
Claude Code headless mode runs Claude as a non-interactive process that you trigger with a command, receives a task through a flag rather than a prompt, does the work, and exits. There is no interface, no approval step waiting for a human, and no session to manage. It is Claude Code as a tool in a pipeline, not Claude Code as a conversation partner.
The flag that enables it is --print. Pass it alongside your task and Claude Code runs non-interactively and prints the result to stdout. You can pipe that output to a file, another command, or a notification. Combine it with --allowedTools to define the exact set of tools Claude can use, and with --output-format for structured output when you are parsing the result downstream.
Headless vs Auto-Accept: What the Difference Actually Is
These two modes are not the same thing, and confusing them is the source of most safety mistakes when people first start running Claude Code unattended.
Headless mode vs auto-accept mode
| Mode | How it runs | Human in the loop | Best for |
|---|---|---|---|
| Headless (--print) | One-shot command, no session, exits when done | No - fully automated | Scripted pipelines, CI, cron jobs, scheduled tasks |
| Auto-accept (--dangerously-skip-permissions) | Interactive session with all approvals bypassed | Optional - you can watch but are not required | Supervised automation where you trust the task scope |
| Interactive (default) | Conversation with approval at each tool call | Yes - human approves every action | Active building, anything touching production data |
The safety difference is not subtle. Auto-accept inside an interactive session still has a human present who can interrupt. Headless mode has nobody. A mistake in headless runs to completion - there is no mid-run checkpoint. That is what makes the --allowedTools flag so important: it is the guardrail that replaces the human.
How to Set Up a Headless Run
A basic headless invocation looks like this: pass the task as a string with -p (short for --print), name the tools it is allowed to use with --allowedTools, and redirect the output wherever you need it. That is the entire setup for most automated tasks.
- Define the task precisely in a string. Headless mode has no back-and-forth to clarify - what you pass is all it gets. Vague tasks in headless produce vague output with no way to course-correct mid-run.
- Restrict tools with --allowedTools. If the task is read-only code review, give it only Read and Bash. If it writes test files, add Write. Never give it more tools than the task needs - each extra tool is a surface for something unexpected to happen.
- Set the output format. Use --output-format json if something downstream parses the result, or leave it as the default text if you are piping to a file or a notification.
- Test it interactively first. Run the same task in a regular interactive Claude Code session before you automate it. If it behaves correctly there, headless will too. If it behaves unexpectedly interactively, headless will silently do the unexpected thing at 2am.
Where Headless Mode Earns Its Keep
Headless mode is most valuable for tasks that are deterministic, low-stakes if they go slightly wrong, and expensive to do by hand on every cycle. The combination of low risk and high repetition is what makes the automation worth the setup time.
- Automated code review on a pull request. Point Claude at a diff and ask for a review pass with a specific checklist. The result is a comment or a file, not a production change.
- Test generation after a code change. Ask Claude to read a changed file and generate tests for the new logic. Review the tests before running them - you are still in the loop, just not in the generation loop.
- Documentation updates after a code change. Point headless Claude at a changed module and ask it to update the inline docs or the readme section. Diff the result before committing.
- Scheduled reports. Run a headless pass nightly to summarize the day's error logs, a code health metric, or a project status. The output goes to a channel or a file, not to a deployment.
- CLAUDE.md maintenance. Headless Claude can read a project's actual current state and update the project context file to match, so the context file does not drift from reality as the build evolves.
Where It Is the Wrong Tool
Headless mode is not a way to make Claude Code faster or more autonomous in general. There are specific situations where removing the human from the loop makes a task harder, not easier, to trust.
- Tasks that touch production systems or real user data. A headless run that can write to a production database or call an API with real side effects needs all of the guardrails that a human approval step replaced - rate limiting, hard caps, a spend ceiling. Without those, the automation is an open faucet.
- Tasks that involve judgment calls. If the right answer depends on context that was not in the task string, headless Claude will make a choice. That choice will be confident and may be wrong. Keep judgment calls in interactive mode where you can redirect.
- Tasks on unfamiliar codebases. Headless mode works well when Claude Code already understands the project from a CLAUDE.md or a prior session. On a codebase it has never seen, an unguided headless pass often touches the wrong files or applies a correct fix in the wrong place.
- First runs of any new automation. Every new headless task should start as an interactive task. Only after it behaves correctly interactively, several times, should you move it to a cron job or a pipeline trigger.
Wiring It Into a Pipeline or Cron Job
The simplest wiring is a shell script in a cron job: set the environment, run the claude command with --print and --allowedTools, and send the output to a file or a notification channel. If the task lives in a GitHub Actions workflow, the same command runs as a step - authenticate with your Claude credentials in the workflow environment, and call the command the same way you would from a terminal.
Hooks extend headless mode without changing the core command. A PostToolUse hook can validate what Claude wrote before it is saved. A Stop hook can scan the final output before the process exits. Use hooks to add the guardrails that auto-accept inside an interactive session would otherwise handle with a human. The [Claude Code hooks that earn their keep](/blog/claude-code-hooks-that-earn-their-keep) post covers hook patterns that pair well with headless runs.
Short, practical drops on skills, MCP, agents, prompts, and more. No spam, unsubscribe anytime.
Frequently asked questions
What is Claude Code headless mode?
Headless mode runs Claude Code as a non-interactive process with no interface and no approval prompts. You pass the task with the --print flag, optionally restrict tools with --allowedTools, and Claude runs to completion and exits. It is Claude Code as a command in a pipeline rather than a conversation.
How do I run Claude Code in headless mode?
Use the --print flag (or -p) with your task: claude --print "your task here" --allowedTools Read,Write,Bash. That runs non-interactively, prints the result to stdout, and exits. Add --output-format json if something downstream needs to parse the output.
What is the difference between headless mode and auto-accept?
Headless mode is a one-shot command with no session and no human present. Auto-accept (--dangerously-skip-permissions) is an interactive session where approval prompts are bypassed but a human can still watch and interrupt. Headless runs to completion with no intervention; auto-accept can still be stopped mid-run.
Is headless mode safe?
It is safe for low-stakes, deterministic tasks on systems that have their own guardrails. Always restrict tools with --allowedTools, test the task interactively before automating it, and never run headless Claude unsupervised on tasks that touch production systems, spend money, or require judgment calls. The --allowedTools flag is the guardrail that replaces the human approval step.
Can I use Claude Code headless mode in GitHub Actions?
Yes. Authenticate with your Claude credentials in the workflow environment, then run the claude --print command as a step the same way you would from a terminal. Restrict tools to Read and Bash for a review or summary task, and write the output to a file or a pull request comment. Test the same command locally before wiring it into the workflow.
Last reviewed by Duncan Rogoff on September 11, 2026


