Claude Code Routines, which Anthropic launched in April 2026, are a saved Claude Code configuration: a prompt, one or more repositories, and connectors, packaged once and run automatically on Anthropic-managed cloud infrastructure. The official docs lay out three trigger types: scheduled cadence, API (HTTP POST with a bearer token), and GitHub events. GitHub Actions, by contrast, execute the scripts you write on GitHub-hosted runners. Both can run AI agents on a schedule. They are not the same thing, and picking the wrong one costs you either money or hours of YAML-wrangling. This post maps the decision, walks the blog queue worker, and covers failure recovery.
Choose Cloud Routines, Desktop, Session Loops, or Actions
Four hosting options exist. They are not interchangeable.
Cloud Routines execute on Anthropic's infrastructure regardless of whether your laptop is on. Per the docs, each routine can carry a scheduled trigger, an API trigger, or a GitHub event trigger, and you can combine all three on one routine. The trade-off: every execution does a fresh clone, so local files are never available.
Desktop scheduled tasks run on your machine. They have full access to your local filesystem, local databases, and .env files. If the machine is off, the task doesn't run. Simple.
Session-scoped scheduling (the CronCreate , CronList , CronDelete tools) operates inside an open CLI session only. These are session scheduling tools, not the cloud routines API. They disappear when the session ends.
GitHub Actions with a cron trigger is a workflow YAML file that GitHub executes on a hosted runner. Free for public repos, cheap for private ones, deterministic, and deeply integrated with your codebase. The overhead is real if you don't already live in GitHub, but for developers who do, it's minimal.
So: how do you choose?
- Task runs whether or not your machine is on, and it needs genuine AI reasoning (summarising, drafting, triaging)? Cloud Routine.
- Task needs your local
.env, a local database, or local tooling? Desktop scheduled task. - Task is a CI/CD pipeline, PR event handler, or a deterministic script that calls an API and posts to Slack? GitHub Actions, possibly with a short Python script and no LLM at all.
- Task is exploratory and lives inside a single session you're already running? Session loop.
AI Magicx's breakdown puts it cleanly: if your routine is "call an API, transform, post to Slack," GitHub Actions with a 10-line Python script is cheaper and simpler. Routines become the right choice when the work genuinely benefits from Claude's reasoning: picking what to report, writing a narrative, reviewing quality.
Persistence, Local Files, and Credentials by Host
This is where operators get burned. The table below uses information from the official docs and community research, not claimed test results.
| Host | Local files | .env | Credentials | Survives closed laptop |
|---|---|---|---|---|
| Cloud Routine | No (fresh clone) | No | Routine environment variables | Yes |
| Desktop scheduled task | Yes | Yes | Local config | No |
Session loop (CronCreate) | Yes (session scope) | Yes | Session scope | No |
| GitHub Actions | Repo files only | No | GitHub Secrets | Yes |
Shareuhack's 2026 write-up flags a specific gotcha worth quoting:
"Every Cloud Routine execution performs a fresh clone in Anthropic's cloud environment, it cannot access your local .env.local, local databases, or other local state."
And one more: network access in cloud routines defaults to "trusted," which some APIs reject outright. If you're hitting ClickUp or another API that drops trusted-mode requests, switch to "full" network access in the routine's environment settings. There is a small security trade-off, so weigh it against your repo's sensitivity.
For GitHub Actions, secrets live in the repository's Secrets settings and are injected as environment variables at runtime. The anthropics/claude-code-action@v1 action, which is built on the Claude Agent SDK, picks those up automatically. You pass --model , --max-turns , and --allowedTools via the claude_args input to control what the agent can actually do.
Read the Current Blog Queue Worker
The blog queue worker is a routine (or equivalent scheduled job) that picks a post from a queue, generates content, and marks it as done. Here's the structure as it stands, with clear caveats about what the code actually does versus what you might assume.

