@bybrawe/opencode-loop
v0.5.36
Published
Claude Code/Codex style /loop and experimental goal mode for OpenCode: heartbeat scheduler, idle-safe loops, scheduled commands, compact scheduling, verification, checkpoints, and persistent coding goals.
Maintainers
Readme
OpenCode Loop
Idle-safe auto-continue, scheduled OpenCode work, and background loops.
OpenCode Loop adds /loop, scheduled prompt/command/shell jobs, compact scheduling, verification/checkpoints, and the opencode-loopd background daemon.
Current stable release:
0.5.36.
Install or update
Recommended:
npx -y @bybrawe/opencode-loop@latestRun the same command again to update. Then fully restart OpenCode and verify:
/loop-help
/loop-doctorInstall/update Loop and the dedicated Goals companion together:
npx -y @bybrawe/opencode-loop@latest --with-goals --without-loop-goals--without-loop-goals removes only Loop's older experimental /loop-goal* command files. It keeps normal /loop, command/shell scheduling, daemon support, and the separate /goal plugin.
Install only Loop and skip companion network work:
npx -y @bybrawe/opencode-loop@latest --loop-onlyGlobal npm alternative:
npm install -g @bybrawe/opencode-loop@latest
opencode-loopTo uninstall:
npx -y @bybrawe/opencode-loop@latest --uninstallor, for a global install:
opencode-loop --uninstall
npm uninstall -g @bybrawe/opencode-loopProject Loop state under .opencode/opencode-loop/ is intentionally preserved by uninstall.
The mental model
Loop separates two ideas:
- When does work become due? Idle, a timer, a watch trigger, or
/loop-now. - When is it safe to dispatch? Only when the session is actually idle and no active tool/child work would overlap it.
A timer expiring does not intentionally inject a second model turn on top of an active one. Due work waits for idle.
Quick start
Keep saying “continue” whenever the assistant stops
/loop continueTurkish shorthand works naturally too:
/loop devam etExplicit equivalent:
/loop idle continueThis is an unlimited idle loop by default. When the assistant finishes and the session becomes safely idle, Loop sends the prompt again. When that turn finishes, it does the same again, until you pause/stop it or a configured limit is reached.
For very short continuation prompts such as continue, keep going, or devam et, Loop adds project-continuation guidance: treat the turn as continuation of the current repository/conversation, inspect relevant files/TODO/progress/git state as needed, find the next unfinished step, avoid redoing completed work, and verify meaningful changes when practical.
For project work, a strong default is:
/loop --safe --ask-never --progress-file progress.md devam etCreate a starter progress file first if needed:
/loop-initRepeat every 5 minutes
/loop every 5m continue the projectThis waits five minutes before the first run, then becomes due every five minutes. If the timer expires while OpenCode is busy, it waits for the next safe idle boundary rather than stacking prompts.
Do it once after 5 minutes
/loop after 5m continue onceAlias:
/loop in 5m continue onceThis is a one-shot delayed job. Five minutes passing makes it due; it still waits for idle before dispatching.
Legacy compact syntax remains supported
/loop 5m continue the projectFor backward compatibility, this form starts on the next safe idle boundary and then follows a five-minute interval.
Delay its first run explicitly:
/loop 5m --no-now continue the projectLegacy idle form is still valid:
/loop 0s continueFor the exact schedule truth table and edge cases, see docs/SCHEDULING.md.
Schedule summary
| Command | Meaning | First dispatch | Repeats |
|---|---|---|---|
| /loop continue | auto-continue on idle | next safe idle | every idle |
| /loop idle continue | explicit idle loop | next safe idle | every idle |
| /loop every 5m continue | recurring timer | after 5m, then idle | yes |
| /loop after 5m continue | delayed one-shot | after 5m, then idle | no |
| /loop in 5m continue | delayed one-shot alias | after 5m, then idle | no |
| /loop 5m continue | legacy recurring form | next safe idle | yes |
| /loop 5m --no-now continue | legacy delayed-first recurring | after 5m, then idle | yes |
| /loop 0s continue | legacy idle form | next safe idle | every idle |
Understand an unfamiliar project and keep going
A useful first loop for an unfamiliar repository is:
/loop-init
/loop --safe --ask-never --progress-file progress.md Understand the existing project architecture and current state first. Inspect relevant source, tests, docs, TODOs, git status, and recent work. Record useful state in progress.md, choose the next unfinished safe improvement, implement it, verify it, update progress.md, and continue from there on later idle turns.Once the project state is established, this is enough:
/loop --safe --ask-never --progress-file progress.md devam etThe short continuation form is deliberately interpreted as “resume this project”, not “invent a new task from scratch”.
Other job types
Schedule an OpenCode slash command:
/loop-command 200m /compactRun a real shell command:
/loop-shell 10m npm testAsk a recurring quality-control prompt:
/loop-ask 1h did you run tests, typecheck, and build? If not, run them and fix errors.Watch a path:
/loop --watch progress.md inspect the updated progress and continuePrompt, command, shell, compact, and watch jobs use the same idle-safe scheduling path but different execution transports.
Core commands
| Command | Purpose |
|---|---|
| /loop <prompt> | Add/update an unlimited idle prompt loop |
| /loop idle <prompt> | Explicit idle-loop form |
| /loop every <duration> <prompt> | Recurring timer, first run delayed |
| /loop after <duration> <prompt> | One-shot delayed prompt |
| /loop in <duration> <prompt> | Alias for after |
| /loop <duration> <prompt> | Backward-compatible compact interval form |
| /loop-command <interval> <slash-command> | Schedule an OpenCode command |
| /loop-cmd <interval> <slash-command> | Alias for /loop-command |
| /loop-ask <interval> <question> | Schedule a recurring check/question |
| /loop-shell <interval> <command> | Schedule a shell command |
| /loop-status | Show jobs plus schedule/state |
| /loop-now [id/name/all] | Mark selected jobs due now; still waits for idle |
| /loop-pause [id/name/all] | Pause jobs |
| /loop-resume [id/name/all] | Resume jobs |
| /loop-remove [id/name/all] | Remove jobs |
| /loop-clear | Remove all jobs for the current session |
| /loop-logs | Show recent scheduler/runtime events |
| /loop-doctor | Diagnose session/state/scheduling problems |
| /loop-init | Create a starter progress.md |
| /loop-export | Export current-session Loop state |
Useful flags
Lifecycle and limits:
--name <name>
--max-runs <n>
--max-runtime <duration>
--max-failures <n>
--timeout <duration>
--no-now
--nowSafety and verification:
--safe
--ask-never
--no-overlap
--verify "npm test"
--preflight "npm install"
--postrun "git status --short"
--pause-on-verify-failProject context:
--progress-file progress.md
--prompt-file loop-prompt.md
--include-file ARCHITECTURE.md
--batch 5
--compact-every 20
--watch progress.mdCheckpoints:
--checkpoint-only
--git-checkpoint--git-checkpoint may stage/commit work; use it only when intentional.
Status and diagnostics
/loop-status reports both the schedule definition and the current scheduler state. Examples:
schedule=every idle | state=waiting for idle
schedule=every 5m, first after 5m | state=due in 3m
schedule=once after 5m | state=due; waiting for idleThis is intentional: “due” is a clock fact, while “waiting for idle” is an admission/safety fact.
If a job says enabled but never runs
The problematic shape is typically:
enabled=true
paused=false
runCount=0
lastRunAt=0Some OpenCode TUI versions can leave session.status at busy/retry after a plugin command acknowledgement. Loop cross-checks that stale state against the chronological message tail before the first Loop run too. It recovers only when the latest assistant message is actually completed and no active tool/child work is known. A genuinely unfinished assistant turn, latest user turn, active tool, busy child, or unknown completion remains busy.
Recovery is logged as:
status-message-idle-recoveryBusy retries are also written as throttled deferred events so loop.log does not misleadingly contain only the original add line.
Use:
/loop-status
/loop-logs
/loop-doctorSession-bound state
Normal plugin Loop jobs are session-bound and stored under:
.opencode/opencode-loop/<session-id>.jsonA new OpenCode session does not silently inherit another session's jobs. /loop-doctor reports other persisted session files that still contain enabled jobs, including jobs that have never run, so an old loop is visible instead of appearing lost.
For work that must continue after the TUI/session closes, use opencode-loopd.
Loop and dedicated OpenCode Goals
They can be installed together. Recommended split:
- use
/goalfor durable outcome-driven work, evidence, verification, restart recovery, and semantic completion; - use
/loop,/loop-command,/loop-shell, andopencode-loopdfor scheduling/repetition/background infrastructure.
A prompt-producing Loop and an active dedicated /goal should not both own autonomous continuation of the same session. The runtime therefore blocks a new prompt Loop when it detects an active dedicated Goal for that session.
Recommended choices are to finish/pause the Goal or use a separate session. Advanced users can deliberately override the guard with:
/loop --allow-goal-overlap continueThat escape hatch can create competing autonomous turns; use it only when that is intentional.
Loop's older experimental /loop-goal* commands remain available for compatibility unless installed with --without-loop-goals. For new strongly verified Goal work, prefer:
npx -y @bybrawe/opencode-goal@latestRecommended development loop
/loop --name dev --ask-never --safe --no-overlap --batch 5 --compact-every 200m --checkpoint-only --progress-file progress.md Treat progress.md as the project state. Continue with the next unfinished TODO, implement it, mark completed items, add useful follow-up TODOs, run tests/lint/build when available, and keep going while work remains.Test/fix loop:
/loop --name testfix --ask-never --safe --verify "npm test" --max-failures 3 Continue from progress.md. If tests fail, analyze the failure, fix it, and run the tests again.Background daemon
The normal /loop plugin is session-bound. opencode-loopd pins one exact OpenCode session for daemon iterations and can keep scheduling outside the normal interactive Loop timer lifecycle.
opencode-loopd --project . --every 5m --prompt-file loop-prompt.mdImmediate daemon cadence:
opencode-loopd --project . --every 0s --prompt "continue from progress.md and implement the next unfinished TODO"Pin a session and limit runs:
opencode-loopd --project . --session ses_xxx --every 5m --max-runs 20 --timeout 30m --prompt-file loop-prompt.mdWindows Task Scheduler:
opencode-loopd install-task --project "C:\path\to\project" --every 10m --prompt-file loop-prompt.md --name OpenCodeLoop
opencode-loopd uninstall-task --name OpenCodeLoopState and checkpoints
Runtime state and logs:
.opencode/opencode-loop/
.opencode/opencode-loop/loop.logPatch checkpoints:
.opencode/opencode-loop/checkpoints/Add .opencode/opencode-loop/ to .gitignore if runtime state should not be committed.
Permissions
For unattended work, avoid permanently allowing every shell command. Grant routine read/edit/test operations while keeping destructive commands on ask/deny. --safe reduces risk but does not replace OpenCode permission configuration.
Package and compatibility
@bybrawe/opencode-loopStable package peer range:
@opencode-ai/plugin >=1.4.0 <2The repository contains experimental OpenCode 2 work, but the stable package does not claim full OpenCode 2 parity.
See docs/SCHEDULING.md for the scheduling contract and CHANGELOG.md for release history.
License
MIT
