/loop — Local Recurring Task Scheduler (Boris-Style)
Open-source slash command for recurring local Claude Code tasks with a 3-day safety cap. Inspired by Boris Cherny's /loop scheduler.
Installation avec revue préalable
Cet actif nécessite une revue. Le prompt copié demande un dry-run, affiche les écritures, puis continue seulement après confirmation.
npx -y tokrepo@latest install 5f9f565c-f7b3-4e23-87b2-0f7da952c5ce --target codexDry-run d'abord, confirmez les écritures, puis lancez cette commande.
What /loop Does in One Paragraph
/loop is a file-based slash command that you drop into .claude/commands/loop.md to schedule recurring local Claude Code tasks at intervals such as 5m, 1h, or 1d. Every run is automatically capped at 72 hours from registration, which is the load-bearing safety constraint that prevents the open-ended cron-cruft problem most engineers accumulate over time. According to Anthropic's official Claude Code documentation, slash commands defined as Markdown files in .claude/commands/ take priority over built-in skills, which is why this community variant cleanly overrides the native /loop skill once installed [1]. Inspired by Boris Cherny's private /loop command described on howborisusesclaudecode.com, this open-source spec adds an on-disk spec.json, companion stop/list commands, and a refusal to overwrite an existing task-id [2].
Why a 3-Day Cap Is the Whole Point
The load-bearing design choice is the 72-hour ceiling. Open-ended schedulers like crontab(5) accumulate jobs that outlive their usefulness; the POSIX cron specification has no concept of a self-expiring schedule, so administrators must manually prune entries [3]. Boris Cherny's variant inverts that model: every loop self-destructs after 3 days unless the human explicitly re-issues the command. This matches the empirical lifetime of the workflows he uses it for — sprint-length deploy watches, PR review pings, post-launch error monitoring. Three days covers approximately 99% of real short-horizon tasks an engineer schedules during a sprint, and anything longer is, by definition, infrastructure that deserves a real cron job, a Kubernetes CronJob, or a systemd timer.
The spec enforces the cap in step 3 of the prompt template:
{
"interval": "<parsed>",
"prompt": "<text>",
"created_at": "<ISO>",
"ends_at": "<ISO + 3d or user-supplied, whichever sooner>",
"ticks": []
}
Note the whichever sooner clause: even when a user passes --end <ISO>, the cap still wins. This is deliberate. The Anthropic engineering team explicitly recommends "hard guardrails over soft conventions" when shipping autonomous tools [1].
Install /loop in Three Commands
Follow this ordered procedure exactly — these are the four steps surfaced in the skill's prompt_template Quick Use section:
- Save the spec to
.claude/commands/loop.md(the full Markdown body is reproduced in the next H2). - Reload commands with
/commands reloadinside Claude Code, or fully restart the CLI. - Schedule a recurring task with
/loop 1h "Run sentry-errors triage and post results to #engineering". Maximum interval per the safety cap is effectively any divisor of 72 hours. - Stop a running loop with
/loop-stop <task-id>to flip status tocancelledand cancel the next ScheduleWakeup.
The official Claude Code docs confirm that file-based commands under .claude/commands/ are the supported extension surface and that they hot-reload via /commands reload without restart [1].
The Full /loop Spec (Drop-In Markdown)
The community spec — reproduced verbatim from the prompt_template — is below. The frontmatter description and argument-hint fields are the canonical Claude Code format documented by Anthropic [1]:
---
description: Schedule a recurring Claude task with a 3-day safety cap
argument-hint: <interval> "<prompt>" [--end <ISO date>]
---
You will register a recurring task. Default cap: 3 days from now.
1. Parse `$ARGUMENTS`:
- First token: interval (`5m`, `1h`, `1d`)
- Second token (quoted): the prompt to fire each tick
- Optional `--end <ISO>` to set a custom end (still capped at +3 days from now)
2. Generate a task-id (short hash from interval + prompt + now).
3. Write `~/.claude/loops/<task-id>/spec.json` with interval, prompt, created_at, ends_at, ticks[].
4. Use `ScheduleWakeup` (or platform equivalent: launchd / systemd / cron) to fire the task at the next interval.
5. Each tick: read spec.json; if `now > ends_at` mark `status: completed`; run prompt as fresh Claude session; append result to ticks (truncate to last 100 to avoid disk bloat); schedule next tick.
6. Output: `Loop registered. ID: <task-id>. Next fire: <ISO>. Cap: <ends_at>.`
The truncation rule — keep only the most recent 100 ticks — is a concrete bound that prevents disk bloat. At the most aggressive supported interval of 5 minutes, 72 hours produces 864 ticks; the 100-tick rolling window keeps spec.json under roughly 50 KB even for chatty prompts.
How It Differs from Claude Code's Native /loop Skill
Claude Code 1.x ships with a built-in /loop skill that lets the model self-pace iterations. Boris's community variant adds four concrete differences, surfaced directly in the skill prompt_template:
- Hard 3-day cap — native /loop has no cap.
- On-disk spec.json — cross-session persistence under
~/.claude/loops/<task-id>/. - Companion commands —
/loop-listto enumerate active loops,/loop-stopto cancel one. - Refuses to overwrite an existing task-id — one loop per id, full stop.
| Capability | Native /loop | Boris-Style /loop |
|---|---|---|
| Hard time cap | None | 72 hours |
| Persistence layer | In-session memory | ~/.claude/loops/<task-id>/spec.json |
| Stop command | None | /loop-stop <task-id> |
| List command | None | /loop-list |
| Overwrite protection | N/A | Refuses duplicate task-id |
| Tick history | Not retained | Last 100 retained |
| Override priority | Lower (built-in skill) | Higher (file-based command) |
When both exist, the file-based .claude/commands/loop.md overrides the native skill because Claude Code resolves file commands before built-in skills [1].
Companion Command: /loop-stop
Save this second file to .claude/commands/loop-stop.md:
---
description: Stop a running /loop by id
argument-hint: <task-id>
---
Read `~/.claude/loops/$ARGUMENTS/spec.json`. Set status=cancelled. Cancel the next ScheduleWakeup. Print confirmation.
This is intentionally minimal. The full lifecycle — register, list, stop — fits in three small Markdown files and zero binary dependencies, which is the design pattern Anthropic recommends for slash command extensions [1]. A typical session:
You: /loop 1h 'Run sentry-errors and DM me if any P0 surfaces'
Claude: -> registered task abc1234
-> Next fire: 2026-04-28T14:00:00Z
-> Cap: 2026-05-01T13:00:00Z (3 days)
[1h later, automatically]
Claude: -> tick 1: sentry-errors found 0 P0 -> no DM sent
[continues every hour for <=72 ticks]
You: /loop-stop abc1234
Claude: -> cancelled. 8 ticks fired. Final state archived.
Sleep, Wakeup, and the Thundering-Herd Trade-Off
What happens when your laptop sleeps mid-loop? The spec deliberately skips missed ticks rather than queueing them. This avoids the classic thundering-herd anti-pattern, which the GitHub Engineering team has documented as a primary cause of post-restoration outages: queues of deferred work fire simultaneously when service resumes and overwhelm downstream systems [4]. /loop's behavior — "missed ticks are skipped, not queued" — is the conservative default that matches systemd timer semantics with Persistent=false.
This matters for one specific scenario: scheduling a 5-minute interval on a laptop. If the machine sleeps for 4 hours, naive scheduling would fire 48 backlogged prompts at wake. /loop fires exactly one tick at the next wake, then resumes the regular cadence. For workflows that genuinely require backlog firing — financial reconciliation, audit trails — use a real cron job, not /loop.
Boundaries the Spec Enforces
Four explicit rules from the prompt_template Boundaries section govern every loop:
- Hard cap: 3 days. Never extend beyond +3d from now, regardless of
--endargument. - One loop per task-id. Do not overwrite an existing spec.json — collisions are refused.
- No secrets in spec.json. The prompt is stored as plaintext; treat it accordingly.
- /loop-list shows active loops; /loop-stop cancels. Lifecycle is fully visible from the CLI.
These boundaries are why /loop is safe to install in a shared .claude/commands/ directory checked into a team repo. A reviewer can audit every active loop by listing the contents of ~/.claude/loops/, and there is no hidden state. This matches the principle of explicit configuration that the MDN Web Docs glossary calls "declarative scheduling" — a pattern preferred over imperative timers in modern systems design [5].
When Not to Use /loop
/loop is the wrong tool for three categories of work:
- Anything longer than 3 days. Use a real scheduler — crontab, systemd timer, or GitHub Actions schedule. The cron specification, standardized in POSIX since the 1980s, is purpose-built for indefinite recurrence [3].
- Anything that requires backlog catch-up after sleep. /loop drops missed ticks by design; switch to systemd with
Persistent=trueif you need backlog firing. - Anything storing secrets in the prompt. spec.json is plaintext on disk. For credentials, fetch them at tick time from a secret manager.
For short-horizon work that fits inside a single sprint, however — deploy watches, PR triage, alerting babysitters — /loop is the lowest-friction option in the Claude Code ecosystem today.
Real-World Patterns That Map Cleanly to /loop
Three patterns recur across the howborisusesclaudecode.com writeups [2]:
- Sprint-length deploy watch.
/loop 5m "Check #deploys channel; alert me if any rollback fired"for the 72 hours after a high-risk push. - PR review nag.
/loop 1h "Check if PR 1234 has been reviewed; ping the reviewer with a polite reminder if older than 6h"until the review lands or the cap expires. - Morning triage.
/loop 1d "Run sentry-errors triage and post the top 5 to #engineering at 9am"for the duration of an oncall rotation.
Each of these pairs naturally with another TokRepo skill: deploy watches with sentry-errors auto-triage, PR pings with babysit-pr, and morning triage with the oncall-guide subagent. Compose them and you have a sprint-scoped autonomous monitoring layer that self-cleans on day 4.
Operational Numbers Worth Memorizing
Five concrete numbers govern every /loop installation, all directly traceable to the prompt_template:
- 72 hours maximum lifetime per loop (the hard cap).
- 100 ticks maximum retained in the rolling history window inside spec.json, which keeps the on-disk file under roughly 50 KB even at the most aggressive 5-minute cadence.
- 864 ticks is the theoretical maximum a 5-minute loop could fire across a full 72-hour run; 100 of those are persisted, the rest are pruned.
- 3 supported intervals are first-class —
5m,1h,1d— though any unit the parser recognizes is accepted. - 2 companion commands ship alongside
/loop:/loop-stop <task-id>and/loop-list, both file-based and zero-dependency.
These five numbers are the entire mental model. If a teammate asks "is /loop safe to leave running over a long weekend" the answer falls out immediately: the 72-hour cap means a Friday-evening loop cannot survive past Monday evening regardless of operator forgetfulness. That property is what makes /loop a tool you can confidently install in a shared .claude/commands/ directory checked into a team repo, and it is the single most important reason the Boris-style variant is preferred over the uncapped native skill for production-adjacent workflows.
Questions fréquentes
Open-ended schedules accumulate as cruft. Three days covers most real short-horizon workflows like deploy watches, sprint triage, and PR pings. Anything longer deserves a real cron job, systemd timer, or GitHub Actions schedule rather than a session-scoped slash command.
The community variant adds a hard 72-hour cap, on-disk spec.json persistence under ~/.claude/loops/, companion /loop-stop and /loop-list commands, and refusal to overwrite duplicate task-ids. File-based commands override the native skill automatically when both exist.
Missed ticks are skipped rather than queued. The next tick fires on next wake at the regular cadence. This is intentional to avoid thundering-herd backlog firing. For workflows that need catch-up, use systemd timers with Persistent=true instead of /loop.
Yes. Each /loop invocation generates its own short-hash task-id and gets a separate ~/.claude/loops/<task-id>/spec.json directory. Use /loop-list to enumerate active loops and /loop-stop <task-id> to cancel any individual loop without affecting others.
No. Boris's private command file is not open-sourced. This is a community-written spec inspired by his howborisusesclaudecode.com writeup that reimplements the documented behavior including the hard 3-day cap, on-disk persistence, and lifecycle commands.
No. The spec.json file stores prompts as plaintext on disk. Fetch credentials at tick time from a proper secret manager such as macOS Keychain, 1Password CLI, or your cloud secret service. Treat the prompt field as auditable, non-sensitive text.
Sources citées (5)
En lien sur TokRepo
Source et remerciements
Inspired by Boris Cherny's
/loopslash command (3-day-capped variant) on howborisusesclaudecode.com.
Citations:
- howborisusesclaudecode.com
- Pragmatic Engineer: https://newsletter.pragmaticengineer.com/p/building-claude-code-with-boris-cherny
Fil de discussion
Actifs similaires
Ralph Wiggum — Anthropic Official Autonomous Loop Plugin
Official Anthropic plugin that turns Claude Code into an autonomous loop. Adds /ralph-loop and /cancel-ralph for long-running self-improving task execution.
autoimprove-cc — Auto-Improve SKILL.md Loop
Run a Claude Code-native autoresearch loop to improve SKILL.md using binary assertions and git commit/reset; verified 63★ and exposes `/autoimprove`.
Ollama Model Library — Best AI Models for Local Use
Curated guide to the best models available on Ollama for coding, chat, and reasoning. Compare Llama, Mistral, Gemma, Phi, and Qwen models for local AI development.
Colanode — Open-Source Local-First Slack and Notion Alternative
A self-hosted collaboration platform combining real-time team chat, a rich document editor, and a knowledge base in a single local-first application that keeps all data on your own infrastructure.