Internal Ops · 03 · Scheduled ops & reportingLesson 2 of 4
Scheduling: making it run without you
- Schedule headless Claude Code jobs reliably
- Pick the right runner (local, Actions, server)
The three-tier menu
Everything you have built so far runs when you run it. This lesson removes you from the loop: by the end, the Monday KPI report arrives in Slack by itself. This is rung three of the ladder - the skill becomes a scheduled Routine. There are exactly three ways to schedule Claude Code in 2026, and picking the right one is most of the skill.
- Cloud Routines (still a research preview as of September 2026) - runs on Anthropic's cloud with your laptop closed. Triggers: a schedule (minimum 1-hour interval, plus one-off runs like
/schedule tomorrow at 9am, ...that do not count against the daily cap), an API endpoint, or GitHub events. Works from a fresh clone of your repo and your claude.ai connectors - no local files, and no localclaude mcp addservers either; a server declared in a committed.mcp.jsondoes work for a single-repo routine. By default it pushes toclaude/-prefixed branches. Best for: "every weekday at 8am, build the KPI report and post it to Slack." - Desktop scheduled tasks - runs on your machine while the app is open, minimum 1-minute intervals, full access to local files. Best for: a morning briefing built from your local brain repo.
- claude -p plus cron or GitHub Actions - headless runs on your server or CI. Full control, any trigger, CI secrets. Best for: anything that needs to be bulletproof, audited, or wired into existing infrastructure.
- /loop - not a tier, but the thing people reach for a tier too early.
/loop 5m <prompt>re-runs a prompt in your open session every five minutes;/loop <prompt>self-paces between one minute and an hour. Recurring loops expire after 7 days and a session holds at most 50 scheduled tasks; Esc stops a self-paced loop, and a fixed-interval one runs until you ask Claude to cancel it. Right for "watch this import until it lands and tell me"; wrong for anything the team depends on, because it dies with your session.
The progression for an ops team: prove the job manually, then as a Desktop task, then promote it to a Routine or CI when it has earned autonomy. Each tier removes a layer of supervision, so each promotion should be deliberate.
Create a Routine with /schedule
- Get the brain repo on GitHub if it is not already - Routines run against a fresh clone of a repo, not your local disk.
- In Claude Code, run /schedule (or go to claude.ai/code/routines). Name the routine, pick the repo, and set the schedule - weekdays 8am for the KPI report.
- Write the prompt as if briefing a capable stranger: "Run the weekly-report skill. Post the result to #ops-reports. If any step fails, still post, stating what failed." The routine has no memory of your sessions - only the repo and the prompt.
- Review the attached connectors. Routines include your claude.ai connectors BY DEFAULT - remove every one this job does not need. The KPI routine needs Slack and Stripe, not your Gmail.
- Run it once manually (
/schedule run, or the Routines page), then open the run transcript and read it end to end before trusting the schedule./schedule listand/schedule updatemanage routines from the CLI;/routinesis an alias.
Operational facts worth knowing: routines run fully autonomously - no permission prompts - so scope them with connectors and the repo, not with hope. There is a daily run cap (past it, runs can bill to usage credits if your org has them on, so the cap is not a spend ceiling), admins can disable Routines org-wide, and the feature is still a research preview as of September 2026, so expect movement.
Desktop tasks: the local tier
Desktop scheduled tasks (Desktop app, then Routines, then New, then Local) are the right tier when the job needs your local files. The first run is supervised - you approve each permission, and those approvals are remembered as "always allow" for future runs. The prompt is stored as a skill at ~/.claude/scheduled-tasks/<name>/SKILL.md, so you can edit it like any other skill.
One behavior to design for: if your machine was asleep at trigger time, a missed task gets exactly one catch-up run on wake, covering the last 7 days. So write prompts time-defensively: "Summarize only TODAY's data. If running after 5pm, just post what was missed instead of the full report." The prompt should behave well whenever it actually fires, not just when it fires on time.
- Use Desktop tasks for: personal briefings, local-file digests, anything still in its supervised trial period.
- Do not use them for: jobs the team depends on. A laptop is not infrastructure - promote team-critical jobs to a Routine or CI.
- The 1-minute minimum interval makes them good for fast iteration: test a prompt on a 5-minute loop, then move it to its real schedule.
Headless: claude -p as a building block
The third tier is Claude Code as a command-line tool any scheduler can call - cron on a server, GitHub Actions, or one step inside an n8n flow.
claude -p "Run the weekly-report skill and write the output \
to reports/" \
--permission-mode acceptEdits \
--permission-prompts none \
--allowedTools "Read,Write,Grep,Glob,Bash(python *)" \
--output-format json
# The JSON result includes total_cost_usd (with a per-model
# breakdown) and session_id - log both on every scheduled run.- -p starts in Manual permission mode on every plan, unlike interactive sessions, so anything outside the allowlist and the mode is denied. --permission-prompts none (v2.1.259+) also tells Claude not to retry a denied action and keeps the run from waiting on a permission host such as an SDK callback, so it continues to its report.
- --allowedTools whitelists exactly what the job may do - the headless equivalent of your settings.json.
- --output-format json returns a machine-readable result including total_cost_usd and a per-model breakdown; --json-schema gets you typed structured output for downstream steps, and now errors on an invalid schema instead of silently ignoring it.
- --bare skips local hooks, MCP, and memory for reproducible scripted runs - recommended for CI, and slated to become the default.
- For GitHub Actions, anthropics/claude-code-action@v1 with an on: schedule: cron trigger is the packaged version of all this.
Event triggers: jobs that fire on webhooks
Schedules cover "every Monday." Webhooks cover "the moment it happens." Routines expose an API trigger for exactly this: POST to the routine's /fire endpoint with a bearer token (and the beta header experimental-cc-routine-2026-04-01), passing the event body as text.
This is the no-server webhook receiver: point a Typeform, Calendly, or Fireflies webhook at the /fire URL - directly, or through one Zapier step if the payload needs reshaping - and the lead-triage flow you sketched in module two becomes live and event-driven. Form submitted, routine fires, lead enriched and routed, Slack alerted, nothing running on your machine.
Do this now
Sources and further reading
Want us to set it up with you, end to end?
Three one-on-one sessions. We train you on your real stack and build your first agents together, until you can run it yourself. You keep everything.