Claude Code's headless mode — running the tool without a screen or an interactive session, executing a single command and finishing right away. Adding the -p flag lets you skip the back-and-forth of a terminal conversation: you pass in one prompt, Claude Code prints the answer, and it exits. This makes it possible to call Claude Code from scripts, servers, or cron jobs (scheduled tasks that run automatically at set times) without anyone sitting at the terminal. Follow this guide and in about 20 minutes you'll go from a basic headless call to choosing an output format and avoiding the permission-flag mistakes people hit most often.
🟢 Model references match the current lineup · model notice · Fable subscription
Fable 5 and 5.1 subscription (updated September 7, 2026): Claude Fable 5.1, released September 1, 2026, is the current Fable model and Fable 5 is now legacy. Plan terms are the same for both — Max and Team Premium plans include Fable at up to 50% of the weekly usage limit; Pro and Team Standard use usage credits (
What you need before you start
Check the following before trying headless mode.
- The Claude Code CLI (the command-line tool you run in a terminal) installed — on macOS, Linux, or WSL run
curl -fsSL https://claude.ai/install.sh | bash; on Windows use PowerShell or WinGet per the official install steps. - At least one prior login via
claude, or, for a server/CI environment, an API key ready in theANTHROPIC_API_KEYenvironment variable. - Basic terminal familiarity — running commands and understanding what the pipe (
|) symbol does. - A shell environment (such as bash) to run your script in, if you're automating this on a server or via cron.
Quick term glossary
- Headless mode — running without a screen or interactive session: one command in, one result out, then exit.
- Flag — an option appended to a command that changes its behavior, e.g.
-p,--output-format. - stdin/stdout — the channels a program uses to receive input (stdin) and send output (stdout).
- Pipe (
|) — a shell symbol that feeds one command's output directly into another command's input. - Permission prompt — the interactive confirmation screen Claude Code shows before editing a file or running a command.
Step-by-step
Flag names and option values below can change between versions, so before wiring any of this into a real script, run claude -p --help in your terminal to confirm the exact options available in your environment.
Step 1 — A basic headless call
claude -p "Summarize the dependencies listed in this folder's package.json"
Adding -p (or --print) tells Claude Code not to open an interactive session — it just prints the answer to your prompt and exits.
You'll know it worked when: the response text prints to the terminal and you're immediately returned to a prompt where you can type another command. If the terminal instead sits there as if waiting for input, you likely forgot -p and it launched in interactive mode. Press Ctrl+C to exit, then re-run with -p.
Step 2 — Piping a file or another command's output as input
cat error.log | claude -p "Summarize the root cause of this error log in one line"
Piping (|) sends the piped content into Claude Code alongside your prompt. You can pipe in a log file, the output of git diff, or anything else that's plain text.
You'll know it worked when: the response reflects the actual piped content — for example, quoting the specific error text from your log file.
Step 3 — Choosing an output format
If a script needs to parse the result rather than just display it to a person, a structured format is safer than plain text, whose wording can shift slightly between runs.
| --output-format value | What it does | When to use it |
|---|---|---|
| text (default) | Prints a human-readable plain-text response | Reading the result directly in the terminal |
| json | Prints the full response as a single JSON object | A script needs to parse the result for a next step |
| stream-json | Prints the process as a sequence of JSON events | Forwarding progress to another program in real time |
claude -p "List all the TODO comments in the src folder" --output-format json
You'll know it worked when: instead of a human-readable sentence, the terminal prints JSON text starting with {. Run it once and inspect the actual field structure before you rely on it in a script.
Step 4 — Understanding permission flags
Headless mode has no screen to show a confirmation prompt on. So when it hits an action that would normally require your approval — like editing a file — the script can hang or exit with an error. The flags below let you decide in advance what's allowed.
| Flag | What it does | Watch out for |
|---|---|---|
| --permission-mode | Sets the mode that governs the approval process | Confirm the exact mode names and default with claude -p --help. |
| --allowedTools | Pre-approves only the listed tools so they run without a prompt | Scope it to only what your script actually needs. |
| --disallowedTools | Explicitly blocks specific tools from being used | Useful for blocking sensitive actions, like deletion-related commands. |
| --dangerously-skip-permissions | Skips every approval step | As risky as it sounds — see the warning below. |
Caution: --dangerously-skip-permissions skips every confirmation step before editing files or running commands. Using it in an automation pipeline where untrusted input might reach the prompt (say, text pulled from an external source and fed in directly) can lead to unexpected file changes or deletions. Only use it inside an isolated environment, like a container, and only when you fully control the input.
Step 5 — Keeping session context across multiple steps
claude -p "Now add test code for the file you just created" -c
-c (--continue) or --resume lets a new prompt pick up the context from a previous headless call. That's useful when a script needs to walk through a multi-step task that a single call can't finish in one shot.
You'll know it worked when: the response continues the earlier work without you having to re-explain the file or context.
Step 6 — Running it from a server or cron job
export ANTHROPIC_API_KEY="your_api_key_here"
claude -p "Summarize today's commits as Slack-ready text" --output-format json
On a server or in a cron job where interactive login isn't possible, authenticate with the ANTHROPIC_API_KEY environment variable instead.
Caution: never commit an API key directly into code or a repository. Inject it through environment variables or a secrets manager (your server's environment configuration, or your CI system's secrets store).
Common sticking points & fixes
Issues people run into most often when first automating with headless mode:
- The terminal seems to hang — usually means
-pwas left off and it launched in interactive mode, waiting for input. PressCtrl+C, then re-run with-p. - The script hangs or exits with an error — it hit an action that needed approval but had no screen to ask on. Pre-approve the needed tools with
--allowedTools, or adjust--permission-mode. - Login-related errors in CI or cron —
ANTHROPIC_API_KEYisn't set. Confirm the environment variable is actually reaching that shell session. - Parsing errors in your script — you're parsing plain human-readable text without setting
--output-format. Switch tojsonorstream-json.
Going further
You can pipe git diff output in to draft commit messages, or loop the same prompt across multiple repositories for a batch check. This guide covered general-purpose automation from local and server scripts. Wiring this into a CI platform like GitHub Actions is covered separately — check that guide if you want to drop this into a pipeline step.
Frequently asked questions
Q. What's the difference between claude -p and plain claude?
Adding -p (--print) skips the interactive session entirely — it prints the response to your prompt and exits immediately. That fits scripts and servers, where no one is present to continue a conversation.
Q. Can headless mode still edit files?
Yes. But since there's no confirmation screen, you need to decide in advance what's allowed using permission flags like --allowedTools, or the script may hang instead of behaving as expected.
Q. When is it okay to use --dangerously-skip-permissions?
Best avoided when you can. If you truly need it, scope it as narrowly as possible and only run it inside an isolated environment, like a container, where you fully control the input.
Q. Which output format should I use if another program needs to read the result?--output-format json or stream-json is recommended. The default plain-text format is easy for a person to read, but even small wording changes in Claude's response can break a parsing script.
Related articles
- Claude Code Plan Mode: Plan First, Then Edit
- Claude Code Use Cases: Explore, Debug, Refactor, Test, and PR Workflows
- Claude Code GitHub Integration — Automate PRs and Reviews with @claude
- Claude Code Slash Commands — Built-in Commands and Custom Ones
- Claude Code Subagents — Specialized AI to Isolate Side Work