The conditional claim: the worker checks whether a post is already claimed before picking it up. That prevents two executions from grabbing the same item simultaneously, at least in the happy path. What the current code does not have is stale-claim recovery. If a worker dies mid-run with a post marked "in progress," that post stays claimed until someone manually resets it. Do not describe this as exactly-once delivery or guarantee one post per day; both claims go further than the code supports.
The worker diagram looks roughly like this:
- Fetch queue, filter for
status = queued - Claim the first available post (set
status = in_progress, write a timestamp) - Run the generation prompt against the claimed post's metadata
- On success: set
status = published, write the output path - On failure: increment
retry_count, resetstatus = queued(if retries remain) or setstatus = failed
Step 5 is where most teams underinvest. The retry logic needs to live in the routine prompt or the wrapper script, because the cloud infrastructure itself does not re-run a routine that exits with an error.
If you're building content pipelines like this and want the agentic layer handled for you, the work we do at agentic engineering covers exactly this pattern.
Schedule Due Jobs and Handle Retries
Scheduling a routine via the CLI requires Claude Code v2.1.225 or later. Before v2.1.211, the CLI reported a phantom next-run time (year 1) for routines with no schedule trigger. Worth knowing if you're reading old logs.
A routine with only API or GitHub event triggers has no next run time. The CLI shows nothing. That's correct behaviour, not a bug.
For retry handling, you have two options:
- Retry inside the prompt. Write the prompt to re-attempt the failing step up to N times before marking the job failed. Claude's reasoning can distinguish between a transient network error and a genuine content problem.
- Retry via a separate scheduled routine. A lightweight "requeue" routine runs hourly, scans for posts where
status = queuedandretry_count < 3, and re-triggers the main worker via its API trigger (a POST to the per-routine endpoint with a bearer token).
The second pattern is cleaner at scale. It decouples the retry policy from the generation prompt, and you can adjust retry limits without touching the main routine.
Daily run caps and shared subscription usage are a real constraint for teams, as Arcade's enterprise write-up points out. Their recommendation: batch work into a single daily "meta-orchestrator" routine and reserve real-time triggers for high-priority events only.
For the SEO keyword retrieval side of a content pipeline, the automation stack we documented at DataForSEO + Claude Code handles that separately and is worth reading before you design the queue schema.
Detect Stuck Claims and Verify Published Output
Stale claims are the silent killer of queue-based pipelines. A post that's been in_progress for six hours is almost certainly stuck, not running.
A detection routine can be as simple as:
- Query for posts where
status = in_progressandclaimed_at < now() - 2 hours - Reset those to
status = queued, zero out the worker identifier, log the reset - Alert via Slack or a webhook if the reset count exceeds a threshold
Run this as a separate low-frequency routine (every two hours is fine) rather than baking it into the main worker. Separation of concerns matters here: the main worker should not be responsible for cleaning up after itself.
Verifying published output is a different problem. "Published" as a status flag means the database was written. It does not mean the post appeared correctly on the site, passed a readability check, or got indexed. A verification step should:
- Fetch the live URL and confirm it returns a 200
- Check word count or a lightweight quality signal against a defined threshold (pick your own number and label it as a team heuristic, not a universal standard)
- If the check fails, revert
statustoqueuedwith an incrementedretry_countand averification_failedflag
The humaniser pipeline we described at AI Content Humanizer Pipeline runs a similar post-publish verification pass and is worth cross-referencing if you're building that layer.
Operating Cost and Ownership
This is where the "routines are simpler" narrative runs into friction.
Cloud Routines run on Anthropic's infrastructure and consume Claude Code session limits the same way an interactive session does. The research preview makes this explicit: routines drain your limits. For a small indie operator running three or four routines a day, that's probably fine. For a team batching 20+ daily runs, you'll hit the cap and need to architect around it.
GitHub Actions is free for public repos and priced per minute for private ones. A Claude Code agent run inside Actions via anthropics/claude-code-action@v1 still consumes API tokens (billed at your Anthropic API rate), but you control the runner, the timeout, and the retry logic entirely. That ownership is the point.
The ownership split in practice:
- Routines own: judgment-heavy tasks that need Claude's reasoning, tasks that must run unattended with no infrastructure overhead, GitHub-triggered PR reviews, and Sentry/log triage.
- GitHub Actions own: CI/CD pipelines, PR event handling and installation flows, deterministic build-test-deploy sequences, and any task where a 10-line Python script genuinely does the job.
Neither replaces the other. The Shareuhack write-up frames it well: "The optimal combination lets GitHub Actions handle CI/CD while Routines handle the reasoning-intensive parts." That framing is correct, and it's the decision boundary worth bookmarking.
FAQ
Can a Cloud Routine write back to my repository?
Yes. Routines connect to one or more repositories, and they can push commits and open pull requests through the connected repo. What they cannot do is access files that only exist on your local machine. Anything the routine needs must be in the repo or configured as an environment variable in the routine's cloud environment settings.
What happens if a Cloud Routine hits a rate limit mid-run?
The routine itself does not automatically retry on rate limit errors. If it exits with an error, it stays failed until the next scheduled run or until you manually trigger it via the API endpoint. Building retry logic into the prompt (detect a rate limit response, wait, re-attempt) or using a separate requeue routine are both reasonable mitigations.
Is the GitHub App installation separate from the CLI web-setup command?
Yes, and this catches people out. Running /web-setup in the CLI grants clone access to the routine but does not install the GitHub App. Webhook delivery for GitHub event triggers requires the separate GitHub App installation. The routine setup flow prompts you through this, but the two steps are distinct.
Do GitHub event triggers in Routines have rate limits during the research preview?
Per the official routines documentation, GitHub webhook events are subject to per-routine and per-account hourly caps during the research preview. Events beyond the cap are dropped until the window resets. Plan accordingly if you expect bursts of PR activity.
Can I use skills inside a GitHub Actions workflow with `anthropics/claude-code-action`?
Yes. The prompt input accepts skill invocations like /skill-name . You need an actions/checkout step before the action so the skill files in .claude/skills/ are present on the runner. Skills and commands are distinct concepts in Claude Code; check the official skills docs before conflating the two.
The single sharpest caveat from everything above: Cloud Routines drain your Claude Code session limits exactly as interactive sessions do, and the current queue worker has no stale-claim recovery built in. Design for both before you ship anything to production.