AI & Machine Learning

I Finally Understand Why Production AI Agents Need to Run Without a Human Watching

A

Adil Sher

Author

Oct 25, 2026
5 min read
0 views
I Finally Understand Why Production AI Agents Need to Run Without a Human Watching

Last month, I was setting up a nightly script to analyze GitHub issues for a client's repository. I started with Claude Code in interactive mode, testing commands by hand, clicking through approvals, reading output from the terminal UI. It worked fine for exploration. Then I tried to automate it with a cron job, and everything broke. The script would hang waiting for confirmations that would never come, or silently fail because permission modes weren't set. I spent hours debugging before realizing I was using the wrong tool for the job. I was trying to run an interactive agent in a headless environment. That's when I discovered there's a massive difference between Claude Code for development and Claude Code for production automation, and the documentation gap between them nearly cost me a week of work.

The original article on headless mode is the first resource I've found that actually addresses this. It's not a theoretical deep-dive; it's a practical playbook for running Claude Code without a human at the keyboard. After reading it and implementing what it covers, I want to share what I learned and what still concerns me about deploying AI agents at scale.

Understanding Headless Mode vs. Interactive Mode

When you run claude -p "your task", you're not launching the familiar terminal interface. It's a completely different execution context with different rules. The agent still has the same tools and capabilities, but permissions, credential handling, and exit behavior all change. Most people discover this the hard way, like I did, by assuming the -p flag is just "quieter mode."

The critical shift is in permission handling. In interactive mode, Claude asks for approval before running sensitive operations. In headless mode with no permission settings, operations quietly fail instead of hanging. This is actually safer for automation, but it's also confusing if you don't know what you're looking for. The article calls this "Manual mode," and it's the default behavior in recent versions. You need to explicitly allow tools or set a permission policy, otherwise your script will "succeed" without actually doing the work.

Bare mode (--bare) is where things get interesting. It completely disables auto-discovery of hooks, MCP servers, and project-specific configurations. This means every run produces identical results across machines, critical for CI/CD reliability. Without it, your cron job will silently execute hooks from .claude/settings.json in any repository it touches, which is a security risk I didn't consider until I read this.

Authentication: The Three Paths Problem

This is where the article earns its value. There are three legitimate ways to authenticate headless Claude Code, and picking the wrong one will cost you either money, security problems, or both.

API keys are stateless and work in bare mode. You set ANTHROPIC_API_KEY and every run behaves identically. This is what I now use for daily cron jobs.

OAuth tokens (subscription-based) work without bare mode and draw from your Pro/Max subscription instead of per-token billing. This is cheaper if you already pay for a subscription, but it's tied to one person's account, problematic for teams.

Local login requires no setup but doesn't work reliably in cron environments, and bare mode won't use it at all.

For my setup on a VPS, I use an API key in bare mode. For a client's GitHub Actions workflow, the article correctly recommends using the official anthropics/claude-code-action@v1, which handles authentication and permissions properly.

My Take: Security and Cost Are Real Concerns

The article doesn't shy away from the hard constraints: budget caps, turn limits, and explicit tool allowlists. But I think it undersells how critical these are. I set --max-budget-usd 3.00 on my test suite runner, and that single flag has saved me more than once when a Claude Code run goes sideways and starts chaining expensive operations.

What I'm still uncertain about: the permission model feels overly safe to me. If I want Claude Code to actually fix failing tests, I need to allow Edit and Bash operations. But that means explicitly trusting it with shell access. The article provides good guidance here, narrow your allowlist to only what the task needs, but in production, this still feels like threading a needle.

The bare mode as the "recommended default" is smart architecture. It removes the assumption that Claude Code knows anything about your project layout or custom configurations. But it also means more explicit setup, which raises the bar for automation that should be simple.

A Practical Example

Here's what my actual cron job looks like:

#!/usr/bin/env bash
set -euo pipefail

source ~/.config/claude-cron.env
cd /home/adil/projects/client-app

/home/adil/.local/bin/claude --bare -p \
 "Run tests in src/tests/ and report failures" \
 --allowedTools "Read,Bash(npm test *)" \
 --permission-mode dontAsk \
 --max-turns 5 \
 --max-budget-usd 2.00 \
 --output-format json | jq '.result'

This runs every night, needs no human input, and I receive structured output I can parse. Critically: --bare means it doesn't run any hooks from the repository, and --allowedTools is specific enough that Claude Code can't do anything unexpected.

What I Want to Know

The article is solid practical guidance, but I'm curious: how do you handle state between runs? If a cron job discovers issues, how does it track what it's already reported? That feels like the next problem I'll hit.

Have you deployed Claude Code headless? I'd like to know what broke and what surprised you.

Source: This post was inspired by "Claude Code Headless Mode: Flags, Auth and Cost (2026)" by Dev.to. Read the original article

Written by Adil Sher

Full stack developer building high-traffic platforms, AI services, and custom web applications. Explore my portfolio, learn about my background, or get in touch.

Related Articles

Why I Stopped Assuming AI Assistants See What You See
AI & Machine Learning Oct 24

Why I Stopped Assuming AI Assistants See What You See

Last month, I was working with a client who wanted to understand why their news content wasn't being cited in ChatGPT responses. They'd seen OpenAI's licensing deals with major publishers and assumed their own content would be swept into the training data automatically. When I du...

Stop Building Monolithic AI Agents, Trees Work Better
AI & Machine Learning Oct 23

Stop Building Monolithic AI Agents, Trees Work Better

I spent three weeks last month debugging a system where one Claude instance was supposed to handle research, planning, and code review simultaneously. The prompt ballooned to 4000 tokens. The latency grew. The model kept hallucinating because it was trying to context-switch betwe...