Repeat a task with /loop
/loop runs a task now and runs it again later, in the same conversation, until you stop it or the task decides another check is pointless. Give it an interval and it runs on that cadence. Leave the interval out and Command Code picks the next delay itself after every check.
It is for work that needs watching rather than building. "Check the deploy every 5 minutes." "Watch this pull request until CI is green." "Poll the migration until it finishes." If you want the agent to build toward something, use /goal instead.
/loop is a bundled skill on top of the scheduler. It shows up in the slash menu, and the cadence and task are parsed by code, so the model never has to guess the schedule.
Basic usage
| Invocation | Behavior |
|---|---|
/loop 5m check the deploy | Runs the task now, then every five minutes. |
/loop check the deploy every 2 hours | Same thing, with the cadence written at the end of the task. |
/loop check the deploy | Runs now, then picks the next delay after every check. |
/loop 15m | Runs the default loop task now and every 15 minutes. |
/loop | Runs the default loop task now, self-paced. |
- The task runs once, immediately, in the current turn. Nobody waits for the first interval to pass.
- A scheduled task is created. A fixed loop becomes a recurring task in the conversation. A self-paced loop becomes a single pending wakeup, and each iteration replaces it.
- When the schedule fires, the task text reaches the agent fenced as data. It cannot override higher-priority instructions or widen permission for destructive or external actions. Tool calls inside an iteration still go through your normal permission mode.
- The loop ends when the work is done or you stop it. A self-paced loop can stop itself. A fixed loop keeps firing until you cancel it or it hits its seven-day lifetime.
Put an interval before the task, or end the task with an every ... clause:
Fixed loops
Intervals accept s, m, h, and d. The trailing form also takes spelled-out units such as minutes or hours.
Fixed loops run on cron. Cron has one-minute resolution and wants a step that divides evenly into the hour or the day, so the interval you ask for is snapped to the closest clean cadence. The confirmation tells you when that happened.
| Requested | Runs as |
|---|---|
| Seconds | Rounded up to whole minutes, then treated like minutes. |
| Minutes or hours | The nearest clean step. Minutes are 1, 2, 3, 4, 5, 6, 10, 12, 15, 20, or 30. Hours are 1, 2, 3, 4, 6, 8, or 12. Past that it becomes once a day. |
| 24 hours or 1 day | Once a day at midnight. |
| 2 to 31 days | Every N days, on cron's day-of-month field. |
Ties round up. 8m becomes every 10 minutes and 45m becomes every hour. Multi-day steps follow the calendar and start over on the first of each month, so /loop 10d fires on the 1st, 11th, 21st, and 31st.
Fixed loops get a small deterministic delay so many sessions do not hit the API at the same instant. A recurring task can fire up to 10% of its interval late, capped at 15 minutes. The offset is derived from the task id, so it survives a resume.
Recurring tasks expire seven days after creation. An expiring loop fires one last time and is removed. If a task has to run longer than that, re-create the loop or use an external scheduler.
Skip the interval and the agent decides when to look again:
Self-paced loop
Each iteration ends by picking a delay between one minute and one hour, with a one-line reason that shows up in the iteration result. A build that is still moving gets checked soon. A quiet one gets left alone for longer. The new delay replaces the pending wakeup rather than adding a second one, and it is not jittered.
| Rule | Detail |
|---|---|
| One per conversation | Starting another self-paced loop replaces the pending one. |
| Quiet checks are counted | An iteration that changed nothing is marked quiet. The next wakeup reports the streak, which nudges the agent to back off while nothing is happening. |
| It stops itself | When the task is complete, or another check cannot help, the loop ends with a final report. |
| Safety check on omission | If an iteration ends without scheduling the next check or stopping, Command Code schedules one 20-minute safety check. A second omission ends the loop. |
A bare /loop, or /loop <interval> with no task, runs a built-in maintenance task. It continues unfinished work from the conversation, then checks the current branch for review feedback, failed checks, or conflicts it can act on. If nothing is pending it makes one bounded quality pass on the work already in scope. It does not authorize unrelated work or widen permission for destructive actions.
Replace that task with a markdown file:
| Path | Scope |
|---|---|
.commandcode/loop.md | The directory Command Code was started in, the same place settings.json is read from. Wins when both exist. |
~/.commandcode/loop.md | Fallback for projects without their own file. |
The file is read again on every default-task iteration, so an edit applies to the next check without restarting the loop. Empty files are ignored. Content past 25,000 bytes is cut off. A task you type into /loop yourself never reads either file.
Example loop.md
| Action | Effect |
|---|---|
| Press Esc | Cancels every fixed and self-paced loop in the conversation. Reminders and other schedules are left alone. |
| Press Esc twice | Needed when something else is open. The first Esc closes a permission prompt, question, transcript view, banner, or overlay and leaves loops scheduled. The second Esc, at the idle prompt, cancels them. |
| Press Ctrl + C during a turn | Interrupts the turn and cancels the conversation's loops with it. |
| Let it stop itself | A self-paced iteration ends the loop as soon as the task is complete. |
| Ask | "cancel the deploy check" runs cron_delete on the loop's id. |
The feed shows Loop stopped · N scheduled tasks cancelled when loops are cancelled. If you do not see that line after pressing Esc, the loops are still running. This matters when a loop iteration raised a permission prompt: Esc denies the prompt but does not stop the loop. A fire that was queued behind a busy turn is re-checked before it runs, so a cancelled loop never sneaks in one last iteration.
To see what is scheduled, ask "what scheduled tasks do I have?". cron_list returns fixed and self-paced loops with their eight-character ids. A conversation holds at most 50 scheduled tasks.
Loops belong to the conversation. Closing Command Code pauses them. --resume or --continue brings back loops that are still inside their seven-day lifetime. A self-paced loop that was mid-iteration when the session closed comes back as a pending 20-minute safety check. A fresh conversation never runs another conversation's loops.
The scheduler checks once a second and only submits a due iteration between turns. If the agent is busy, one due event waits for the turn to finish. Missed intervals do not pile up into a burst of catch-up runs. A scheduled /skill reference runs only when that skill is enabled and allows model invocation.
/loop needs an interactive, top-level conversation. It is unavailable in these places:
| Surface | Behavior |
|---|---|
Headless runs (-p) | /loop is refused with a notice and no task is created. Use an external scheduler to run a headless prompt on a cadence. |
| Sub-agents | schedule_wakeup is withheld, so a sub-agent cannot start or continue a self-paced loop. |
| Plan mode | Scheduling is a write action. /loop says it cannot start and creates no task. Leave plan mode and run it again. |
| Environment variable | Effect |
|---|---|
COMMANDCODE_DISABLE_CRON=1 | Disables /loop and every scheduler tool. Read at launch, so loops restored into a resumed conversation do not fire while it is set. |
Fixed loop
The task runs once now, then every 20 minutes. Resume the conversation to keep it going after a restart, press Esc to stop it, or ask Command Code to cancel it by id.
Self-paced loop
The first checks come fast while the rollout is moving. Once the deploy is healthy and the smoke test passes, the loop stops itself and reports.
Default task on a cadence
Every hour, Command Code continues unfinished work, tends review comments and CI on the current branch, then makes one bounded quality pass. Drop a .commandcode/loop.md in the project to change what the bare command does.
- Learn the scheduler tools underneath in Background Tasks
- Give the agent a standing objective with
/goal - Let a loop run unattended in Auto-Accept Mode
- Bring loops back after a restart with sessions
- Join our Discord community for feedback, requests, and support.