The Complete Guide to Scheduling Claude Code Tasks
From basic cron to production scheduling: everything you need to know about running Claude Code on a schedule.

Scheduling Claude Code tasks isn't a simple binary—it's not just "now" or "later." There's a spectrum of approaches, each with different tradeoffs in complexity, reliability, and observability. The decision of which one you use shapes how your automation works, whether you'll notice when it fails, and how much friction you'll hit when scaling from a single job to five or ten.
We're going to walk through the entire landscape: from simple shells scripts with cron, through systemd timers, to proper scheduling infrastructure. By the end, you'll know not just what's available, but which approach actually makes sense for what you're trying to build.
The Scheduling Problem Isn't New
Automation has been a solved problem for decades. Unix had cron. systemd added timers. Cloud platforms offer scheduled tasks. But Claude Code is different from the ordinary command-line utility because it's conversational—it expects some degree of interactivity, error handling, and course correction. A script that exits with a nonzero code tells you something failed. Claude Code that gets stuck waiting for input and never exits tells you nothing at all.
The scheduling landscape for Claude Code is therefore not just about "when to run"—it's about "what to do if it hangs," "how to see what happened," and "what to do if something went wrong."
Option 1: Shell Script + Cron (Minimal, Not Recommended for Production)
The simplest starting point is a shell script that invokes Claude Code, wrapped in a cron job.
0 2 * * * /usr/local/bin/claude-code < /path/to/prompt.txt > /tmp/claude-output.log 2>&1This works for trivial use cases. But it has obvious gaps:
- If Claude Code hangs, the process runs indefinitely, and your cron daemon eventually kills it (timing out is silent—you don't know it happened)
- Checking whether a job succeeded means parsing log files manually
- Retrying a failed job requires a separate manual step
- Multiple concurrent runs are possible if jobs overlap
- Log files grow unbounded
For a one-off "run this task at 2 AM" task on a personal project, it's fine. For anything you care about, it's insufficient.
Option 2: Systemd Timer (Better, Linux-Native)
If you're on Linux, systemd timers are a step up from cron. They're more explicit about dependencies, can log to systemd journal, and support more complex scheduling patterns.
Create a service file:
[Unit]
Description=Claude Code Task Runner
After=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/claude-code < /path/to/prompt.txt
TimeoutStartSec=3600
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.targetAnd a timer file:
[Unit]
Description=Claude Code Task Runner Timer
[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
[Install]
WantedBy=timers.targetThis gains you service isolation, structured logging (all output goes to systemd journal), and automatic restart on failure. But it still doesn't solve the hanging problem—a timeout helps, but you don't get visibility into what happened or recovery options.
Option 3: OpenHelm (macOS Production Scheduling)
If you're on macOS and care about reliability, OpenHelm is built specifically for the Claude Code scheduling problem. It adds the bits that operating system schedulers don't have: silence detection, structured run history, and built-in recovery.
When you schedule a task in OpenHelm, it monitors the output stream. If nothing appears for 10 minutes, the run stops automatically. No hanging jobs burning API costs overnight. The result—success, failure, or timeout—is logged to a structured dashboard you can check in the morning.
When a run fails, OpenHelm can automatically queue a corrective retry, passing the failure context back to Claude Code so it can try a different approach.
Option 4: Cloud-Native Scheduling (AWS, GCP, Azure)
If your infrastructure lives in the cloud, you can schedule Claude Code via platform-native tools: AWS EventBridge + Lambda, Google Cloud Scheduler + Cloud Functions, or Azure Logic Apps.
The advantage: infrastructure as code, integrated logging, built-in retry and dead-letter queue support, and transparent cost tracking. The disadvantage: you're delegating a portion of control to a cloud provider's API.
For teams already in the cloud, it's the natural fit. For solo developers or projects that prefer to stay self-hosted, it adds complexity.
The Decision Framework
If you're prototyping or learning: Start with cron + shell script. Get it working. Then measure what breaks.
If you're on macOS and care about reliability: Use OpenHelm. Silence detection and run history save time and money.
If you're on Linux and prefer to stay on-machine: systemd timers + a wrapper script that handles timeouts and logging.
If you're part of a team with cloud infrastructure: Use your platform's scheduler (EventBridge, Cloud Scheduler, Logic Apps) and wire it to an API endpoint that triggers Claude Code.
A Production Example: OpenHelm + Nightly Refactoring
Here's how a real team uses scheduled Claude Code:
Every night at 3 AM, a task runs:
Goal: Audit the codebase for type errors, deprecated API calls, and common linting violations in src/api/. Run ESLint, check the output, and submit a pull request with fixes.OpenHelm's dashboard shows:
- Run started 3:02 AM, completed 3:41 AM
- 47 violations found
- PR #8392 opened with fixes
- All tests passing
- Next scheduled run: tomorrow at 3 AM
If the run had hanged (Claude Code stuck waiting for input, network timeout, something else), it would have stopped at the 10-minute mark, logged "Timeout: silence detected", and no PR would have opened. The team checks the dashboard, sees the timeout, and investigates before the next run.
Common Pitfalls
Not setting a timeout. An unbound process that gets stuck costs money and consumes resources. Whether you use OS-level timeouts, silence detection, or cloud platform limits, set one.
Not logging output. Debugging a failed automation is impossible without visibility into what happened. Store structured logs (JSON if possible) and make them searchable.
Not handling overlapping runs. If a task takes longer than the interval between runs, you'll end up with multiple concurrent runs competing for locks or resources. Use a lock file or mutual exclusion mechanism to prevent this.
Ignoring cost implications. A Claude Code task that's supposed to run for 5 minutes but hangs for an hour is expensive. Silence detection exists to prevent exactly this scenario.
FAQ
Can I run Claude Code on a schedule without a scheduler?
Yes. You can invoke Claude Code manually whenever you want. But if you want something to run reliably at a specific time without your intervention, you need a scheduler. Otherwise you're relying on a cron job that you have to manually set up and monitor.
What's the maximum runtime for a Claude Code task?
There's no hard limit in Claude Code itself, but there's a practical one: the longer a task runs, the more it costs. A three-hour refactoring session might cost £50–100 in API tokens. Silence detection helps, but even reasonable jobs can be pricey if they're inefficiently scoped.
Should I run Claude Code on a schedule in production?
Yes, if the task is well-scoped and you've tested it manually first. A task that works reliably in interactive mode will usually work scheduled. The difference is whether you're watching to fix mistakes.
More from the blog
OpenHelm vs runCLAUDErun: Which Claude Code Scheduler Is Right for You?
A direct comparison of the two most popular Claude Code schedulers — how each works, what each costs, and which fits your workflow.
Claude Code vs Cursor Pro: Real Developer Cost Comparison
An honest look at what developers actually spend on Claude Code, Cursor Pro, and GitHub Copilot — and how to get the most from each.