Skip to content

How to Run Claude Code in Headless Mode with -p Flag

I wanted to run Claude Code as a scheduled task to automatically review my server logs every night. I set up a cron job and walked away, expecting to find a summary in the morning. Instead, I found my server with a stuck process waiting for input that would never come.

The Problem: Interactive Mode Blocks Automation

Here’s what I tried first:

cron setup (WRONG)
# This hangs forever in cron
0 3 * * * claude "Review the logs in /var/log/app.log and alert on errors"

The cron job ran at 3 AM, but Claude Code started in interactive mode, waiting for me to confirm permissions or provide input. Since cron has no terminal, the process just sat there until I manually killed it hours later.

I needed a way to run Claude Code without any interactive prompts, something that could execute a task and exit cleanly.

The Solution: The -p Flag

The -p flag enables headless mode in Claude Code. It tells Claude to execute the task and exit without any interactive UI or waiting for user input.

basic headless execution
claude -p "Review the logs in /var/log/app.log and summarize any errors"

But here’s the thing almost nobody explains properly: the -p flag alone isn’t enough for safe automation. You need to combine it with permission controls.

Understanding Permission Controls

When Claude runs in headless mode, it can’t ask you for permission to use tools. If it tries to read a file or run a command that requires permission, the task will fail.

I learned this the hard way:

headless without permissions (WRONG)
claude -p "Review all Python files and suggest improvements"
# Result: Fails when Claude tries to read files without permission

The solution is to pre-approve specific tools using --allowedTools:

headless with permission controls
claude -p "Review all Python files and suggest improvements" \
--allowedTools 'Read' 'Bash(git diff)' 'Bash(python *)'

This pattern allows Claude to read files, run git diff, and execute Python commands without asking for permission.

Building a Safe Cron Job

After several iterations, I arrived at a robust setup for automated tasks:

cron setup (CORRECT)
0 3 * * * cd /app && claude -p "Review logs for errors" \
--allowedTools 'Read' 'Bash(curl *)' \
--max-turns 10 \
--max-budget-usd 0.50

Let me break down each component:

-p: Enables headless mode - no UI, no waiting for input

--allowedTools 'Read' 'Bash(curl *)': Pre-approves specific tools. The wildcard pattern Bash(curl *) allows any curl command.

--max-turns 10: Limits the conversation to 10 turns. Without this, Claude could get stuck in a loop.

--max-budget-usd 0.50: Caps the API cost at 50 cents. Essential for automation where you can’t monitor costs in real-time.

cd /app: Ensures Claude works in the correct directory. Without this, Claude might operate in the wrong location.

Piping Input for Context

One powerful pattern is piping content directly into Claude:

pipe log file to Claude
cat /var/log/app.log | claude -p "Explain these errors and suggest fixes" \
--allowedTools 'Read' \
--max-turns 5

This sends the log file content as context to Claude, which can then analyze it without needing file system access. It’s more secure because Claude doesn’t need permission to read files.

CI/CD Integration

The same pattern works in CI/CD pipelines. Here’s a GitHub Actions example:

GitHub Actions workflow
- name: Claude Code Review
run: |
claude -p "Review changed files for security issues" \
--allowedTools 'Read' 'Bash(git diff)' \
--max-turns 15 \
--max-budget-usd 1.00

The key is balancing autonomy with safety. You want Claude to do useful work, but you need guardrails.

Continuing from Previous Sessions

Another useful feature is combining -p with -c to continue from a previous session:

continue from session
claude -c -p "Based on our previous discussion, implement the changes we discussed"

This is useful for multi-step workflows where you want Claude to build on previous context.

Common Mistakes to Avoid

I made most of these mistakes, so you don’t have to:

  1. No permission controls: Without --allowedTools, Claude will fail when it needs to use tools that require permission.

  2. No budget limits: I once ran a long analysis task overnight and woke up to a $15 bill. Now I always set --max-budget-usd.

  3. No turn limits: Without --max-turns, Claude can get stuck in loops or make excessive API calls.

  4. Wrong working directory: I spent hours debugging why Claude couldn’t find my files. The issue was a missing cd command.

  5. Expecting interactive features: Confirmation prompts, progress bars, and other UI elements don’t exist in headless mode. Design your prompts accordingly.

How It Actually Works

Under the hood, the -p flag changes Claude’s behavior in three ways:

  1. No tool confirmation prompts: Claude proceeds with pre-approved tools automatically.

  2. Immediate exit: After completing the task (or hitting a limit), Claude exits with a status code. Zero means success.

  3. Stdout output: Results go to stdout, making it easy to capture or redirect the output.

capture output to file
claude -p "Analyze code quality" --allowedTools 'Read' > analysis.txt

When to Use Headless Mode

Headless mode shines in these scenarios:

  • Scheduled maintenance: Nightly security scans, log analysis, report generation
  • CI/CD pipelines: Automated code reviews, deployment checks, test analysis
  • Scripted workflows: Chaining multiple Claude tasks together
  • Batch processing: Running the same task across multiple files or projects

It’s not ideal for exploratory work where you want to iterate with Claude interactively.

Summary

The -p flag transforms Claude Code from an interactive assistant into a headless automation tool. The key is combining it with proper safety controls:

the pattern to remember
claude -p "your task" \
--allowedTools 'Read' 'Bash(specific-command *)' \
--max-turns N \
--max-budget-usd X

Always set --allowedTools, --max-turns, and --max-budget-usd when running in automated environments. This ensures Claude can complete useful work without unintended actions or runaway costs.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments