Originally published at hafiz.dev
The problem with most AI coding workflows is they stop when you do. You close your laptop, the session ends. You're asleep, nothing runs. You come back Monday morning to a pile of unreviewed PRs and no idea whether Friday's deploy is healthy.
Claude Code Routines changes that. They run on Anthropic-managed cloud infrastructure, which means the session keeps going whether your machine is on or not. You write the prompt once, wire up a trigger, and the work happens in the background.
This is a practical guide to getting Routines set up on a real Laravel project. Five concrete use cases, actual prompts, and the gotchas you'll run into before you do.
What Routines are (and what they're not)
A Routine is a saved Claude Code configuration: a prompt, one or more GitHub repositories, and optional MCP connectors, packaged together and triggered automatically. Each run creates a full Claude Code cloud session on Anthropic's infrastructure. Claude clones your repo, does the work, and pushes to a claude/-prefixed branch.
Three things are worth knowing upfront.
First, Routines are different from /loop and Desktop scheduled tasks. /loop runs prompts inside your current terminal session and dies when you close it. Desktop scheduled tasks run on a schedule but need your machine to be on and Claude Code Desktop open. Routines are the only option that runs fully unattended on cloud infrastructure.
Second, this feature is currently in research preview. Behavior, the API shapes, and rate limits may change. That said, it's available right now on Pro, Max, Team, and Enterprise plans with Claude Code on the web enabled at claude.ai/code.
Third, Routines run fully autonomously. No approval prompts during a run. Whatever you write in the prompt is what runs. This is meaningfully different from a normal Claude Code session where you can steer mid-task. If you've used Claude Code Channels to send commands remotely, think of Routines as the version that runs without you sending anything at all.
| Option | Where it runs | Machine required? | Survives closing terminal? |
|---|---|---|---|
/loop |
Local terminal | Yes | No |
| Desktop scheduled task | Your machine | Yes | No |
| Routine | Anthropic cloud | No | Yes |
The three trigger types
Every Routine needs at least one trigger. You can also stack them on the same Routine.
Schedule triggers run on a recurring cadence. Hourly is the minimum interval. Daily, weekdays, and weekly are the built-in presets. For something like "every two hours" or "first Monday of the month," you pick the closest preset in the form and then run /schedule update in the CLI to set a specific cron expression after creation.
API triggers give the Routine a dedicated HTTP endpoint. POST to it with a bearer token and optionally pass a text field for run-specific context. This is what makes Routines composable with the rest of your stack: your deploy pipeline, your alerting system, a webhook from Sentry. Any service that can make an authenticated HTTP request can trigger a Routine.
GitHub triggers react to repository events automatically. A PR is opened. A release is published. A labeled PR gets a new commit pushed. You add filters to narrow which events fire: base branch equals main, is draft is false, author contains a specific username.
One Routine can use multiple triggers. A code review Routine might run nightly (for anything opened the day before), fire on every new PR, and be callable via API from your CI pipeline. All three wired to the same prompt.
Five Laravel use cases worth setting up
1. Nightly PR review
The most immediately useful Routine for any active Laravel project. Claude reviews all open PRs opened in the last 24 hours, runs your Pest test suite, flags anything touching auth or database migrations, and leaves inline comments.
Prompt to use:
Review all open pull requests in this repository that were opened in the last 24 hours and have no reviewer assigned.
For each PR:
- Run the Pest test suite and report any failures
- Check that migrations are reversible and include both up() and down() methods
- Flag any raw queries that bypass Eloquent
- Check that jobs implement ShouldQueue and define both $tries and $timeout
- Flag any use of env() outside of config files
- Leave inline review comments for issues found
- Add a summary comment listing all issues, or confirming the PR is clean
Do not approve the PR. Add a "needs-changes" label if any issues are found, and "passed-ai-review" if clean.
Set a schedule trigger for every weekday at 8:00 AM. You start the morning with feedback already posted. Human reviewers can focus on architecture instead of catching env() in the wrong place.
2. Queue health check
Horizon is great but it doesn't catch everything. A nightly Routine can run queue diagnostics on your Laravel project and ping you only when something is actually wrong, not just generate noise.
Using the environment variables available in this session, run the following checks:
1. Run php artisan queue:monitor against all configured queue drivers
2. Check the failed_jobs table for any entries created in the last 24 hours
3. Hit the /horizon/api/stats endpoint and verify Horizon is running and workers are active
4. Check the application log for any CRITICAL or ERROR entries from the last 24 hours
If all checks pass, exit without posting anything.
If any check fails, post a message to the #alerts Slack channel with the failure details and the exact artisan commands to fix it.
You'll need a Slack MCP connector configured and your environment credentials set as environment variables in the cloud environment. For a full list of queue-related Artisan Commands, the reference page is worth bookmarking when you're building out the prompt.
3. Automated code review on PR open
Set a GitHub trigger to fire on pull_request.opened with one filter: is draft is false. This catches every non-draft PR the moment it's opened and runs your team's checklist before a human reviewer even looks at it.
A new pull request has just been opened. Apply our Laravel code review checklist:
- New controllers must use the single-action pattern (one public __invoke method only)
- Form Requests used for all validation, never validate() inside controllers
- No env() calls outside of config files
- No missing $fillable on new Eloquent models
- All new jobs implement ShouldQueue and define $tries and $timeout
- Flag any database queries inside loops (N+1 problem) with the exact file and line
- No direct use of DB::statement() or DB::select() without a comment explaining why
Leave an inline comment for each violation. Post a summary comment at the bottom of the PR. Add label "passed-ai-review" if clean, or "needs-changes" if violations were found. Do not approve or request changes on the PR directly.
The filter matters here. is draft: false means the Routine only fires on PRs that are actually ready for review. You don't want it running every time someone pushes a commit to a draft.
4. Post-deploy smoke test via API
Wire your CD pipeline to trigger a Routine every time a production deploy completes. The Routine runs smoke checks against the new build and posts the result to your release channel.
The API trigger gives you a text field you can use to pass deploy context. From your deploy script:
curl -X POST https://api.anthropic.com/v1/claude_code/routines/trig_01XXXXX/fire \
-H "Authorization: Bearer YOUR_ROUTINE_TOKEN" \
-H "anthropic-beta: experimental-cc-routine-2026-04-01" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{"text": "Deploy complete. SHA: abc123. Environment: production."}'
Note: the bearer token here is your Routine-specific token, not your Anthropic API key. Generate it from the API trigger setup in the web UI. It's shown once, so store it in your secrets manager immediately.
The Routine prompt can reference the deploy context passed via text:
A production deploy has just completed. The deploy details are in your session context.
Run the following smoke checks:
1. Hit the /health endpoint and verify a 200 response
2. Run php artisan about to confirm the application is responding
3. Run php artisan queue:monitor and report queue status
4. Check the error log for any new CRITICAL entries in the last 5 minutes
Post results to the #deployments Slack channel. Include the deploy SHA from the context. Mark as PASS if all checks succeed, FAIL with details if any check fails.
5. Weekly documentation drift detection
Docs get stale. A weekly Routine that scans merged PRs, compares changed methods against your /docs directory, and opens update PRs when it finds drift handles this automatically.
Scan all pull requests merged in the last 7 days.
For each merged PR:
1. Identify which PHP files changed
2. Check whether the changed public methods or classes are referenced in the /docs directory
3. If documentation references a changed method but looks outdated based on the diff, open a PR against the docs branch with a suggested update
Skip PRs that only changed tests, migrations, config files, or frontend assets. Only flag documentation that references changed public-facing methods or API endpoints.
Schedule it for Sunday at midnight. By Monday morning you have doc update PRs queued, not a manual task sitting in someone's backlog.
Setting up your first Routine
The fastest path is through the web UI. Go to claude.ai/code/routines and click New routine.
Give it a descriptive name. "Nightly PR Review" is better than "Routine 1." Write the prompt. This is the most important part: the Routine runs without you in the loop, so the prompt must be explicit about what to do and what success looks like. Vague prompts produce vague results, and there's no one watching to redirect them.
Select your GitHub repository. Claude clones it fresh at the start of every run, starting from the default branch.
Pick an environment. The Default environment works for most cases. If your Routine needs to call external APIs or read secrets like Sentry tokens or Slack webhooks, create a custom environment first and set those values as environment variables there.
Add your trigger. For a scheduled Routine, pick the frequency. Times are set in your local timezone and converted automatically, so "9:00 AM" fires at 9:00 AM wherever you are, not in some UTC offset you have to calculate.
Review the connectors. All connected MCP connectors are included by default. Remove anything the Routine doesn't actually need. A Routine that only reviews code and opens PRs has no reason to have Linear or Google Drive in scope.
Click Create. Hit Run now on the detail page to test it immediately without waiting for the next scheduled time.
From the CLI, run /schedule in any Claude Code session to create a Routine conversationally. Useful when you know exactly what you want and don't want to click through the web UI. /schedule list shows all your Routines, /schedule update changes one, and /schedule run triggers it immediately.
Branch permissions: the default that catches people
By default, Routines can only push to branches prefixed with claude/. This is intentional. An autonomous agent creating commits on main or develop is risky if the prompt isn't perfectly scoped.
When you add a repository to a Routine, there's an Allow unrestricted branch pushes toggle. Leave it off unless you have a specific need. The claude/ prefix keeps automated work clearly identifiable and makes cleanup straightforward if something goes sideways.
If your Routine is creating PRs that look right but fails on push, this is almost certainly the reason. Enable unrestricted pushes for that repo in the Routine's settings.
The flip side: PRs created by a Routine appear under your GitHub identity. Commits carry your username. Slack messages sent by a Routine's connector use your Slack account. The Routine acts as you, not as a bot account.
Plans and limits
Routines are available on Pro, Max, Team, and Enterprise plans. They draw from your regular Claude Code subscription usage the same way interactive sessions do. There's also a daily cap on how many Routine runs can start per account, visible at claude.ai/settings/usage.
If you hit the daily cap, additional runs are rejected until the window resets. On Team and Enterprise plans with extra usage enabled, Routines continue on metered overage instead.
GitHub event triggers also have per-routine and per-account hourly caps during the research preview. Events beyond the limit are dropped until the window resets. Worth keeping in mind if you're setting up a trigger on a high-volume repository.
When to use GitHub Actions instead
Routines are not a replacement for CI/CD. Running tests on every push, deploying to staging on merge, enforcing security checks before a PR can be merged, anything that needs to block a developer workflow belongs in GitHub Actions. It integrates with branch protections, runs in your own infrastructure, and has native visibility in the PR UI.
Routines are better for background work that doesn't need to gate anything. Review, triage, documentation updates, monitoring. Think of it as the difference between a gatekeeper (CI/CD) and an assistant handling repetitive work in the background.
Also, Routines run with no approval prompts. That's the point, but it's also a risk. Test any Routine with Run now and review what it actually did before leaving it to run unattended. A badly scoped PR review prompt that opens 30 spurious PRs is not a great Monday morning.
The Claude Code ecosystem post covers where Routines fit alongside other pieces like CLAUDE.md, skills, MCP, and the plugin marketplace if you want the full picture.
FAQ
Do Routines work on private repositories?
Yes. Routines clone your connected GitHub repositories, including private ones, as long as you've granted the necessary access via the web setup flow or /web-setup in the CLI. GitHub event triggers specifically require installing the Claude GitHub App on the repository. Repository access via /web-setup is separate and doesn't install the App automatically.
What's the difference between a Routine and a GitHub Action that calls Claude Code?
GitHub Actions run on GitHub's infrastructure, count against your GitHub Actions minutes, and can gate PRs and deployments through required status checks. Routines run on Anthropic-managed infrastructure and count against your Claude Code subscription. Use GitHub Actions when you need to block something. Use Routines for background work that doesn't need to block anything.
Can I share Routines with teammates?
Not currently. Routines belong to your individual claude.ai account and aren't shared. Everything a Routine does through your GitHub identity or connectors appears as you. For team workflows where multiple people need the same automation, each person sets up their own Routine, or you handle it through GitHub Actions with shared secrets.
Can I pass different context on each API trigger call?
Yes. The optional text field in the API request body is passed to the Routine as run-specific context alongside its saved prompt. Pass anything: a Sentry alert body, a deploy SHA, a list of changed files. The Routine receives it as a literal string, so don't send structured JSON expecting it to be parsed. If you need structured data, serialize it yourself and parse it in the prompt instructions.
What happens when a Routine run fails mid-session?
The run session stays visible at claude.ai/code/routines. You can open it, see exactly what Claude did, and continue the conversation manually if needed. The Routine itself keeps running on future triggers. Only that individual run failed.
Conclusion
Routines flip the default. Instead of Claude Code being a tool you actively drive, it becomes something that works in the background while you're focused on other things, or asleep. The nightly PR review alone is worth the setup time on any project with more than one contributor.
Start with one. Set up the nightly PR review, run it manually a few times to tune the prompt, then leave it running. Once you trust it, you'll think of five more things to automate.
Building a Laravel application that needs architectural review or a second set of eyes on code quality? Get in touch and let's talk about what that looks like.
Top comments (0)