How do I make Claude open a PR every Monday morning?
Routines are saved Claude Code configurations that run on a schedule, on demand via HTTP, or in response to GitHub events — on Anthropic's cloud, not your laptop. This is everything you need to set one up and avoid the obvious footguns.
For the first two years Claude Code was a tool you opened. Routines are the moment it becomes something you deploy.
A routine is a saved configuration — a prompt, one or more repos, an environment, a set of connectors, and one or more triggers — that runs on Anthropic’s cloud infrastructure. Your laptop can be closed. The deploy can land at 3am. The Sentry alert can fire while you’re on the train. Claude still works.
This guide is the practical version: the three trigger types, a real worked example, the identity gotchas, and the cases where a routine is the wrong answer.
What a routine actually is
Five things, packaged once:
- A prompt. What Claude should do, written so it’s complete on its own. There’s no human to clarify mid-run.
- One or more GitHub repositories. Cloned fresh from the default branch on every run.
- An environment. Network level, environment variables, a setup script that gets cached so deps don’t re-install every time.
- Connectors. Your linked MCP connectors (Slack, Linear, Drive, etc.). All connectors you have linked are included by default — you have to actively remove the ones the routine shouldn’t touch.
- One or more triggers. Schedule, API endpoint, or GitHub event. A single routine can have all three.
You create them at claude.ai/code/routines, in the Desktop app’s Routines sidebar (pick Remote, not Local), or with /schedule from the CLI.
Research preview, real money. Routines are still in research preview as of mid-2026 — expect API shape and limits to shift. They run as you: every commit, every PR, every Slack message goes out under your GitHub identity and your linked connector accounts. Set up scope deliberately, not generously.
The three trigger types
You can attach any combination of these to one routine.
Schedule
Hourly, daily, weekdays, weekly. Times are entered in your local zone and converted automatically, so 9am Helsinki stays 9am Helsinki regardless of where the cloud actually runs the job. Runs may start a few minutes off the dot due to stagger; the offset is consistent per routine.
For non-preset cadences (every two hours, first of each month, etc.) pick the closest preset in the web form, then run /schedule update from the CLI to swap in a real cron expression. Minimum interval is one hour — anything more frequent is rejected.
There’s also a one-off variant. /schedule tomorrow at 9am, summarize yesterday's merged PRs resolves the natural-language phrase against the current time and confirms the absolute timestamp before saving. After it fires, the routine auto-disables. One-off runs don’t count against the daily routine cap.
API
Each routine can be given a dedicated HTTP endpoint with a bearer token. You POST to it, optionally with a text body, and it kicks off a session. The endpoint returns a session URL you can open to watch the run.
This is how you wire Claude into Sentry, PagerDuty, your deploy pipeline, an internal Retool button — anywhere you can make an authenticated HTTP request.
API triggers can only be added from the web UI today. The CLI can’t generate or revoke tokens. Once generated, the token is shown once — store it before you close the modal.
GitHub
Pull-request and Release events. Choose a category, pick a specific action (pull_request.opened, release.published, etc.), and optionally filter by author, title, body, base branch, head branch, labels, draft state, or merged state.
A real footgun: the matches regex filter operator tests the entire field, not a substring. To match any PR title containing “hotfix”, write .*hotfix.* — without the surrounding .*, the filter only matches a title that is exactly the word hotfix. For substring matching without regex, use contains instead.
GitHub triggers need the Claude GitHub App installed on the repo. /web-setup grants clone access but does not install the app — the trigger setup screen will prompt you when needed.
Worked example: weekly PR opener
The motivating example. Every Monday at 9am, Claude reviews last week’s merged feature PRs and opens a docs-update PR for any that mention public API changes.
Step 1: Write the prompt like Claude won’t be there to ask questions
You are running on Monday morning. Look at the merged pull requests in the
`api` repo from the last 7 days. For each merged PR whose title contains
"feat(api)" or whose body mentions a public endpoint change, check whether
the corresponding section of `docs/api.md` was updated.
If a PR changed the API surface but no matching docs commit landed, draft
the docs change yourself. Open a single new PR titled
"docs(api): catch up to last week's API changes" against `main` from a
`claude/docs-catchup-<date>` branch. List the source PRs in the description.
If everything is documented, post one Slack message to #eng-docs that says
"docs are caught up through <date>" and exit. Don't open an empty PR.
Notice what’s in the prompt: the success criteria, the failure mode (don’t open empty PRs), the branch naming, the Slack channel for the no-op case. Routines run autonomously — if you don’t say what success looks like, Claude has to guess.
Step 2: Pick the repos and environment
For this routine you need the api repo (read + push for the docs branch) and the docs repo if it’s separate. Default branch push is off by default — Claude can only push to claude/-prefixed branches, which is exactly what we want for claude/docs-catchup-2026-05-04. Don’t enable “Allow unrestricted branch pushes” unless you really need it.
The Default environment works for this case (no special deps, just git/gh).
Step 3: Trim connectors
By default every connector you’ve ever linked is included. For a docs-catchup routine the routine needs Slack (to post the no-op message) and GitHub (implicit from repo selection). Remove Linear, Drive, Notion, Calendar, anything else.
This step matters more than people realize. A routine with all your connectors enabled has the union of every write permission you’ve ever granted Claude — and it can act on them without per-tool approval during a run.
Step 4: Set the schedule
Pick Weekly from the trigger picker, set Monday 09:00, save. That’s it. The first run fires next Monday.
Step 5: Watch the first run
Click the routine on the Routines list, click Run now to fire it once immediately, and open the resulting session URL. You can watch every tool call, every file Claude reads, every PR draft. Always do this before letting it run unattended. Routines are autonomous; you’re not — your one job before walking away is to verify the prompt produces the right behavior.
API trigger in 30 seconds
For the alert-triage variant, add an API trigger after the routine is saved:
curl -X POST https://api.anthropic.com/v1/claude_code/routines/trig_01ABCDEFGHJKLMNOPQRSTUVW/fire \
-H "Authorization: Bearer sk-ant-oat01-xxxxx" \
-H "anthropic-beta: experimental-cc-routine-2026-04-01" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{"text": "Sentry alert SEN-4521 fired in prod. Stack trace attached."}'
The response body looks like:
{
"type": "routine_fire",
"claude_code_session_id": "session_01HJKLMNOPQRSTUVWXYZ",
"claude_code_session_url": "https://claude.ai/code/session_01HJKLMNOPQRSTUVWXYZ"
}
The text field is freeform. If you send JSON, the routine receives it as a literal string — it isn’t parsed for you. Either keep your alert payload as plain text, or have the prompt know it’ll be receiving JSON-as-string and parse it.
The experimental-cc-routine-2026-04-01 beta header is the API contract version. Anthropic ships breaking changes behind new dated headers and keeps the two most recent ones working — give yourself a calendar reminder for the migration window.
Footguns that bite people
Identity sprawl. Every connector you have linked is included by default. A routine you wrote for “open PRs” may also have Slack, Linear, Drive, and your calendar attached. Trim aggressively.
Branch-push permissions. “Allow unrestricted branch pushes” is off by default for a reason. Leave it off unless you’ve thought about it — claude/-prefixed branches keep accidents quarantined.
One-off runs are a separate budget. They consume regular subscription usage but don’t count against the daily routine cap. Useful: schedule a “remind me to clean up the feature flag in two weeks” without worrying about the cap.
Daily routine cap is per account, not per routine. Many small hourly routines eat the same budget as a few big nightly ones. Watch your remaining-runs counter at claude.ai/settings/usage.
No human to ask. A routine has no permission-mode picker. Skills committed to the cloned repo are available, connectors are available, and Claude runs without approval prompts. The prompt has to encode the safety: tell it explicitly what it can and can’t push to, what to do on uncertainty, and when to bail with a Slack message instead of an action.
The token shows once. Generate, copy, paste into your secret store — in that order. There’s no recovery, only regeneration.
GitHub regex matches the whole field. hotfix ≠ .*hotfix.*. The doc says it; the form doesn’t shout it.
When NOT to use a routine
- You need to react in seconds. Routines stagger by a few minutes and run on shared infrastructure. For genuine real-time work, channels are the right primitive.
- The prompt would need clarification. If the prompt isn’t fully self-contained, an autonomous run will produce mediocre work. Run it interactively a few times first, distill what worked, then promote to a routine.
- You’d want to step in halfway. The session is open in the web UI — you can take over — but if mid-run intervention is the common path, this is just a regular session you’re scheduling for no reason. Use
/loopfor in-session repetition or Desktop scheduled tasks for local recurring work. - The work touches secrets you wouldn’t paste into a Sentry alert. Routines run on Anthropic-managed infra. Your environment can carry env vars, but treat the cloud session like any other multi-tenant compute: if it’s not OK to run there, don’t.
The shift in your head
Most Claude Code mental models still treat it as a tool — you open it, you ask, you watch. Routines move part of your workflow into the same conceptual bucket as cron jobs, GitHub Actions, or a Lambda function: written once, kicked off by something else, observed in summary.
The mistake is to treat them like a chatbot you happen to have automated. The work goes in the prompt, not in your head. Spend the time you’d spend in a normal session writing the prompt, the success criteria, and the no-op behavior — then let the cloud carry it.
Sources
- Routines (canonical doc) — Triggers, connectors, environments, limits — the full reference
- Claude Code on the web — cloud environment — Network levels, env vars, setup scripts, environment caching
- MCP connectors — What connectors are available and how identity works
- Trigger a routine via API (platform reference) — Full API reference: error responses, validation, field limits
- /loop and in-session scheduling — Local alternative when you don't actually need cloud