You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
LIST 4a. How are scheduled tasks created and managed inside OpenCode? Do they run fully independently (no Muse tokens spent)? Can the route be chosen per task (summit/specialist instead of workhorse)? What does Muse's management surface look like — creating schedules, checking other OpenCode sessions aren't crashing, adjusting routes? Deliverable: capability report with a worked example schedule created and observed.
Program: Drew's 2026-10-28 directive (full text: hatch-personal memory/topics/id-program-2026-10-28.md).
Working pattern: parallel investigations, then the named synthesis issue merges them into a full design. Route guidance: Workhorse by default; Specialist/Summit for synthesis and ramification-heavy work. A result that says "done" is not the endpoint — the orchestrator reviews it and may commission another round. Deliverables: a markdown design/investigation doc (mermaid/SVG diagrams welcome) linked from this issue, plus follow-up issues for anything buildable. Build a proof of concept where the design calls for one, but do NOT build the permanent feature on top of an unreviewed PoC.
Top priority — ID program wave-1. Drew directed this be picked up in the next runs (2026-10-29): enqueued directly as triage task 3338 in repo-health-code-pilot at queue priority 20 (only breakage-class work at priority 10 outranks it). Wave-1 is the ungated investigations and designs; syntheses and PoCs stay gated on their named inputs. Investigation route: Workhorse.
Expectation: effort class m — done = investigation result recorded on this issue (comment/doc) + follow-on work routed in the same pass, gated syntheses left gated.
Investigation result — OpenCode native scheduled tasks (LIST 4a)
Worker: queue task 3338 (repo-health-code-pilot), Lane D, 2026-10-29. Method: local CLI/source checks on the fleet fork (v2.0.30) on sandbox + laptop, upstream docs/issues, ecosystem review, and a live worked example (below).
Verdict in one paragraph
OpenCode has no native scheduler today — not upstream, not in the fleet fork. What exists is a proven composition: an OS scheduler (systemd timer / launchd / cron) firing opencode run with a per-job --model route. That composition runs with zero Muse tokens in both trigger and execution, supports per-task route choice (workhorse / specialist / summit are just the job's --model value), and gives Muse a file-based management surface. Scheduling is not supervision: no mechanism watches for stalls — that remains the babysitter's job (see #2021).
1. Is there a native scheduler? No.
Fleet fork CLI (v2.0.30, verified on laptop + sandbox 2026-10-29): subcommands are upgrade, acp, api, debug, auth, mcp, plugin, models, stats, mini, run, session, msg, service, reload, pair, serve — no schedule/cron. A grep of the fork's packages finds no scheduler subsystem (hits are unrelated UI/timeline uses of the word).
Upstream: feature request [FEATURE]: /schedule — run recurring background tasks (cron-like routines) anomalyco/opencode#41906 ("[FEATURE]: /schedule — run recurring background tasks") is OPEN. A community prototype (SQLite-backed automations; once/interval/5-field cron; CLI create/list/show/run/pause/resume/history/remove; restart recovery) was described there on 2026-09-08 but has not merged. Do not plan on it.
2. The three real mechanisms today
(a) OS scheduler + opencode run — the de-facto pattern, recommended. The ecosystem plugin different-ai/opencode-scheduler (listed on opencode.ai's ecosystem page) wraps exactly this: natural language → 5-field cron; job JSON persisted under ~/.config/opencode/scheduler/scopes/<workdir-hash>/jobs/; generates a systemd .timer (Linux) / launchd plist (macOS) / schtasks / crontab entry; a supervisor wrapper enforces no-overlap (lock file), non-interactive permissions (OPENCODE_PERMISSION), and optional hard timeout. Management tools: schedule_job, list_jobs, get_job, job_logs, run_job. Fleet caveat: it is a v1 plugin (@opencode-ai/plugin); the fleet's v2 fork cannot run v1 plugins (the deployed config's plugin array is emptied for exactly this reason), so adopting it means a port — the underlying OS-timer pattern needs no plugin at all.
(b) GitHub Actions schedule: event with the official anomalyco/opencode/github action: cron in the workflow file, model: chosen per workflow, output to logs/PRs. Fits repo-scoped periodic chores; does not reach laptop sessions or local state.
(c) Third-party daemons (e.g. an opencode-cron CLI with a launchd ticker; MCP cron servers): they exist, are unvetted, and are not recommended as a fleet foundation without a review round.
3. Independence from Muse tokens — YES for execution
A scheduled OpenCode run spends only the provider plan its route resolves to. Verified live in the worked example: the run resolved opencode-route/workhorse → opencode-go DeepSeek V4.1 Flash; no Muse process or token was involved between timer creation and completion. Note the inversion in today's fleet: execution already spends plan quotas, but the triggers and supervision are Muse cron jobs (dispatcher, babysitter) spending Muse tokens. OS-level scheduling is precisely the piece that moves the trigger off Muse.
4. Per-task route choice — YES
Route is a property of the job definition, not the scheduler: each unit carries its own opencode run --model opencode-route/<workhorse|specialist|summit|speed> (fleet route ids from opencode.jsonc; effort variants via #low/#high/#max). Changing one job's route = editing one unit. The GitHub Actions path takes model: per workflow the same way. This matches Drew's route guidance directly: scheduled tasks run on a single route pool chosen per task.
5. Muse's management surface
Create / adjust / retire: write or remove systemd user units (or job JSON where a wrapper is used). Units are files — diffable and committable, unlike opaque in-app state.
Health / crash visibility:systemctl --user list-timers / status, per-job run logs; for live sessions, the OpenCode server API (/api/*) and OpenChamber session views — the surfaces the dispatcher/babysitter already use. Caveat found during the worked example: opencode session list did not surface the just-run session on its first page (paginated/unordered in practice) — directory-scoped server-API reads are the reliable surface, not the CLI list.
6. Worked example — created and observed 2026-10-29
On the laptop (amd), a one-shot systemd user timer:
Created 10:19:03Z: systemd-run --user --unit=oc-sched-example-3338 --on-active=60s --collect ~/tmp/oc-sched-3338/run.sh
Fired 10:20:03Z; the service ran opencode run --auto --title oc-sched-example-3338 --model opencode-route/workhorse "Create a file named SCHEDULED-RUN.md …" in ~/tmp/oc-sched-3338
Log: route resolved to deepseek-v4.1-flash (build agent), file created with the exact requested two lines, exit 0 at 10:20:14Z (~10 s of execution)
Artifacts retained on the laptop: ~/tmp/oc-sched-3338/{run.sh, run.log, SCHEDULED-RUN.md}; transient units auto-collected.
This is a proof of the pattern, not a permanent feature — no fleet job was migrated onto it by this investigation.
7. Fit guidance (feeds #2018 and the #2024 placement synthesis)
Poor fits: anything needing judgement at trigger time, cross-session coordination, or guaranteed escalation — those stay Muse-triggered or dispatcher-launched.
8. Follow-on routing
Implementation follow-on filed as a separate issue (linked below when posted): implement: fleet OpenCode scheduled-task pattern — systemd timer units + opencode run with per-job route, a small job registry, and a log surface — adopting the v1 plugin (after a v2 port) and waiting on upstream #41906 are recorded there as considered-and-deferred alternatives. The placement synthesis #2024 stays gated on its named inputs; this report is one of them.
— Sources: fork CLI --help output (laptop + sandbox, 2026-10-29); upstream issue anomalyco/opencode#41906 (state OPEN, read 2026-10-29); opencode.ai/docs/github (schedule event) and /docs/ecosystem (opencode-scheduler listing); different-ai/opencode-scheduler docs via DeepWiki; fleet quota picture from the dispatcher log (2026-10-29 ~05:20 CDT: Workhorse OPEN via opencode-go).
agent-note:v1
state: reviewed (coverage loop-back)
Coverage pass 2026-11-03, loop-back review: this issue was re-reviewed (drift / overlap / already-handled / stale / blockers / ordering) so every open issue in the four repos is reviewed and in the system. Verdict: still live; in the system as task 7263 (triage, queued, priority 50) in repo-health-code-pilot. Labels audited and synced. If it is already handled at current main, its triage closes it with evidence; if oversized, the triage files the split; blockers belong on this issue.
Found via: coverage loop-back 2026-11-03
Triage verdict — #2019 at current main (verified fresh 2026-11-03T23:09Z)
State verified: issue #2019 is OPEN. No hard-stop labels (held, user/owned, do-not-merge, do-not-auto-edit all absent).
The investigation this issue asks for is already delivered. Queue task 3338 (Lane D, 2026-10-29) posted the full capability report on this issue and observed a live worked example. All four LIST 4a questions are answered there:
Independence from Muse tokens: YES for execution — the worked example (laptop systemd user timer, fired 2026-10-29T10:20:03Z, exit 0) resolved opencode-route/workhorse → DeepSeek V4.1 Flash with no Muse process or token in the loop.
Per-task route choice: YES — route is a property of the job definition (--model opencode-route/<workhorse|specialist|summit|speed> per unit/workflow).
Correction already on record (Drew, 2026-10-31): the "no native scheduler" verdict covers OpenCode only — OpenChamber does have native scheduled tasks, and #3026 uses them as its mechanism, with this investigation's systemd pattern as fallback.
Blockers / gates named: none blocking the investigation itself. The remaining consumers are gated by design: the placement synthesis #2024 is gated on its named inputs (this report is one of them), under epic #2055.
Fix path already enqueued (no new task needed from this triage):
Disposition: triage complete. This issue stays open as the investigation record feeding synthesis #2024 / epic #2055; its buildable follow-ons are already filed and queued as #2232 and #2174, so no duplicate issue or task is created here.
Activity
developing-today commentedon Oct 29, 2026
CODE-940
dezren39 commentedon Oct 29, 2026
Parent epic: #2055 — fleet expansion & placement program (2026-10-28 directive).
dezren39 commentedon Oct 29, 2026
Top priority — ID program wave-1. Drew directed this be picked up in the next runs (2026-10-29): enqueued directly as triage task 3338 in repo-health-code-pilot at queue priority 20 (only breakage-class work at priority 10 outranks it). Wave-1 is the ungated investigations and designs; syntheses and PoCs stay gated on their named inputs. Investigation route: Workhorse.
dezren39 commentedon Oct 29, 2026
🤖 Agent note · picked up
dezren39 commentedon Oct 29, 2026
Investigation result — OpenCode native scheduled tasks (LIST 4a)
Worker: queue task 3338 (repo-health-code-pilot), Lane D, 2026-10-29. Method: local CLI/source checks on the fleet fork (v2.0.30) on sandbox + laptop, upstream docs/issues, ecosystem review, and a live worked example (below).
Verdict in one paragraph
OpenCode has no native scheduler today — not upstream, not in the fleet fork. What exists is a proven composition: an OS scheduler (systemd timer / launchd / cron) firing
opencode runwith a per-job--modelroute. That composition runs with zero Muse tokens in both trigger and execution, supports per-task route choice (workhorse / specialist / summit are just the job's--modelvalue), and gives Muse a file-based management surface. Scheduling is not supervision: no mechanism watches for stalls — that remains the babysitter's job (see #2021).1. Is there a native scheduler? No.
upgrade, acp, api, debug, auth, mcp, plugin, models, stats, mini, run, session, msg, service, reload, pair, serve— noschedule/cron. A grep of the fork's packages finds no scheduler subsystem (hits are unrelated UI/timeline uses of the word).2. The three real mechanisms today
opencode run— the de-facto pattern, recommended. The ecosystem plugindifferent-ai/opencode-scheduler(listed on opencode.ai's ecosystem page) wraps exactly this: natural language → 5-field cron; job JSON persisted under~/.config/opencode/scheduler/scopes/<workdir-hash>/jobs/; generates a systemd.timer(Linux) / launchd plist (macOS) / schtasks / crontab entry; a supervisor wrapper enforces no-overlap (lock file), non-interactive permissions (OPENCODE_PERMISSION), and optional hard timeout. Management tools:schedule_job,list_jobs,get_job,job_logs,run_job. Fleet caveat: it is a v1 plugin (@opencode-ai/plugin); the fleet's v2 fork cannot run v1 plugins (the deployed config's plugin array is emptied for exactly this reason), so adopting it means a port — the underlying OS-timer pattern needs no plugin at all.schedule:event with the officialanomalyco/opencode/githubaction: cron in the workflow file,model:chosen per workflow, output to logs/PRs. Fits repo-scoped periodic chores; does not reach laptop sessions or local state.opencode-cronCLI with a launchd ticker; MCP cron servers): they exist, are unvetted, and are not recommended as a fleet foundation without a review round.3. Independence from Muse tokens — YES for execution
A scheduled OpenCode run spends only the provider plan its route resolves to. Verified live in the worked example: the run resolved
opencode-route/workhorse→ opencode-go DeepSeek V4.1 Flash; no Muse process or token was involved between timer creation and completion. Note the inversion in today's fleet: execution already spends plan quotas, but the triggers and supervision are Muse cron jobs (dispatcher, babysitter) spending Muse tokens. OS-level scheduling is precisely the piece that moves the trigger off Muse.4. Per-task route choice — YES
Route is a property of the job definition, not the scheduler: each unit carries its own
opencode run --model opencode-route/<workhorse|specialist|summit|speed>(fleet route ids fromopencode.jsonc; effort variants via#low/#high/#max). Changing one job's route = editing one unit. The GitHub Actions path takesmodel:per workflow the same way. This matches Drew's route guidance directly: scheduled tasks run on a single route pool chosen per task.5. Muse's management surface
systemctl --user list-timers/status, per-job run logs; for live sessions, the OpenCode server API (/api/*) and OpenChamber session views — the surfaces the dispatcher/babysitter already use. Caveat found during the worked example:opencode session listdid not surface the just-run session on its first page (paginated/unordered in practice) — directory-scoped server-API reads are the reliable surface, not the CLI list.6. Worked example — created and observed 2026-10-29
On the laptop (
amd), a one-shot systemd user timer:systemd-run --user --unit=oc-sched-example-3338 --on-active=60s --collect ~/tmp/oc-sched-3338/run.shopencode run --auto --title oc-sched-example-3338 --model opencode-route/workhorse "Create a file named SCHEDULED-RUN.md …"in~/tmp/oc-sched-3338deepseek-v4.1-flash(build agent), file created with the exact requested two lines, exit 0 at 10:20:14Z (~10 s of execution)~/tmp/oc-sched-3338/{run.sh, run.log, SCHEDULED-RUN.md}; transient units auto-collected.This is a proof of the pattern, not a permanent feature — no fleet job was migrated onto it by this investigation.
7. Fit guidance (feeds #2018 and the #2024 placement synthesis)
8. Follow-on routing
Implementation follow-on filed as a separate issue (linked below when posted): implement: fleet OpenCode scheduled-task pattern — systemd timer units +
opencode runwith per-job route, a small job registry, and a log surface — adopting the v1 plugin (after a v2 port) and waiting on upstream #41906 are recorded there as considered-and-deferred alternatives. The placement synthesis #2024 stays gated on its named inputs; this report is one of them.— Sources: fork CLI
--helpoutput (laptop + sandbox, 2026-10-29); upstream issue anomalyco/opencode#41906 (state OPEN, read 2026-10-29); opencode.ai/docs/github (schedule event) and /docs/ecosystem (opencode-scheduler listing); different-ai/opencode-scheduler docs via DeepWiki; fleet quota picture from the dispatcher log (2026-10-29 ~05:20 CDT: Workhorse OPEN via opencode-go).dezren39 commentedon Oct 29, 2026
🤖 Agent note · done
opencode runwith per-job route — verified with a live worked example (systemd user timer on the laptop fired 2026-10-29T10:20:03Z, routeopencode-route/workhorse→ opencode-go DeepSeek V4.1 Flash, exit 0, zero Muse tokens). Follow-on implementation filed as implement: fleet OpenCode scheduled-task pattern — systemd timers + opencode run with per-job route #2232. This issue stays open for the orchestrator's review round per the program pattern; the placement synthesis design: task-placement framework v1 — decision rules and a shared-pool efficiency model #2024 remains gated on its inputs.3 remaining items
developing-today commentedon Nov 3, 2026
agent-note:v1
state: reviewed (coverage loop-back)
Coverage pass 2026-11-03, loop-back review: this issue was re-reviewed (drift / overlap / already-handled / stale / blockers / ordering) so every open issue in the four repos is reviewed and in the system. Verdict: still live; in the system as task 7263 (triage, queued, priority 50) in repo-health-code-pilot. Labels audited and synced. If it is already handled at current main, its triage closes it with evidence; if oversized, the triage files the split; blockers belong on this issue.
Found via: coverage loop-back 2026-11-03
dezren39 commentedon Nov 3, 2026
🤖 Agent note · picked up
dezren39 commentedon Nov 3, 2026
🤖 Agent note · done (triage)
Triage verdict — #2019 at current main (verified fresh 2026-11-03T23:09Z)
State verified: issue #2019 is OPEN. No hard-stop labels (
held,user/owned,do-not-merge,do-not-auto-editall absent).The investigation this issue asks for is already delivered. Queue task 3338 (Lane D, 2026-10-29) posted the full capability report on this issue and observed a live worked example. All four LIST 4a questions are answered there:
opencode run.opencode-route/workhorse→ DeepSeek V4.1 Flash with no Muse process or token in the loop.--model opencode-route/<workhorse|specialist|summit|speed>per unit/workflow).systemctl --user+ per-job logs, OpenCode server API / OpenChamber session views for live sessions. Scheduling is not supervision; stall detection stays with the babysitter function (design: scheduled OpenCode preliminary babysitter — sweep sessions, fix easy stalls, escalate the rest #2021).Correction already on record (Drew, 2026-10-31): the "no native scheduler" verdict covers OpenCode only — OpenChamber does have native scheduled tasks, and #3026 uses them as its mechanism, with this investigation's systemd pattern as fallback.
Blockers / gates named: none blocking the investigation itself. The remaining consumers are gated by design: the placement synthesis #2024 is gated on its named inputs (this report is one of them), under epic #2055.
Fix path already enqueued (no new task needed from this triage):
opencode runwith per-job route (OPEN,queue/queued,priority/high) — the implementation follow-on filed by the investigation.queue/queued) — the OpenChamber-native path from the 2026-10-31 correction.Disposition: triage complete. This issue stays open as the investigation record feeding synthesis #2024 / epic #2055; its buildable follow-ons are already filed and queued as #2232 and #2174, so no duplicate issue or task is created here.