How scheduled Claude actually works
A 24/7 loop is two separate pieces: a scheduler that fires on a cadence, and a headless Claude run (claude -p "…") that does the work and exits — no UI, no chat, just input → action → output. The headless command is the engine.
-p default.total_cost_usd per run.acceptEdits lets it write files without prompts for unattended runs.claude -p / Agent SDK usage on subscription plans draws from a separate monthly Agent SDK credit pool, not your interactive limits. Budget for it if you scale up loops.
The decision: where does it run?
Three options. The current setup is A. The Mac Studio sits on a desk on AC power, which matters for the recommendation.
| Approach | Always-on? | Effort | Cost | Best when |
|---|---|---|---|---|
| A. The Mac (launchd) — current | Only when Mac awake + online | none (built) | $0 extra | Local files/scripts, occasional gaps OK |
| B. Anthropic Routines (cloud) | Yes, truly | low | plan usage | Self-contained tasks on repos/connectors |
| C. A VPS (Linux server) | Yes, truly | medium | ~$5–10/mo | Custom 24/7 loops, full control, your secrets |
A. Stay on the Mac — fix the one weakness
The nine launchd jobs are real always-on infrastructure with one gap: launchd only fires when the Mac is awake, online, and logged in. A sleeping Mac Studio = missed runs. Two fixes:
sudo pmset -a disablesleep 1 stops it sleeping across reboots. Lighter touch: caffeinate -s prevents sleep only on AC power.StartCalendarInterval runs a job at next wake if the scheduled time passed while asleep — unlike cron, which just skips. So if the Mac stays awake, you're covered. Confirm time-of-day plists use StartCalendarInterval, not a cron-style StartInterval.pmset disablesleep 1 is genuinely enough for most loops. Don't move to a server if the Studio is always plugged in.
B. Anthropic Routines — cloud, zero infrastructure
Anthropic now runs scheduled Claude Code on their infrastructure. A routine = a saved prompt + repos + connectors, with triggers. Runs even with the laptop closed; nothing on your machine.
/schedule update. 1-hour minimum interval — faster is rejected..env secrets, and writing into john-labs/. Use Routines for "review this repo nightly"; keep local/VPS for "run my Python scraper and commit results".C. A VPS — your own always-on Linux box
A $5–10/mo Linux server (Hetzner, DigitalOcean) that's online 24/7 by definition — no sleep problem, independent of the Mac. The move if you want loops that never depend on the Studio being on, or to keep heavy/long jobs off the daily machine.
npm install -g @anthropic-ai/claude-code..bashrc: echo 'ANTHROPIC_API_KEY=sk-ant-...' > /opt/loops/.env && chmod 600 /opt/loops/.env. Keys never expire and need no browser. Note: API-key auth means no Remote Control on that box (that feature needs claude.ai OAuth) — fine for headless loops.Persistent=true to catch missed runs) once you outgrow cron. For long-running or interactive debugging, use tmux so sessions survive SSH disconnects.Hardening any unattended loop
Applies whether it runs on the Mac, Routines, or a VPS.
--allowedTools to the minimum (e.g. Bash(curl *),Read,Edit). Avoid --dangerously-skip-permissions on anything that can touch live ad accounts. The Telegram bot uses it — acceptable there because of the single-user lock, but don't copy that into an unattended scheduled job.total_cost_usd from --output-format json per run so a runaway loop is visible. Remember the June 15 Agent SDK credit change.chmod 600, never in shell history or committed. Keep the existing discipline (keys in tools/*.yaml / .env).Recommendation
Now: make the Studio reliable — sudo pmset -a disablesleep 1, verify time-of-day plists use StartCalendarInterval. That closes the only real gap for ~$0.
If you want a loop that runs even when the Studio is off (travel, reboots, isolation from the daily machine): stand up a small VPS and move the most critical loop (e.g. wsb-tracker) there.
For new self-contained tasks (nightly repo review): use Routines — no infra at all. Reach for the Agent SDK (Python/TS) only if a loop outgrows a shell one-liner and needs real control flow, structured outputs, or retries.