How to Schedule Claude Code Tasks: A Developer's Guide
Master scheduling Claude Code with practical examples for cron, GitHub Actions, and OpenHelm. Run unattended tasks overnight.

Scheduling Claude Code to run unattended is the difference between an AI tool that works in your shell and an AI tool that works for you overnight. But scheduling introduces a problem: Claude Code is interactive by default. It asks questions, expects responses, waits for you. When you schedule it, nobody's there to answer.
This guide walks through the practical mechanics of scheduling Claude Code tasks and how to make them run reliably when nobody's watching.
Why Scheduling Matters
An interactive Claude Code session is fine for a 30-minute refactoring task at 2pm when you can babysit it. But for larger tasks—dependency upgrades, code migrations, test expansions, documentation updates—interactive sessions become impractical.
A scheduled, unattended task lets you queue work that takes several hours and wake up to a finished PR. That's the asymptotic win: specify a goal, let Claude Code work through the night, check the results in the morning.
The catch: unattended execution requires different constraints and setup than interactive sessions.
Method 1: Unix Cron for Simple Recurring Tasks
The simplest approach is Unix cron. It's available on any system with a shell, it's rock-solid, and it requires almost no setup.
Setting Up a Cron Job
Here's a basic cron entry that runs a Claude Code task every morning at 6am:
0 6 * * * /usr/local/bin/claude -p "Review the test failures from yesterday and attempt to fix them. Limit yourself to 10 turns." --project /Users/you/myapp 2>&1 | tee -a /var/log/claude-code.logBreaking this down:
0 6 * * *— run at 6:00 AM every day- `/usr/local/bin/claude -p "..."—the Claude Code invocation with a prompt
--project /Users/you/myapp— the directory to work in2>&1 | tee -a /var/log/claude-code.log— capture output to a log file
The prompt is crucial. It needs to be specific, scoped, and have a defined stopping condition. "Review the test failures and fix them" is fine because there's a natural end state—either the tests pass or you've tried a reasonable number of times.
Making Cron Prompts Reliable
Three rules for prompts that work unattended:
First: explicit scope. Don't say "upgrade dependencies." Say "upgrade the three npm packages in the top-level package.json that have security warnings. Run tests after each upgrade to verify the fix."
Second: stopping conditions. Include "Stop after 5 turns if you haven't made progress" or "Exit when all tests pass." Claude Code is designed to be iterative, but when it's running unattended, unbounded iteration becomes expensive and risky.
Third: error handling. Tell it what to do if something goes wrong. "If the build fails, check the error message, attempt one fix, and stop. Do not retry indefinitely."
The Cron Log Problem
Cron jobs run in the background, so you won't see output unless you explicitly capture it. The tee command above writes to a log file. Check it:
tail -100 /var/log/claude-code.logA downside of cron: if the job fails or hangs, you won't know until you check the log manually. There's no notification, no dashboard, no run history. It's functional but not transparent.
Method 2: GitHub Actions for CI-Integrated Tasks
If your project is on GitHub, GitHub Actions is a natural fit for scheduled Claude Code tasks that integrate with your CI/CD pipeline.
A Basic GitHub Actions Workflow
Create a file in .github/workflows/claude-code-overnight.yml:
name: Claude Code Overnight Task
on:
schedule:
- cron: '0 2 * * *' # Run at 2am UTC daily
jobs:
claude-code:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Install Claude CLI
run: npm install -g @anthropic-ai/claude-code
- name: Run Claude Code task
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
claude -p "Run the test suite. Fix any failing tests. Commit changes if successful." \
--project . \
--max-turns 15
- name: Create PR if changes were made
if: github.event_name == 'schedule'
uses: peter-evans/create-pull-request@v5
with:
commit-message: '[Claude Code] Nightly test fixes'
title: '[Claude Code] Overnight fixes from scheduled run'
branch: claude-code-overnightThis workflow:
- Runs on a schedule (2am UTC every day)
- Checks out your repo
- Runs Claude Code with a specific task
- Automatically opens a PR if changes were made
The advantage over cron: GitHub Actions handles environment setup, logs are visible in your Actions tab, and you can wire in notifications if a run fails.
Method 3: OpenHelm for Structured Unattended Execution
If you're running multiple scheduled Claude Code tasks or want structured run history and silence detection, OpenHelm manages this through a desktop app.
With OpenHelm, you:
- Define a job in the UI or via command
- Set a schedule (one-time, daily, weekly, custom cron)
- Specify the prompt and working directory
- Enable silence detection (stops runs that produce no output for 10 minutes)
OpenHelm keeps a dashboard of all runs—success/failure status, runtime, output logs, and any errors. If a job hangs, silence detection stops it automatically rather than letting it burn through API credits for hours.
It's the most user-friendly approach if you have multiple projects with multiple scheduled tasks.
Common Pitfalls and How to Avoid Them
Pitfall 1: Unbounded loops. Claude Code with no turn limit can iterate endlessly if the goal isn't specific. Use --max-turns to enforce a hard ceiling.
Pitfall 2: Missing environment variables. When running via cron or Actions, shell environment variables from your login session aren't available. Be explicit:
export NODE_ENV=production
export DATABASE_URL="..."
claude -p "Deploy to staging" --project /path/to/appPitfall 3: Working directory confusion. If your cron job is supposed to work on /Users/you/project-a but accidentally runs in /Users/you/project-b, the results will be wrong. Always use absolute paths.
Pitfall 4: Silent failures. A job that fails without notification is invisible. Whether it's cron, GitHub Actions, or OpenHelm, have a logging or notification strategy so you know when something goes wrong.
Choosing a Method
Use cron if: You have one or two tasks, you're comfortable reading log files, and you don't need a dashboard.
Use GitHub Actions if: Your task is deeply integrated with your CI/CD pipeline and you want run logs visible in your GitHub UI.
Use OpenHelm if: You have multiple projects with multiple scheduled tasks and want structured run history, silence detection, and a dashboard.
Most teams end up mixing these—cron for one-off setup tasks, GitHub Actions for CI-integrated work, and OpenHelm or a similar tool for mission-critical unattended execution.
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.