Routines
Package a prompt, repositories and connectors into a routine that runs in the cloud on a schedule, from an HTTP call, or when GitHub events fire.
A routine is a saved Claude Code job. You write the prompt once, choose the repositories, environment and connectors it needs, and attach one or more triggers. Each time a trigger fires, a full Claude Code cloud session starts and carries out the task, whether or not your laptop is open.
Note: Routines are in research preview. Limits, behaviour and the API may change.
Routines are available on Pro, Max, Team and Enterprise plans. You manage them at claude.ai/code/routines, in the desktop app, or with /schedule in the CLI. All three edit the same account, so changes show up everywhere immediately.
Triggers at a glance
| Trigger | Starts a run when | Configure from |
|---|---|---|
| Schedule | A recurring time arrives (hourly, daily, weekdays, weekly, or custom cron) or a one-off timestamp is reached | Web, desktop, CLI |
| API | Something POSTs to the routine's /fire endpoint with its bearer token | Web only |
| GitHub | A matching pull request or release event happens on a connected repository | Web, or CLI v2.1.225+ |
You can mix them. A review routine might run nightly, be poked by your deploy script, and also react to each new PR.
Ideas that work well
Routines suit work that is unattended, repeatable and has a clear finish line. Some I have set up or seen work:
- Dependency watch. Weekly schedule: check for outdated packages with known advisories, open one PR per upgrade with the changelog summarised in the description.
- Alert to draft fix. Your monitoring tool fires the API trigger with the alert body. The routine finds the stack trace, matches it to recent commits and opens a draft PR linking back to the alert.
- House-style review. GitHub trigger on
pull_request.opened: apply your team's checklist and leave inline comments so humans can focus on design. - Post-deploy smoke test. The CD pipeline fires the routine after release; it runs smoke checks, scans error logs and posts go or no-go.
- Docs drift. Weekly: look at merged PRs, find docs that mention changed APIs, open update PRs.
- Cross-language port. GitHub trigger on merged PRs in the Python SDK; port the change to the TypeScript SDK and open a matching PR.
How a run behaves
A run is a full cloud session with no permission prompts. Claude runs shell commands, uses skills committed to the cloned repos and calls every included connector tool, including writes, without asking. The one exception is publishing artifacts: Claude republishes an existing artifact unprompted only if all of these hold:
- you can edit it and it belongs to your organisation;
- it is not publicly shared;
- if shared with people or your organisation, viewers do not automatically see each new version;
- the publish carries only the page (no extra files) and does not force over a newer version;
- the page has no grant reaching beyond itself, such as connector calls.
Otherwise, including publishing a new artifact, Claude asks. If a routine's job is to keep a dashboard fresh, publish the page yourself first and point the routine at it.
Routines belong to you. They are not shared with teammates, runs count against your own usage, and everything they do appears as you: commits and PRs carry your GitHub identity, and Slack posts or Linear tickets use your linked accounts.
What a routine can touch is the sum of its repositories, its environment's network access and variables, and its connectors. Keep each as narrow as the job allows.
Creating a routine on the web
- Go to claude.ai/code/routines and click New routine.
- Name it and write the prompt. This is the part that matters. Nobody is there to answer questions, so spell out the task, the constraints and what "done" looks like. Pick the model from the selector in the prompt box; every run uses it.
- Add repositories. Each is cloned fresh on every run from its default branch. Claude pushes to
claude/-prefixed branches. - Choose an environment. The cloud environment sets network access, variables and a cached setup script. Default uses Trusted access: package registries, cloud provider APIs, container registries and common dev domains only. Environment variables are visible to anyone using that environment, so on Pro and Max keep API keys as network secrets instead.
- Pick triggers under Select a trigger. For API, select it and save first; the URL and token are generated afterwards because they depend on the routine ID.
- Prune connectors. Every connector on your account is included by default. Remove what the routine does not need.
- Create. Use Run now on the detail page to test it straight away.
In the desktop app, open Routines in the Code tab sidebar (or its More menu), click New routine and choose Cloud. Choosing Local creates a desktop scheduled task that runs on your machine instead.
How the prompt is treated
When a trigger fires, the session receives the saved prompt as its assigned task, not as untrusted mid-conversation input. The trigger only proves the prompt was stored in advance by an authorised session on your account, so it cannot stand in for live approval of risky actions. Anything Claude fetches during the run is handled as usual. (Before v2.1.213 the prompt arrived framed as an untrusted background notification, and Claude sometimes declined to act.)
Creating from the CLI
/schedule (alias /routines) sets up scheduled routines conversationally:
/schedule every weekday at 08:10, triage new issues in acme/storefront and post a summary to #storefront-eng
Claude asks about repositories, timing and prompt details before saving. If it instead says you need to authenticate or cannot reach your claude.ai account, nothing was created; see troubleshooting.
The CLI cannot create API triggers. It can add GitHub triggers from v2.1.225. A routine with no schedule has no next run time, and the CLI shows none (versions before v2.1.211 printed a date in year 1).
Schedule triggers
Choose hourly, daily, weekdays or weekly. Enter times in your own time zone; they are converted so the run happens at that wall-clock time.
Tip: Runs set exactly on the hour can start several minutes late. Use something like 09:07 instead of 09:00 if timing matters.
For other intervals (every two hours, the first of the month), pick the nearest preset and then run /schedule update to set a cron expression. Anything more frequent than once an hour is rejected.
One-off runs
A one-off schedule fires once at a set time, then disables itself and shows as Ran. Edit it and set a new time to reuse it. Describe the time in plain language from the CLI and Claude confirms the exact timestamp:
/schedule on Friday at 4pm, check whether the v3 migration PR merged and open the cleanup PR if so
One-off runs count towards the same hourly limit as recurring ones.
API triggers
An API trigger gives the routine its own HTTPS endpoint. Add it on the web:
- Open the routine, then Edit from the menu next to its name.
- Under Select a trigger, click Add another trigger and choose API.
- Copy the URL, click Generate token and copy the token now. It is only shown once.
Each token can only fire its own routine. Regenerate and Revoke live in the same dialog. The CLI cannot create or revoke tokens.
Firing it
POST to the /fire endpoint with the token and two required headers. The optional text field carries per-run context:
curl -X POST "$ROUTINE_URL" \
-H "Authorization: Bearer $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 2026.10.08-3 finished on prod-eu at 14:02 UTC"}'
The response contains type: "routine_fire", a claude_code_session_id and a claude_code_session_url you can open to watch the run. A wrong URL or token returns 401.
text is passed through as a literal string, even if it is JSON. It also arrives wrapped in a <routine-fire-payload> block marked as untrusted, with an instruction not to obey it unless the routine's own prompt says to. Text supplied with Run now is wrapped the same way. So your prompt has to opt in explicitly, for example:
Run the smoke checks against the deployment described in the routine-fire-payload block.
That design means a leaked token can only feed in labelled, untrusted data rather than commands.
Warning: The endpoint sits behind the
experimental-cc-routine-2026-04-01beta header. Breaking changes ship under new dated header values, and the two previous values keep working for a while so callers can migrate. The endpoint is for claude.ai users only and is not part of the public Claude Platform API.
GitHub triggers
A GitHub trigger starts a fresh session for each matching event; sessions are never reused, so two pushes to a PR mean two sessions. The Claude GitHub App must be installed on the repository. /web-setup grants clone access but does not install the app or enable webhooks.
On the web: Edit, Add another trigger, GitHub event, then choose the repository, event and filters. From the CLI (v2.1.225+), install the app first, then ask, for example /schedule add a GitHub trigger to my release notes routine for releases published in acme/cli. Claude replies with a link to the routine.
Webhook deliveries are capped per routine and per account each hour; anything over is dropped until the window resets.
Events
| Category | Fires on |
|---|---|
| Pull request | Opened, closed, assigned, labelled, synchronised and other updates |
| Release | Created, published, edited or deleted |
Pick a specific action such as pull_request.opened, or all actions in the category.
Pull request filters
All conditions must match. Fields: Author, Title, Body, Base branch, Head branch, Labels, Is draft, Is merged. Operators: equals, contains, starts with, is one of, is not one of, matches regex.
matches regex tests the whole value. To find migration anywhere in a title use .*migration.*, or just use contains.
Useful combinations:
- Only ready PRs: Is draft equals
false. - Payments code to a specialist reviewer: Base branch equals
main, Head branch starts withpayments/. - Backports on demand: Labels include
backport-2.x. - Post-merge follow-up: event
pull_request.closed, Is merged equalstrue.
Managing routines
Each routine's detail page shows its repositories, connectors, prompt, schedules, API tokens, GitHub triggers and past runs. From there:
- Run now starts a run, optionally with run-specific text.
- The on/off switch pauses or resumes it without losing configuration.
- Edit (from the menu by the name) changes anything, including triggers.
- Delete removes it.
Click a run to open it as a normal session: inspect, open a PR, carry on the conversation, rename, archive or delete.
Warning: A green status only means the session started and ended without an infrastructure fault. It says nothing about whether the task worked. Read the transcript; blocked requests and missing tools show up there.
From the CLI: /schedule list, /schedule update, /schedule run. From v2.1.227 you can also ask questions such as /schedule why did the docs drift routine open no PRs last week? and Claude will list recent runs and read their logs.
Repositories and branches
When you create a routine with /schedule, Claude checks you have GitHub access to the current repo and adds a setup note if not. See GitHub authentication options.
If GitHub is disconnected or expired when a run is due, the routine skips runs for up to 72 hours. Reconnect within that window and it resumes by itself; after that it switches off and you must turn it back on.
Claude starts from the default branch and pushes to claude/... branches unless the prompt says otherwise. Use GitHub branch protection or rulesets to limit where it can push. Those rules are evaluated against the GitHub access you connected (for Anthropic-hosted runs and self-hosted runs using Anthropic's git proxy), so a rule your access can bypass will not stop a push. Self-hosted runs using their own git credentials are checked against those.
Connectors
Routines use the claude.ai connectors on your account. MCP servers added locally with claude mcp add live on your machine and do not appear. Either add them as connectors at claude.ai/customize/connectors or, for single-repo routines, commit them in the repo's .mcp.json. See MCP.
Network access
The routine inherits its environment's network policy. Under Trusted, requests to hosts outside the allowlist fail with 403 and x-deny-reason: host_not_allowed. Connector traffic goes through Anthropic's servers, so connectors need no allowlist changes.
To open up one of your own environments: Edit the routine, click the cloud icon with the environment name below Instructions, hover the environment and click its settings icon, set Network access to Custom, add Allowed domains (tick Also include default list of common package managers to keep the defaults), or choose Full. Save; the next run uses it. Organisation-shared environments are read-only here; an Owner edits them under Cloud environments in admin settings.
Usage and limits
Runs consume subscription usage just like interactive sessions. On top of that, there are hourly caps with no overage:
| What | Cap | Scope | When exceeded |
|---|---|---|---|
| Scheduled runs (including one-offs) | 100/hour | Account | Waits for the window to reset |
| Run now + API fires + re-arming a one-off | 30/hour | Per routine, shared | Action fails until reset |
| Run now + re-arming a one-off | 100/hour | Account | Action fails until reset |
| API fires | 100/hour | Account, separate from Run now | Action fails until reset |
| GitHub events | Per routine and per account caps | Events dropped |
If you hit your subscription limit, organisations with usage credits enabled carry on at metered rates; otherwise runs are rejected until the window resets. Individuals enable credits in their usage settings; on Team and Enterprise an admin does it for the organisation. If your subscription is paused, routines are put on hold and need turning back on afterwards.
Team and Enterprise Owners can switch routines off for everyone with the Routines toggle in the Claude Code admin settings. Existing routines stop and nobody can create new ones.
Troubleshooting
/schedule returns "Unknown command"
The command is hidden (the menu shows No commands match "/schedule") when a requirement is missing:
- Wrong kind of login. It needs a claude.ai subscription login. With a Console API key or an Anthropic profile or federation credential, submitting it shows a message saying
/scheduleis available with Claude for Enterprise and suggesting you ask your admin about migrating from API key access. With Bedrock, Vertex or Foundry you getUnknown command: /schedule. RemoveANTHROPIC_API_KEY,ANTHROPIC_AUTH_TOKENor anapiKeyHelpersetting, and switch off profiles, since all of these override a claude.ai login. - Signed out entirely. You see
/schedule requires a claude.ai subscription. Run /login to sign in with your claude.ai account. - Inside a cloud session. Manage routines on the web instead.
- Cloud sessions disabled by policy. Returns
Cloud sessions are disabled by your organization's policy. - Routines disabled by an Owner.
Unless routines or cloud sessions are disabled for your organisation, the web UI works regardless of your CLI setup.
"Routines are disabled by your organization's policy"
An Owner has turned off the Routines toggle. It is a server-side setting; local config cannot override it. From v2.1.227 it also hides /schedule.