opencode-jobs 0.1.2 → 1.0.0
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/README.md +87 -26
- package/dist/cli.js +827 -63
- package/dist/index.d.ts +1 -1
- package/dist/index.js +302 -49
- package/dist/install.d.ts +3 -0
- package/dist/internals.d.ts +2 -1
- package/dist/job.d.ts +7 -0
- package/dist/migration.d.ts +9 -0
- package/dist/paths.d.ts +4 -1
- package/dist/registry.d.ts +1 -0
- package/dist/runs.d.ts +2 -0
- package/dist/tools.d.ts +1 -1
- package/package.json +1 -1
- package/skill/opencode-jobs/SKILL.md +10 -3
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@ and reports the manual change required.
|
|
|
36
36
|
|
|
37
37
|
Job files are committed agent prompts that run on your machine on a
|
|
38
38
|
schedule — only install and enable projects whose
|
|
39
|
-
`.opencode/
|
|
39
|
+
`.opencode/jobs/` you trust, the same care you would take before
|
|
40
40
|
running an unfamiliar repository's build.
|
|
41
41
|
|
|
42
42
|
Alternatively, add the package manually to the project root `opencode.json`
|
|
@@ -67,8 +67,8 @@ the uninstaller cannot rewrite safely is left untouched with a non-zero
|
|
|
67
67
|
exit. Job definitions, run history, session state, and logs are kept.
|
|
68
68
|
|
|
69
69
|
Add `--purge` to also delete the project's job definitions
|
|
70
|
-
(`.opencode/
|
|
71
|
-
session state, and logs):
|
|
70
|
+
(`.opencode/jobs/`) and its job data (run scripts, run history,
|
|
71
|
+
session state, run locks, worktrees, and logs):
|
|
72
72
|
|
|
73
73
|
```sh
|
|
74
74
|
opencode-jobs uninstall --purge
|
|
@@ -87,21 +87,21 @@ can also be used from setup scripts and CI.
|
|
|
87
87
|
|
|
88
88
|
## Tools
|
|
89
89
|
|
|
90
|
-
| Tool | What it does
|
|
91
|
-
| ----------------- |
|
|
92
|
-
| `schedule_job` | Create or update a job (cron schedule, prompt or custom command, session mode, guard, timeout) |
|
|
93
|
-
| `list_jobs` | List job definitions in the project with next/last run status
|
|
94
|
-
| `get_job` | Show one job: definition, timer state, last runs, recent log tail
|
|
95
|
-
| `run_job` | Fire a job now, through the exact script the timer would run
|
|
96
|
-
| `job_logs` | Tail a job's log (scheduled and manual runs both append)
|
|
97
|
-
| `delete_job` | Delete a job, its units, run script, and session state
|
|
98
|
-
| `enable_project` | Install systemd user units for all jobs in the project and register it
|
|
99
|
-
| `disable_project` | Stop and remove the project's units (jobs and history are kept)
|
|
100
|
-
| `list_projects` | List all projects that have enabled jobs
|
|
90
|
+
| Tool | What it does |
|
|
91
|
+
| ----------------- | -------------------------------------------------------------------------------------------------------- |
|
|
92
|
+
| `schedule_job` | Create or update a job (cron schedule, prompt or custom command, session mode, guard, worktree, timeout) |
|
|
93
|
+
| `list_jobs` | List job definitions in the project with next/last run status |
|
|
94
|
+
| `get_job` | Show one job: definition, timer state, last runs, recent log tail |
|
|
95
|
+
| `run_job` | Fire a job now, through the exact script the timer would run |
|
|
96
|
+
| `job_logs` | Tail a job's log (scheduled and manual runs both append) |
|
|
97
|
+
| `delete_job` | Delete a job, its units, run script, and session state |
|
|
98
|
+
| `enable_project` | Install systemd user units for all jobs in the project and register it |
|
|
99
|
+
| `disable_project` | Stop and remove the project's units (jobs and history are kept) |
|
|
100
|
+
| `list_projects` | List all projects that have enabled jobs |
|
|
101
101
|
|
|
102
102
|
## Job definitions
|
|
103
103
|
|
|
104
|
-
Jobs live in your repo at `.opencode/
|
|
104
|
+
Jobs live in your repo at `.opencode/jobs/<slug>.json` — review
|
|
105
105
|
them in PRs like any other code:
|
|
106
106
|
|
|
107
107
|
```json
|
|
@@ -114,6 +114,7 @@ them in PRs like any other code:
|
|
|
114
114
|
},
|
|
115
115
|
"session": "compact+last",
|
|
116
116
|
"guard": "! git diff --quiet",
|
|
117
|
+
"worktree": true,
|
|
117
118
|
"timeoutSeconds": 1800
|
|
118
119
|
}
|
|
119
120
|
```
|
|
@@ -127,6 +128,8 @@ them in PRs like any other code:
|
|
|
127
128
|
- `guard` — shell command run first; a non-zero exit skips the run (recorded
|
|
128
129
|
as `skipped`). Example: `"! git diff --quiet"` runs only when the repo has
|
|
129
130
|
changes.
|
|
131
|
+
- `worktree` — run in a fresh git worktree instead of the project checkout
|
|
132
|
+
(below).
|
|
130
133
|
- `timeoutSeconds` — hard limit; systemd stops the run with SIGTERM.
|
|
131
134
|
|
|
132
135
|
### Session modes
|
|
@@ -141,6 +144,48 @@ them in PRs like any other code:
|
|
|
141
144
|
Tracked modes (`persist`/`compact`/`compact+last`) self-heal a deleted or
|
|
142
145
|
stale session by retrying once with a fresh session.
|
|
143
146
|
|
|
147
|
+
### Worktree jobs
|
|
148
|
+
|
|
149
|
+
Set `"worktree": true` (or an object) to run a job in a fresh git worktree
|
|
150
|
+
instead of the project checkout, so scheduled runs never race your editor or
|
|
151
|
+
leave the main tree dirty:
|
|
152
|
+
|
|
153
|
+
```json
|
|
154
|
+
"worktree": {
|
|
155
|
+
"base": "/srv/worktrees",
|
|
156
|
+
"ref": "origin/main",
|
|
157
|
+
"commitMessage": "nightly sweep: automated fixes"
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Each run:
|
|
162
|
+
|
|
163
|
+
1. takes a per-job lock (so an overlapping timer and `run_job` invocation
|
|
164
|
+
cannot fight over the worktree — the later run is recorded as
|
|
165
|
+
`skipped`), then creates a worktree at `<base>/<slug>` on a new branch
|
|
166
|
+
`opencode-jobs/<slug>/<timestamp>-<pid>`, starting from `ref`
|
|
167
|
+
(default: `HEAD` of the project checkout). A leftover worktree from a
|
|
168
|
+
crashed or timed-out run is committed first (recovery commit on its own
|
|
169
|
+
branch) and then removed — unless the recovery commit fails (for
|
|
170
|
+
example a `pre-commit` hook rejects the changes), in which case the
|
|
171
|
+
stale worktree is kept and the run fails instead of discarding work;
|
|
172
|
+
2. runs the job with the worktree as the working directory — if the
|
|
173
|
+
project is a subdirectory of a larger repository, the job runs in the
|
|
174
|
+
matching subdirectory of the worktree;
|
|
175
|
+
3. commits everything (`git add -A`) as `opencode-jobs` with
|
|
176
|
+
`--no-gpg-sign`, then removes the worktree — the branch and its commits
|
|
177
|
+
stay in the repository, and the run record stores `worktreeBranch` and
|
|
178
|
+
`worktreeCommit`.
|
|
179
|
+
|
|
180
|
+
If the safety commit fails, the worktree is kept on disk rather than
|
|
181
|
+
discarded. The default base is
|
|
182
|
+
`~/.local/state/opencode/jobs/worktrees/<scopeId>/<slug>` (respecting
|
|
183
|
+
`XDG_STATE_HOME`); override with `base` (relative paths resolve against the
|
|
184
|
+
project directory, and the base should be dedicated to job worktrees).
|
|
185
|
+
Worktree jobs require `git` and a git repository — a missing repo fails the
|
|
186
|
+
run with a clear record. Branches accumulate per run by design; merge or
|
|
187
|
+
delete them when you no longer need the work.
|
|
188
|
+
|
|
144
189
|
## How it works
|
|
145
190
|
|
|
146
191
|
- `enable_project` generates, for each job: a frozen POSIX `run-<slug>.sh`
|
|
@@ -149,6 +194,9 @@ stale session by retrying once with a fresh session.
|
|
|
149
194
|
- Run scripts work standalone: they append a JSONL record (status, exit
|
|
150
195
|
code, duration, session id) per run, capture `--format json` output for
|
|
151
196
|
tracked session modes, and never leave temp files behind.
|
|
197
|
+
- Worktree jobs create a fresh worktree per run, commit all changes to a
|
|
198
|
+
per-run branch, and remove the worktree afterwards — see
|
|
199
|
+
[Worktree jobs](#worktree-jobs).
|
|
152
200
|
- A global registry tracks enabled projects so `list_projects` and
|
|
153
201
|
`disable_project` work from any session.
|
|
154
202
|
- Schedules are cron expressions compiled to systemd `OnCalendar` and
|
|
@@ -156,32 +204,45 @@ stale session by retrying once with a fresh session.
|
|
|
156
204
|
|
|
157
205
|
## Storage
|
|
158
206
|
|
|
159
|
-
| What | Where
|
|
160
|
-
| ------------------- |
|
|
161
|
-
| Job definitions | `<project>/.opencode/
|
|
162
|
-
| Run scripts | `~/.config/opencode/
|
|
163
|
-
| Run history (JSONL) | `~/.config/opencode/
|
|
164
|
-
| Session state | `~/.config/opencode/
|
|
165
|
-
|
|
|
166
|
-
|
|
|
167
|
-
|
|
|
207
|
+
| What | Where |
|
|
208
|
+
| ------------------- | ----------------------------------------------------------------------------- |
|
|
209
|
+
| Job definitions | `<project>/.opencode/jobs/<slug>.json` (git-committed) |
|
|
210
|
+
| Run scripts | `~/.config/opencode/jobs/scopes/<scopeId>/run-<slug>.sh` |
|
|
211
|
+
| Run history (JSONL) | `~/.config/opencode/jobs/runs/<scopeId>/<slug>.jsonl` |
|
|
212
|
+
| Session state | `~/.config/opencode/jobs/sessions/<scopeId>/<slug>.txt` |
|
|
213
|
+
| Run locks | `~/.config/opencode/jobs/locks/<scopeId>/<slug>.lock` (worktree jobs) |
|
|
214
|
+
| Job worktrees | `~/.local/state/opencode/jobs/worktrees/<scopeId>/<slug>` (removed after run) |
|
|
215
|
+
| Job logs | `~/.config/opencode/logs/jobs/<scopeId>/<slug>.log` |
|
|
216
|
+
| Project registry | `~/.config/opencode/jobs/registry.json` |
|
|
217
|
+
| systemd units | `~/.config/systemd/user/opencode-sched-<scope>-<slug>.{service,timer}` |
|
|
168
218
|
|
|
169
219
|
`scopeId` is a stable hash of the project path, so multiple projects can
|
|
170
220
|
define jobs without colliding. Because it is path-derived, moving or renaming
|
|
171
221
|
a project directory orphans its units, history, and registry entry — run
|
|
172
222
|
`opencode-jobs uninstall --purge` from the old path before moving, or clean
|
|
173
|
-
up `~/.config/opencode/
|
|
223
|
+
up `~/.config/opencode/jobs/` (and the unit files) manually afterwards.
|
|
224
|
+
|
|
225
|
+
### Upgrading storage
|
|
226
|
+
|
|
227
|
+
When the plugin or CLI first runs after an upgrade, it moves legacy 0.1.x
|
|
228
|
+
definitions and state to the paths above, preserving the registry, run history,
|
|
229
|
+
session state, logs, locks, and worktrees. Enabled projects are re-synced so
|
|
230
|
+
their existing systemd units use the new paths. Migration is idempotent and
|
|
231
|
+
refuses to overwrite a new path when both old and new data exist; reconcile or
|
|
232
|
+
back up one side and retry.
|
|
174
233
|
|
|
175
234
|
## Configuration
|
|
176
235
|
|
|
177
|
-
- `
|
|
236
|
+
- `OPENCODE_JOBS_OPENCODE_PATH` — absolute path to the `opencode`
|
|
178
237
|
binary the run scripts invoke (default: resolved from `PATH`, then
|
|
179
238
|
`~/.opencode/bin/opencode`, then common install locations).
|
|
239
|
+
`OPENCODE_SCHEDULER_OPENCODE_PATH` remains accepted for 0.1.x compatibility.
|
|
180
240
|
|
|
181
241
|
## Requirements
|
|
182
242
|
|
|
183
243
|
- Linux with a systemd user session (jobs run via `systemctl --user`)
|
|
184
244
|
- `curl` (used by `compact`/`compact+last` modes only)
|
|
245
|
+
- `git` and `flock` (from util-linux; used by `worktree` jobs only)
|
|
185
246
|
- POSIX `sh` (generated scripts are `sh`/`dash`-verified)
|
|
186
247
|
- The `opencode` CLI available to the timer environment
|
|
187
248
|
|