@bybrawe/opencode-loop 0.5.32 → 0.5.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/README.md +197 -283
- package/commands/loop.md +1 -1
- package/package.json +3 -3
- package/scripts/action-dispatch-test.mjs +117 -0
- package/scripts/comprehensive-test.mjs +1 -1
- package/scripts/host-loop-canary.mjs +8 -3
- package/scripts/loop-command-handlers-test.mjs +33 -4
- package/scripts/loop-registration-test.mjs +77 -3
- package/scripts/run-admission-test.mjs +133 -0
- package/scripts/run-finalization-test.mjs +119 -0
- package/scripts/schedule-policy-test.mjs +114 -0
- package/scripts/schedule-syntax-test.mjs +75 -0
- package/scripts/session-status-idle-recovery-test.mjs +44 -0
- package/src/index.js +916 -473
- package/src/source/core/continuation.js +20 -0
- package/src/source/core/jobs.js +3 -0
- package/src/source/core/schedule-syntax.js +93 -0
- package/src/source/opencode/loop-commands.js +39 -30
- package/src/source/opencode/loop-registration.js +40 -3
- package/src/source/runtime/action-dispatch.js +108 -0
- package/src/source/runtime/companion-goal.js +37 -0
- package/src/source/runtime/executor.js +55 -228
- package/src/source/runtime/goal-evidence.js +39 -0
- package/src/source/runtime/goal-policy.js +1 -1
- package/src/source/runtime/goal-prompt.js +53 -0
- package/src/source/runtime/goal-report.js +52 -0
- package/src/source/runtime/goal-runtime.js +9 -141
- package/src/source/runtime/loop-diagnostics.js +45 -0
- package/src/source/runtime/run-admission.js +121 -0
- package/src/source/runtime/run-finalization.js +100 -0
- package/src/source/runtime/schedule-policy.js +80 -0
- package/src/source/runtime/scheduler-diagnostics.js +30 -0
- package/src/source/runtime/scheduler.js +10 -23
- package/src/source/runtime/session-status.js +28 -4
package/README.md
CHANGED
|
@@ -1,330 +1,261 @@
|
|
|
1
1
|
# OpenCode Loop
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**Idle-safe auto-continue, scheduled OpenCode work, and background loops.**
|
|
4
4
|
|
|
5
|
-
OpenCode Loop adds `/loop`, scheduled prompt/command/shell jobs, compact scheduling,
|
|
5
|
+
OpenCode Loop adds `/loop`, scheduled prompt/command/shell jobs, compact scheduling, verification/checkpoints, and the `opencode-loopd` background daemon.
|
|
6
6
|
|
|
7
|
-
> **Current release: `0.5.
|
|
7
|
+
> **Current stable release: `0.5.34`.**
|
|
8
8
|
|
|
9
9
|
## Install or update
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
### Option 1 — one-command install with `npx` (recommended)
|
|
11
|
+
Recommended:
|
|
14
12
|
|
|
15
13
|
```bash
|
|
16
14
|
npx -y @bybrawe/opencode-loop@latest
|
|
17
15
|
```
|
|
18
16
|
|
|
19
|
-
Run the same command again
|
|
20
|
-
|
|
21
|
-
Install Loop and Goals together from scratch with:
|
|
17
|
+
Run the same command again to update. Then **fully restart OpenCode** and verify:
|
|
22
18
|
|
|
23
|
-
```
|
|
24
|
-
|
|
19
|
+
```text
|
|
20
|
+
/loop-help
|
|
21
|
+
/loop-doctor
|
|
25
22
|
```
|
|
26
23
|
|
|
27
|
-
|
|
24
|
+
Install/update Loop and the dedicated Goals companion together:
|
|
28
25
|
|
|
29
26
|
```bash
|
|
30
27
|
npx -y @bybrawe/opencode-loop@latest --with-goals --without-loop-goals
|
|
31
28
|
```
|
|
32
29
|
|
|
33
|
-
`--without-loop-goals` removes only Loop's
|
|
30
|
+
`--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.
|
|
34
31
|
|
|
35
|
-
|
|
32
|
+
Install only Loop and skip companion network work:
|
|
36
33
|
|
|
37
34
|
```bash
|
|
38
35
|
npx -y @bybrawe/opencode-loop@latest --loop-only
|
|
39
36
|
```
|
|
40
37
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
### Option 2 — install with npm
|
|
44
|
-
|
|
45
|
-
Install OpenCode Loop globally so its installer and daemon commands are available:
|
|
38
|
+
Global npm alternative:
|
|
46
39
|
|
|
47
40
|
```bash
|
|
48
41
|
npm install -g @bybrawe/opencode-loop@latest
|
|
49
42
|
opencode-loop
|
|
50
43
|
```
|
|
51
44
|
|
|
52
|
-
To
|
|
45
|
+
To uninstall:
|
|
53
46
|
|
|
54
47
|
```bash
|
|
55
|
-
|
|
56
|
-
opencode-loop
|
|
48
|
+
npx -y @bybrawe/opencode-loop@latest --uninstall
|
|
57
49
|
```
|
|
58
50
|
|
|
59
|
-
|
|
51
|
+
or, for a global install:
|
|
60
52
|
|
|
61
53
|
```bash
|
|
62
|
-
opencode-loop --
|
|
54
|
+
opencode-loop --uninstall
|
|
55
|
+
npm uninstall -g @bybrawe/opencode-loop
|
|
63
56
|
```
|
|
64
57
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
```bash
|
|
68
|
-
opencode-loop --with-goals --without-loop-goals
|
|
69
|
-
```
|
|
58
|
+
Project Loop state under `.opencode/opencode-loop/` is intentionally preserved by uninstall.
|
|
70
59
|
|
|
71
|
-
|
|
60
|
+
## The mental model
|
|
72
61
|
|
|
73
|
-
|
|
62
|
+
Loop separates two ideas:
|
|
74
63
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
- installs the tool-denied, hidden `opencode-loop-local` acknowledgement subagent used only by Loop's bound local command definitions;
|
|
78
|
-
- keeps an existing npm plugin entry pinned to the installer’s exact version to avoid stale OpenCode package-cache resolution;
|
|
79
|
-
- removes duplicate old local Loop plugin copies when the package entry is authoritative;
|
|
80
|
-
- refreshes OpenCode Goals through **Goals' own official installer** when an existing managed Goals installation is detected;
|
|
81
|
-
- can explicitly install both packages with `--with-goals`, skip companion network work with `--loop-only`, or omit the packaged experimental `/loop-goal*` command files with `--without-loop-goals`.
|
|
64
|
+
1. **When does work become due?** Idle, a timer, a watch trigger, or `/loop-now`.
|
|
65
|
+
2. **When is it safe to dispatch?** Only when the session is actually idle and no active tool/child work would overlap it.
|
|
82
66
|
|
|
83
|
-
|
|
67
|
+
A timer expiring does **not** intentionally inject a second model turn on top of an active one. Due work waits for idle.
|
|
84
68
|
|
|
85
|
-
|
|
86
|
-
/loop-help
|
|
87
|
-
/loop-doctor
|
|
88
|
-
```
|
|
69
|
+
## Quick start
|
|
89
70
|
|
|
90
|
-
|
|
71
|
+
### Keep saying “continue” whenever the assistant stops
|
|
91
72
|
|
|
92
73
|
```text
|
|
93
|
-
/
|
|
74
|
+
/loop continue
|
|
94
75
|
```
|
|
95
76
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
If you use the `npx` installer:
|
|
77
|
+
Turkish shorthand works naturally too:
|
|
99
78
|
|
|
100
|
-
```
|
|
101
|
-
|
|
79
|
+
```text
|
|
80
|
+
/loop devam et
|
|
102
81
|
```
|
|
103
82
|
|
|
104
|
-
|
|
83
|
+
Explicit equivalent:
|
|
105
84
|
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
npm uninstall -g @bybrawe/opencode-loop
|
|
85
|
+
```text
|
|
86
|
+
/loop idle continue
|
|
109
87
|
```
|
|
110
88
|
|
|
111
|
-
|
|
89
|
+
This 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.
|
|
112
90
|
|
|
113
|
-
|
|
91
|
+
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.
|
|
114
92
|
|
|
115
|
-
|
|
93
|
+
For project work, a strong default is:
|
|
116
94
|
|
|
117
95
|
```text
|
|
118
|
-
|
|
96
|
+
/loop --safe --ask-never --progress-file progress.md devam et
|
|
119
97
|
```
|
|
120
98
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
## Quick start
|
|
124
|
-
|
|
125
|
-
Auto-continue whenever OpenCode becomes idle:
|
|
99
|
+
Create a starter progress file first if needed:
|
|
126
100
|
|
|
127
101
|
```text
|
|
128
|
-
/loop
|
|
102
|
+
/loop-init
|
|
129
103
|
```
|
|
130
104
|
|
|
131
|
-
|
|
105
|
+
### Repeat every 5 minutes
|
|
132
106
|
|
|
133
107
|
```text
|
|
134
|
-
/loop 5m continue the project
|
|
108
|
+
/loop every 5m continue the project
|
|
135
109
|
```
|
|
136
110
|
|
|
137
|
-
|
|
111
|
+
This 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.
|
|
112
|
+
|
|
113
|
+
### Do it once after 5 minutes
|
|
138
114
|
|
|
139
115
|
```text
|
|
140
|
-
/loop 5m
|
|
116
|
+
/loop after 5m continue once
|
|
141
117
|
```
|
|
142
118
|
|
|
143
|
-
|
|
119
|
+
Alias:
|
|
144
120
|
|
|
145
121
|
```text
|
|
146
|
-
/loop
|
|
122
|
+
/loop in 5m continue once
|
|
147
123
|
```
|
|
148
124
|
|
|
149
|
-
|
|
125
|
+
This is a one-shot delayed job. Five minutes passing makes it due; it still waits for idle before dispatching.
|
|
126
|
+
|
|
127
|
+
### Legacy compact syntax remains supported
|
|
150
128
|
|
|
151
129
|
```text
|
|
152
|
-
/loop
|
|
130
|
+
/loop 5m continue the project
|
|
153
131
|
```
|
|
154
132
|
|
|
155
|
-
|
|
133
|
+
For backward compatibility, this form starts on the next safe idle boundary and then follows a five-minute interval.
|
|
134
|
+
|
|
135
|
+
Delay its first run explicitly:
|
|
156
136
|
|
|
157
137
|
```text
|
|
158
|
-
/loop
|
|
138
|
+
/loop 5m --no-now continue the project
|
|
159
139
|
```
|
|
160
140
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
Use Loop when the important question is **“what should run again, and when?”**
|
|
141
|
+
Legacy idle form is still valid:
|
|
164
142
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
- recurring coding prompts;
|
|
169
|
-
- progress.md / TODO workflows;
|
|
170
|
-
- scheduled `/compact` or other OpenCode commands;
|
|
171
|
-
- recurring tests/lint/build shell jobs;
|
|
172
|
-
- retry/fix loops with verification;
|
|
173
|
-
- patch checkpoints;
|
|
174
|
-
- maximum run/runtime/failure limits;
|
|
175
|
-
- prompt-file workflows;
|
|
176
|
-
- background work through `opencode-loopd`;
|
|
177
|
-
- Windows Task Scheduler integration.
|
|
143
|
+
```text
|
|
144
|
+
/loop 0s continue
|
|
145
|
+
```
|
|
178
146
|
|
|
179
|
-
|
|
147
|
+
For the exact schedule truth table and edge cases, see [docs/SCHEDULING.md](./docs/SCHEDULING.md).
|
|
180
148
|
|
|
181
|
-
##
|
|
149
|
+
## Schedule summary
|
|
182
150
|
|
|
183
|
-
|
|
151
|
+
| Command | Meaning | First dispatch | Repeats |
|
|
152
|
+
|---|---|---|---|
|
|
153
|
+
| `/loop continue` | auto-continue on idle | next safe idle | every idle |
|
|
154
|
+
| `/loop idle continue` | explicit idle loop | next safe idle | every idle |
|
|
155
|
+
| `/loop every 5m continue` | recurring timer | after 5m, then idle | yes |
|
|
156
|
+
| `/loop after 5m continue` | delayed one-shot | after 5m, then idle | no |
|
|
157
|
+
| `/loop in 5m continue` | delayed one-shot alias | after 5m, then idle | no |
|
|
158
|
+
| `/loop 5m continue` | legacy recurring form | next safe idle | yes |
|
|
159
|
+
| `/loop 5m --no-now continue` | legacy delayed-first recurring | after 5m, then idle | yes |
|
|
160
|
+
| `/loop 0s continue` | legacy idle form | next safe idle | every idle |
|
|
184
161
|
|
|
185
|
-
|
|
162
|
+
## Understand an unfamiliar project and keep going
|
|
186
163
|
|
|
187
|
-
|
|
164
|
+
A useful first loop for an unfamiliar repository is:
|
|
188
165
|
|
|
189
|
-
```
|
|
190
|
-
|
|
166
|
+
```text
|
|
167
|
+
/loop-init
|
|
168
|
+
/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.
|
|
191
169
|
```
|
|
192
170
|
|
|
193
|
-
|
|
171
|
+
Once the project state is established, this is enough:
|
|
194
172
|
|
|
195
|
-
```
|
|
196
|
-
|
|
173
|
+
```text
|
|
174
|
+
/loop --safe --ask-never --progress-file progress.md devam et
|
|
197
175
|
```
|
|
198
176
|
|
|
199
|
-
|
|
177
|
+
The short continuation form is deliberately interpreted as “resume this project”, not “invent a new task from scratch”.
|
|
200
178
|
|
|
201
|
-
|
|
202
|
-
npx -y @bybrawe/opencode-goal@latest
|
|
203
|
-
```
|
|
179
|
+
## Other job types
|
|
204
180
|
|
|
205
|
-
|
|
181
|
+
Schedule an OpenCode slash command:
|
|
206
182
|
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
opencode-goal
|
|
183
|
+
```text
|
|
184
|
+
/loop-command 200m /compact
|
|
210
185
|
```
|
|
211
186
|
|
|
212
|
-
|
|
187
|
+
Run a real shell command:
|
|
213
188
|
|
|
214
189
|
```text
|
|
215
|
-
/
|
|
216
|
-
/goal status
|
|
217
|
-
/goal contract
|
|
218
|
-
/goal audit
|
|
190
|
+
/loop-shell 10m npm test
|
|
219
191
|
```
|
|
220
192
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
Yes. `@bybrawe/opencode-loop` and `@bybrawe/opencode-goal` use different package names, commands, and project-state directories, so they can coexist in one OpenCode installation.
|
|
224
|
-
|
|
225
|
-
Recommended split:
|
|
226
|
-
|
|
227
|
-
- use **`/goal`** for persistent, strongly verified outcome completion;
|
|
228
|
-
- use **`/loop`**, `/loop-command`, `/loop-shell`, and `opencode-loopd` for scheduling/repetition/background infrastructure.
|
|
229
|
-
|
|
230
|
-
Do **not** run Loop’s `/loop-goal` and OpenCode Goals `/goal` against the same work in the same session. Both can autonomously continue on idle boundaries and can compete to start turns. Use `--without-loop-goals` when you want to remove that legacy command surface entirely.
|
|
231
|
-
|
|
232
|
-
Likewise, avoid leaving a prompt-producing `/loop ...` job continuously injecting agent turns into a session while an OpenCode Goal is actively continuing. Use separate sessions or pause/remove that prompt loop until the Goal is done. Scheduled shell/command jobs should also be chosen carefully so they do not race files or verification.
|
|
233
|
-
|
|
234
|
-
Install both with one `npx` command:
|
|
193
|
+
Ask a recurring quality-control prompt:
|
|
235
194
|
|
|
236
|
-
```
|
|
237
|
-
|
|
195
|
+
```text
|
|
196
|
+
/loop-ask 1h did you run tests, typecheck, and build? If not, run them and fix errors.
|
|
238
197
|
```
|
|
239
198
|
|
|
240
|
-
|
|
199
|
+
Watch a path:
|
|
241
200
|
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
opencode-loop --with-goals
|
|
201
|
+
```text
|
|
202
|
+
/loop --watch progress.md inspect the updated progress and continue
|
|
245
203
|
```
|
|
246
204
|
|
|
247
|
-
|
|
205
|
+
Prompt, command, shell, compact, and watch jobs use the same idle-safe scheduling path but different execution transports.
|
|
248
206
|
|
|
249
207
|
## Core commands
|
|
250
208
|
|
|
251
209
|
| Command | Purpose |
|
|
252
210
|
|---|---|
|
|
253
|
-
| `/loop <
|
|
254
|
-
| `/loop
|
|
211
|
+
| `/loop <prompt>` | Add/update an unlimited idle prompt loop |
|
|
212
|
+
| `/loop idle <prompt>` | Explicit idle-loop form |
|
|
213
|
+
| `/loop every <duration> <prompt>` | Recurring timer, first run delayed |
|
|
214
|
+
| `/loop after <duration> <prompt>` | One-shot delayed prompt |
|
|
215
|
+
| `/loop in <duration> <prompt>` | Alias for `after` |
|
|
216
|
+
| `/loop <duration> <prompt>` | Backward-compatible compact interval form |
|
|
217
|
+
| `/loop-command <interval> <slash-command>` | Schedule an OpenCode command |
|
|
255
218
|
| `/loop-cmd <interval> <slash-command>` | Alias for `/loop-command` |
|
|
256
|
-
| `/loop-ask <interval> <question>` | Schedule recurring
|
|
257
|
-
| `/loop-shell <interval> <command>` | Schedule a
|
|
258
|
-
| `/loop-status` | Show
|
|
259
|
-
| `/loop-now [id/name/all]` |
|
|
219
|
+
| `/loop-ask <interval> <question>` | Schedule a recurring check/question |
|
|
220
|
+
| `/loop-shell <interval> <command>` | Schedule a shell command |
|
|
221
|
+
| `/loop-status` | Show jobs plus schedule/state |
|
|
222
|
+
| `/loop-now [id/name/all]` | Mark selected jobs due now; still waits for idle |
|
|
260
223
|
| `/loop-pause [id/name/all]` | Pause jobs |
|
|
261
224
|
| `/loop-resume [id/name/all]` | Resume jobs |
|
|
262
225
|
| `/loop-remove [id/name/all]` | Remove jobs |
|
|
263
|
-
| `/loop-clear` | Remove all current
|
|
264
|
-
| `/loop-
|
|
226
|
+
| `/loop-clear` | Remove all jobs for the current session |
|
|
227
|
+
| `/loop-logs` | Show recent scheduler/runtime events |
|
|
228
|
+
| `/loop-doctor` | Diagnose session/state/scheduling problems |
|
|
265
229
|
| `/loop-init` | Create a starter `progress.md` |
|
|
266
|
-
| `/loop-export` | Export Loop state
|
|
267
|
-
| `/loop-goal <objective>` | Start the older experimental Loop Goal Mode when those optional legacy command files are installed |
|
|
268
|
-
|
|
269
|
-
## Intervals and job types
|
|
270
|
-
|
|
271
|
-
Examples:
|
|
272
|
-
|
|
273
|
-
```text
|
|
274
|
-
0s run whenever OpenCode becomes idle
|
|
275
|
-
5m run every 5 minutes when idle
|
|
276
|
-
200m run every 200 minutes when idle
|
|
277
|
-
1h run every hour when idle
|
|
278
|
-
```
|
|
279
|
-
|
|
280
|
-
OpenCode Loop separates prompt, slash-command, and shell work because they should not be executed the same way.
|
|
281
|
-
|
|
282
|
-
| Type | Example |
|
|
283
|
-
|---|---|
|
|
284
|
-
| Prompt | `/loop 0s continue from progress.md` |
|
|
285
|
-
| Scheduled question | `/loop-ask 1h did you run tests?` |
|
|
286
|
-
| OpenCode command | `/loop-command 200m /compact` |
|
|
287
|
-
| Shell | `/loop-shell 10m npm test` |
|
|
288
|
-
|
|
289
|
-
Do not use a normal prompt loop when you mean to run `/compact`. Prefer:
|
|
290
|
-
|
|
291
|
-
```text
|
|
292
|
-
/loop-command 200m /compact
|
|
293
|
-
```
|
|
230
|
+
| `/loop-export` | Export current-session Loop state |
|
|
294
231
|
|
|
295
232
|
## Useful flags
|
|
296
233
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
```text
|
|
300
|
-
/loop 0s --name dev continue the project
|
|
301
|
-
/loop-pause dev
|
|
302
|
-
/loop-resume dev
|
|
303
|
-
/loop-stop dev
|
|
304
|
-
```
|
|
305
|
-
|
|
306
|
-
### Limits
|
|
234
|
+
Lifecycle and limits:
|
|
307
235
|
|
|
308
236
|
```text
|
|
237
|
+
--name <name>
|
|
309
238
|
--max-runs <n>
|
|
310
239
|
--max-runtime <duration>
|
|
311
240
|
--max-failures <n>
|
|
312
241
|
--timeout <duration>
|
|
242
|
+
--no-now
|
|
243
|
+
--now
|
|
313
244
|
```
|
|
314
245
|
|
|
315
|
-
|
|
246
|
+
Safety and verification:
|
|
316
247
|
|
|
317
248
|
```text
|
|
249
|
+
--safe
|
|
250
|
+
--ask-never
|
|
251
|
+
--no-overlap
|
|
318
252
|
--verify "npm test"
|
|
319
253
|
--preflight "npm install"
|
|
320
254
|
--postrun "git status --short"
|
|
321
255
|
--pause-on-verify-fail
|
|
322
|
-
--safe
|
|
323
|
-
--ask-never
|
|
324
|
-
--no-overlap
|
|
325
256
|
```
|
|
326
257
|
|
|
327
|
-
|
|
258
|
+
Project context:
|
|
328
259
|
|
|
329
260
|
```text
|
|
330
261
|
--progress-file progress.md
|
|
@@ -335,119 +266,137 @@ Do not use a normal prompt loop when you mean to run `/compact`. Prefer:
|
|
|
335
266
|
--watch progress.md
|
|
336
267
|
```
|
|
337
268
|
|
|
338
|
-
|
|
269
|
+
Checkpoints:
|
|
339
270
|
|
|
340
271
|
```text
|
|
341
272
|
--checkpoint-only
|
|
342
273
|
--git-checkpoint
|
|
343
274
|
```
|
|
344
275
|
|
|
345
|
-
`--git-checkpoint` may stage
|
|
276
|
+
`--git-checkpoint` may stage/commit work; use it only when intentional.
|
|
346
277
|
|
|
347
|
-
##
|
|
278
|
+
## Status and diagnostics
|
|
279
|
+
|
|
280
|
+
`/loop-status` reports both the **schedule definition** and the **current scheduler state**. Examples:
|
|
348
281
|
|
|
349
282
|
```text
|
|
350
|
-
|
|
283
|
+
schedule=every idle | state=waiting for idle
|
|
284
|
+
schedule=every 5m, first after 5m | state=due in 3m
|
|
285
|
+
schedule=once after 5m | state=due; waiting for idle
|
|
351
286
|
```
|
|
352
287
|
|
|
353
|
-
|
|
288
|
+
This is intentional: “due” is a clock fact, while “waiting for idle” is an admission/safety fact.
|
|
289
|
+
|
|
290
|
+
### If a job says enabled but never runs
|
|
291
|
+
|
|
292
|
+
The problematic shape is typically:
|
|
354
293
|
|
|
355
294
|
```text
|
|
356
|
-
|
|
295
|
+
enabled=true
|
|
296
|
+
paused=false
|
|
297
|
+
runCount=0
|
|
298
|
+
lastRunAt=0
|
|
357
299
|
```
|
|
358
300
|
|
|
359
|
-
|
|
301
|
+
Some 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.
|
|
360
302
|
|
|
361
|
-
|
|
303
|
+
Recovery is logged as:
|
|
362
304
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
```bash
|
|
366
|
-
opencode-loopd --project . --every 5m --prompt-file loop-prompt.md
|
|
305
|
+
```text
|
|
306
|
+
status-message-idle-recovery
|
|
367
307
|
```
|
|
368
308
|
|
|
369
|
-
|
|
309
|
+
Busy retries are also written as throttled `deferred` events so `loop.log` does not misleadingly contain only the original `add` line.
|
|
370
310
|
|
|
371
|
-
|
|
372
|
-
|
|
311
|
+
Use:
|
|
312
|
+
|
|
313
|
+
```text
|
|
314
|
+
/loop-status
|
|
315
|
+
/loop-logs
|
|
316
|
+
/loop-doctor
|
|
373
317
|
```
|
|
374
318
|
|
|
375
|
-
|
|
319
|
+
### Session-bound state
|
|
376
320
|
|
|
377
|
-
|
|
378
|
-
|
|
321
|
+
Normal plugin Loop jobs are session-bound and stored under:
|
|
322
|
+
|
|
323
|
+
```text
|
|
324
|
+
.opencode/opencode-loop/<session-id>.json
|
|
379
325
|
```
|
|
380
326
|
|
|
381
|
-
|
|
327
|
+
A 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.
|
|
382
328
|
|
|
383
|
-
|
|
384
|
-
opencode-loopd --project . --session ses_xxx --every 5m --prompt-file loop-prompt.md
|
|
385
|
-
```
|
|
329
|
+
For work that must continue after the TUI/session closes, use `opencode-loopd`.
|
|
386
330
|
|
|
387
|
-
|
|
331
|
+
## Loop and dedicated OpenCode Goals
|
|
388
332
|
|
|
389
|
-
|
|
390
|
-
opencode-loopd --project . --every 5m --max-runs 20 --prompt-file loop-prompt.md
|
|
391
|
-
```
|
|
333
|
+
They can be installed together. Recommended split:
|
|
392
334
|
|
|
393
|
-
|
|
335
|
+
- use **`/goal`** for durable outcome-driven work, evidence, verification, restart recovery, and semantic completion;
|
|
336
|
+
- use **`/loop`**, `/loop-command`, `/loop-shell`, and `opencode-loopd` for scheduling/repetition/background infrastructure.
|
|
394
337
|
|
|
395
|
-
|
|
338
|
+
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.
|
|
396
339
|
|
|
397
|
-
|
|
398
|
-
|
|
340
|
+
Recommended choices are to finish/pause the Goal or use a separate session. Advanced users can deliberately override the guard with:
|
|
341
|
+
|
|
342
|
+
```text
|
|
343
|
+
/loop --allow-goal-overlap continue
|
|
399
344
|
```
|
|
400
345
|
|
|
401
|
-
|
|
346
|
+
That escape hatch can create competing autonomous turns; use it only when that is intentional.
|
|
402
347
|
|
|
403
|
-
|
|
404
|
-
opencode-loopd uninstall-task --name OpenCodeLoop
|
|
405
|
-
```
|
|
348
|
+
Loop's older experimental `/loop-goal*` commands remain available for compatibility unless installed with `--without-loop-goals`. For new strongly verified Goal work, prefer:
|
|
406
349
|
|
|
407
|
-
|
|
350
|
+
```bash
|
|
351
|
+
npx -y @bybrawe/opencode-goal@latest
|
|
352
|
+
```
|
|
408
353
|
|
|
409
|
-
|
|
354
|
+
## Recommended development loop
|
|
410
355
|
|
|
411
356
|
```text
|
|
412
|
-
/loop-
|
|
357
|
+
/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.
|
|
413
358
|
```
|
|
414
359
|
|
|
415
|
-
|
|
360
|
+
Test/fix loop:
|
|
416
361
|
|
|
417
362
|
```text
|
|
418
|
-
/loop-
|
|
419
|
-
/loop-goal-pause
|
|
420
|
-
/loop-goal-resume
|
|
421
|
-
/loop-goal-clear
|
|
422
|
-
/loop-goal-done <summary>
|
|
423
|
-
/loop-goal-blocked <reason>
|
|
363
|
+
/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.
|
|
424
364
|
```
|
|
425
365
|
|
|
426
|
-
|
|
366
|
+
## Background daemon
|
|
427
367
|
|
|
428
|
-
|
|
429
|
-
|
|
368
|
+
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.
|
|
369
|
+
|
|
370
|
+
```bash
|
|
371
|
+
opencode-loopd --project . --every 5m --prompt-file loop-prompt.md
|
|
430
372
|
```
|
|
431
373
|
|
|
432
|
-
|
|
374
|
+
Immediate daemon cadence:
|
|
433
375
|
|
|
434
376
|
```bash
|
|
435
|
-
|
|
377
|
+
opencode-loopd --project . --every 0s --prompt "continue from progress.md and implement the next unfinished TODO"
|
|
436
378
|
```
|
|
437
379
|
|
|
438
|
-
|
|
380
|
+
Pin a session and limit runs:
|
|
439
381
|
|
|
440
382
|
```bash
|
|
441
|
-
|
|
442
|
-
|
|
383
|
+
opencode-loopd --project . --session ses_xxx --every 5m --max-runs 20 --timeout 30m --prompt-file loop-prompt.md
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
Windows Task Scheduler:
|
|
387
|
+
|
|
388
|
+
```powershell
|
|
389
|
+
opencode-loopd install-task --project "C:\path\to\project" --every 10m --prompt-file loop-prompt.md --name OpenCodeLoop
|
|
390
|
+
opencode-loopd uninstall-task --name OpenCodeLoop
|
|
443
391
|
```
|
|
444
392
|
|
|
445
393
|
## State and checkpoints
|
|
446
394
|
|
|
447
|
-
|
|
395
|
+
Runtime state and logs:
|
|
448
396
|
|
|
449
397
|
```text
|
|
450
398
|
.opencode/opencode-loop/
|
|
399
|
+
.opencode/opencode-loop/loop.log
|
|
451
400
|
```
|
|
452
401
|
|
|
453
402
|
Patch checkpoints:
|
|
@@ -456,62 +405,27 @@ Patch checkpoints:
|
|
|
456
405
|
.opencode/opencode-loop/checkpoints/
|
|
457
406
|
```
|
|
458
407
|
|
|
459
|
-
|
|
408
|
+
Add `.opencode/opencode-loop/` to `.gitignore` if runtime state should not be committed.
|
|
460
409
|
|
|
461
|
-
|
|
462
|
-
.opencode/opencode-loop/loop.log
|
|
463
|
-
```
|
|
410
|
+
## Permissions
|
|
464
411
|
|
|
465
|
-
|
|
412
|
+
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.
|
|
466
413
|
|
|
467
|
-
##
|
|
468
|
-
|
|
469
|
-
For unattended loops, avoid granting every shell command permanently. Allow routine read/edit/test operations and keep destructive operations on ask/deny.
|
|
470
|
-
|
|
471
|
-
Example:
|
|
472
|
-
|
|
473
|
-
```json
|
|
474
|
-
{
|
|
475
|
-
"$schema": "https://opencode.ai/config.json",
|
|
476
|
-
"permission": {
|
|
477
|
-
"read": "allow",
|
|
478
|
-
"grep": "allow",
|
|
479
|
-
"glob": "allow",
|
|
480
|
-
"todowrite": "allow",
|
|
481
|
-
"edit": "allow",
|
|
482
|
-
"bash": {
|
|
483
|
-
"*": "ask",
|
|
484
|
-
"git status*": "allow",
|
|
485
|
-
"git diff*": "allow",
|
|
486
|
-
"npm test*": "allow",
|
|
487
|
-
"npm run test*": "allow",
|
|
488
|
-
"npm run lint*": "allow",
|
|
489
|
-
"git push*": "ask",
|
|
490
|
-
"git reset*": "ask",
|
|
491
|
-
"git clean*": "deny",
|
|
492
|
-
"rm *": "deny"
|
|
493
|
-
},
|
|
494
|
-
"external_directory": "ask"
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
```
|
|
498
|
-
|
|
499
|
-
`--safe` reduces risk but does not replace careful OpenCode permission configuration.
|
|
500
|
-
|
|
501
|
-
## Package
|
|
414
|
+
## Package and compatibility
|
|
502
415
|
|
|
503
416
|
```text
|
|
504
417
|
@bybrawe/opencode-loop
|
|
505
418
|
```
|
|
506
419
|
|
|
507
|
-
|
|
420
|
+
Stable package peer range:
|
|
508
421
|
|
|
509
|
-
```
|
|
510
|
-
opencode-
|
|
511
|
-
opencode-loopd --help
|
|
422
|
+
```text
|
|
423
|
+
@opencode-ai/plugin >=1.4.0 <2
|
|
512
424
|
```
|
|
513
425
|
|
|
514
|
-
|
|
426
|
+
The repository contains experimental OpenCode 2 work, but the stable package does not claim full OpenCode 2 parity.
|
|
427
|
+
|
|
428
|
+
See [docs/SCHEDULING.md](./docs/SCHEDULING.md) for the scheduling contract and [CHANGELOG.md](./CHANGELOG.md) for release history.
|
|
515
429
|
|
|
516
430
|
## License
|
|
517
431
|
|