Headless Mode Explained: Running Claude Code Without a Terminal
Every Claude Code session you run at a terminal is interactive: you type a request, Claude Code responds, maybe asks to run a tool, and you approve or deny it in real time.
Search across all documentation pages
Every Claude Code session you run at a terminal is interactive: you type a request, Claude Code responds, maybe asks to run a tool, and you approve or deny it in real time.
That model breaks down the moment nobody is sitting at the terminal to approve anything - inside a script, a scheduled job, or a CI pipeline.
Headless mode is how Claude Code handles that case: it runs as a single non-interactive command that takes a prompt, does the work, and exits, without ever opening the interactive REPL.
Understanding headless mode is the prerequisite for everything else in this section that touches CI - an automated review bot, a GitHub Actions job, anything that runs Claude Code without a person watching.
gh CLI, GitHub Actions triggers, automated code review, CI secrets management.An interactive Claude Code session is a conversation. You send a message, Claude Code replies, maybe requests to run a tool, you approve it, and the back-and-forth continues until you're satisfied.
Headless mode replaces that conversation with a single instruction. You give Claude Code one prompt describing the whole task, and it runs everything needed to complete that task without pausing to ask you anything further.
The output is text (or a structured format like JSON), returned once the run finishes, rather than a live stream of messages you respond to as they arrive.
A useful comparison: an interactive session is like sitting down with a colleague and talking through a task together. Headless mode is like handing that colleague a written brief and getting a finished report back, with no conversation in between.
# Interactive: opens a live session, waits for your input.
claude
# Headless: runs one prompt to completion, then exits.
claude -p "Summarize the open pull requests in this repository." --output-format textBoth invocations use the same underlying Claude Code capability - the same models, the same tool access model. What differs is entirely the shape of the invocation: one waits for you, one does not.
Because headless mode has no human present to approve tool calls as they come up, its permission model has to be decided before the run starts, not negotiated during it.
In an interactive session, a tool call you haven't pre-approved typically pauses and asks. In a headless run, there's nobody there to answer that prompt - so a headless invocation needs its allowed tools, working directory, and any relevant scopes configured up front, otherwise the run either fails or gets stuck waiting on an approval that will never come.
This is why headless invocations are usually paired with an explicit permission or tool-allowlist configuration passed alongside the prompt, rather than relying on the interactive approval flow.
The output format matters more in headless mode too. An interactive session's output is meant for a person reading a terminal in real time. A headless run's output often feeds into something else - a script that parses it, a CI step that posts it as a PR comment, a log a pipeline archives. That's why headless invocations commonly specify an explicit output format (plain text, JSON, or a structured transcript) rather than relying on whatever the default human-facing formatting looks like.
# Headless mode invoked with structured output, so a script can parse the result
# programmatically instead of scraping human-readable text.
claude -p "Review the diff on PR #482 and summarize any risks." \
--output-format json > review-result.jsonThe commentary that matters here: --output-format json exists specifically because headless mode's consumer is usually another program, not a person - the same request phrased for an interactive session would just print readable prose.
Headless mode is the mechanism that makes every CI-based use of Claude Code possible, because a GitHub Actions job is, by definition, running with nobody watching a terminal.
A GitHub Actions job that runs Claude Code headlessly needs three things wired together: a trigger (such as on: pull_request), a secret holding an API key so the job can authenticate, and the headless invocation itself with its flags and permitted tools configured. Each of those is covered in more depth elsewhere in this section.
Headless mode also changes the failure mode developers need to think about. An interactive session that hits an ambiguous situation can ask you a clarifying question. A headless run has no one to ask - so a well-designed headless prompt needs to specify enough constraints and context up front that ambiguity is unlikely, or needs to fail gracefully (exit with a clear error) rather than guess.
| Aspect | Interactive Session | Headless Mode |
|---|---|---|
| Who approves tool calls | You, in real time | Pre-configured allowlist, decided before the run |
| Output shape | Human-readable, streamed | Text or structured (JSON), returned at completion |
| Handles ambiguity by | Asking a follow-up question | Failing clearly, or acting on the best available instruction |
| Typical trigger | You, typing a request | A script, a schedule, or a CI event |
This is also where headless mode's security posture matters most. Since a headless run's tool access is decided up front rather than approved interactively, the permissions and secrets granted to a CI job effectively become the boundary of what that headless invocation can do - there's no human safety net catching an overly broad grant in the moment, the way there would be in an interactive session.
Pass a prompt with the print flag and let it run to completion, e.g. claude -p "your instruction here" - the session runs once and exits, without opening the interactive REPL.
No - model choice is independent of interactive versus headless invocation; either mode can use any model in the current lineup.
Because there's no person present to approve a tool call in the moment the way there is in an interactive session - without a pre-configured allowlist, a headless run either fails or stalls waiting on an approval nobody will give.
Commonly plain text and structured JSON; JSON is preferred when the output feeds into another program, such as a CI step that parses the result to post a comment.
No - that's the core trade-off of the mode; a headless prompt needs to carry enough context and constraints up front, since there's no one available to answer a follow-up.
No - it works from any script or shell context, including a local terminal; GitHub Actions is simply the most common CI use case for it in this section.
It's blocked or the run fails, since there's no interactive approval flow to fall back on - this is why the permitted tool set has to be decided before the run starts.
Yes - because permissions are granted up front rather than approved case-by-case, whatever a headless invocation is allowed to do becomes the actual boundary of what it can do, with no human catching an overly broad grant mid-run.
Yes - running the same claude -p "..." command from a local terminal is a reliable way to validate a prompt and its output format before wiring it into a GitHub Actions job.
It has access to whatever tools are explicitly permitted for that invocation - potentially the same set as an interactive session, or a narrower, deliberately scoped-down set, depending on how it's configured.
Stack versions: Written against the Claude model lineup current as of ~June 2026 - Claude Fable 5, Claude Opus 4.8, Claude Sonnet 5 (the default), and Claude Haiku 4.5. Model names, pricing, and product features move quickly - verify current specifics at platform.claude.com/docs before relying on them.
Reviewed by Chris St. John·Last updated Jul 16, 2026