Guide5 min read

Claude calendar: how to schedule Claude Code tasks and run Claude Code on a schedule

How to run Claude Code on a schedule: cron with the headless CLI, GitHub Actions, and Claude Code's own schedulers. The pitfalls (expired logins, a sleeping laptop, runs nobody sees) and how a calendar of routines running in the cloud on your Claude plan avoids them.

Written by

To run Claude Code on a schedule, call it headless with claude -p from cron, a GitHub Actions workflow, or one of Claude Code's own schedulers. That handles simple jobs. What breaks is everything around the run: logins expire, laptops sleep, and failures go unseen. A calendar of routines running in the cloud solves those three.

What are the ways to run Claude Code on a schedule?

The options differ mainly in where the run happens:

MethodRuns onMachine must be onGood for
cron + claude -pYour computer or a serverYesFull control, local files
GitHub Actions scheduleGitHub's runnersNoRepo chores and reports
/loop in a sessionYour open sessionYesPolling a deploy or a PR
Desktop scheduled tasksThe Claude desktop appYes, app openLocal jobs without cron
Cloud routines (/schedule)Anthropic's cloudNoRepo work, at most hourly
A calendar workspaceA cloud computer per agentNoWork you want to see and steer

Claude Code's built-in schedulers are the quickest start. A /loop lives inside its session and expires after seven days. Desktop tasks fire only while the app is open and the computer awake. Cloud routines, a research preview on paid plans, clone your GitHub repos fresh on every run.

(Want Claude to read your Google Calendar? That is a connector question. This post is about scheduling Claude's own work.)

How do I schedule Claude Code with cron?

Cron is the most flexible option, and it takes four steps:

  1. Create a long-lived login. Run claude setup-token. It opens the browser sign-in and prints a token valid for one year. Save it as CLAUDE_CODE_OAUTH_TOKEN in a file only you can read.
  2. Write a wrapper script, say ~/bin/claude-errors.sh, and make it executable. Use full paths, including the path to claude that which claude prints, because cron runs with an almost empty environment:
#!/bin/bash
set -euo pipefail
source ~/.claude-cron.env    # exports CLAUDE_CODE_OAUTH_TOKEN
cd ~/code/myapp
~/.local/bin/claude -p "Read the error logs in logs/, group errors by cause, and write reports/errors-$(date +%F).md" \
  --allowedTools "Read,Write,Bash(git log *)" \
  --output-format json >> ~/logs/claude-cron.jsonl
  1. Add the crontab line. 0 8 * * 1 /Users/you/bin/claude-errors.sh runs it every Monday at 8:00.
  2. Pre-approve exactly what the job needs. In a headless run, any action that would ask for permission is denied, so a missing --allowedTools entry means part of the job quietly never happens.

Run the script once by hand before trusting the schedule.

How do I run Claude Code on a schedule with GitHub Actions?

If the job is about a repository, GitHub can own the timer. The Claude Code GitHub Action runs a prompt on any event, including a cron schedule:

name: weekly-report
on:
  schedule:
    - cron: "0 8 * * 1"
jobs:
  report:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      issues: read
      id-token: write
    steps:
      - uses: anthropics/claude-code-action@v1
        with:
          claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
          prompt: "Summarize last week's commits and open issues in under 200 words."
          claude_args: |
            --allowedTools "mcp__github__list_commits,mcp__github__list_issues"

Things to know before you rely on it:

  • Store the token from claude setup-token as a repository secret. It is tied to your own subscription.
  • GitHub reads the cron line in universal time, so convert from your own time zone.
  • Schedules run only from the default branch, and in public repos GitHub disables them after 60 days without repository activity.
  • Each run starts on a fresh machine. Output lands in the workflow log unless the job posts or commits it somewhere you will see it.

Why do scheduled Claude Code jobs fail?

Most failures have nothing to do with the prompt:

  • Auth expires. An interactive login eventually expires, and every request then fails with "Login expired" until someone runs /login. Use the one-year token, put its renewal date on your own calendar, and note that --bare mode ignores that token and wants an API key instead.
  • The laptop is asleep. Cron skips jobs while the machine sleeps, and the desktop app only fires while it is open and awake. Monday at 8:00 often happens with the lid closed.
  • Nobody answers prompts. Headless runs deny anything you did not pre-approve. The run still ends normally, minus the step that mattered.
  • Usage limits. A job at 3:00 that hits your plan's limit simply stops, and you find out at breakfast, if at all.
  • "Success" means the process exited. Exit code 0 or a green run says Claude finished, and says nothing about whether the task worked. Anthropic's own routine docs make the same point: read the transcript.
  • Overlaps. A slow run collides with the next one, and two agents edit the same files.

How do I make scheduled Claude runs visible?

A schedule you cannot see is a schedule you stop trusting. Six habits fix most of it:

  1. Ask for structured output. --output-format json returns the result, session ID and cost. Add --json-schema and Claude fills fields you define, such as status, summary and needs_human.
  2. Send results where you already look. End the script by posting the summary to Slack, email or a Telegram bot, including failures.
  3. Produce a deliverable every run. A dated report file or a pull request means "did it run?" has a file as its answer.
  4. Prevent overlaps. On Linux, flock -n /tmp/claude-errors.lock ./claude-errors.sh exits if the previous run is still going.
  5. Keep a run log. Append each JSON result to one file and skim it weekly. A missing date is a run that never started.
  6. Put a checkpoint before anything public. Let the job draft the post, the email or the deploy, then stop and wait for you.

These turn a scheduled job from a hope into something you can audit in two minutes a week.

What do routines, events and time windows add?

Once you have more than a handful of scheduled jobs, a list of crontab lines stops being enough. Three ideas help, whatever you build on:

  • Routines. Recurring work with a name, an owner and a time in your own time zone: "every Monday at 8:00, the support agent summarizes last week's tickets".
  • Events. Work that starts when something happens: a webhook from Stripe, a new file in a folder, a merged pull request. Polling on a timer burns runs on empty checks. An event fires once, when there is something to do.
  • Windows. A start and an end date on a routine. A launch-week routine that posts a daily metrics recap should stop by itself after launch, without you remembering to delete a crontab line.

All of it belongs on a calendar next to your one-off tasks, because the questions you actually ask are "what is running this week?" and "what came out of it?" A crontab answers neither. If your one-off work also lives in chat threads, Claude task management covers how to give it a proper board.

How does Kavela put Claude on a calendar?

Kavela's workspace is a calendar (month, week and day views). You tell Kav, the agent that runs your workspace, what should happen and when, and it lands as one of three kinds of work: tasks that run as soon as possible or at a set time, routines (every Monday at 8:00 in your time zone, optionally only between a start and end date), and events that fire on a webhook from any service or a file added to the workspace.

Every run happens in the worker agent's own cloud computer, with a shell, files, git and a browser, and keeps going with your laptop closed. Set the agent to "My Claude plan" and Claude Code runs there on your own subscription. You sign in once from a card instead of managing a token yourself. With several accounts connected, Kavela rotates when one hits its usage limit, and if all are at their limit the run pauses and asks you once: wait and resume automatically, finish on Kavela credits, or cancel.

Results come back as deliverables attached to the task, decisions wait in one Approvals inbox, and Telegram sends you a regular digest.

Kavela is in early access, with a 14-day free trial and no limit on routines. Start your free trial

Keep reading