JSON reads of the board — status --json and next --json (ka7fx)
Two read-only views of the board print one JSON object on one stdout line, for a program that narrates the board (the cyberine-taskboard plugin, a script, a status bar) instead of parsing the text views. Each carries a schema string; a field is only ever added under the same schema, and a rename or removal bumps its number. The full CLI and the taskboard bundle build both from the same module (src/tasks/boardJson.ts), so for the same board and the same directory they print byte-identical JSON. Warnings (lint findings, a CRLF manifest) still go to stderr; the scope and stale notices of the text views do not, because the JSON carries scope, hidden and stale itself. cyberine tasks board --json (the HTML page's data, with briefs, archive and journal) is unchanged and is a third, heavier read.
cyberine tasks status --json # board-status/1
cyberine tasks status --json --all # inside a submodule: every task, not only the submodule's
cyberine next --json # board-next/1 (`cyberine tasks next --json` is the same command)
node <plugin-dir>/cli/tasks.mjs status --json # the taskboard bundle, same bytes
node <plugin-dir>/cli/tasks.mjs next --jsonstatus --json (schema board-status/1) is the board view with counts and each task's effective status:
{"schema":"board-status/1","manifest":"/repo/.local/tasks/ACTIVE.md","scope":"","hidden":0,
"counts":{"doing":0,"todo":1,"waiting":1,"blocked":1,"backlog":1,"done":0,"forbidden":0,"unknown":0,
"ready":1,"stale":0,"recurring":0,"recurringDue":0,"pending":0},
"tasks":[{"id":"k5d45","title":"First task","status":"todo","baseStatus":"todo","eff":"todo",
"deps":[],"unmet":[],"blocker":"","reason":"","duplicateOf":"","path":"","owner":"",
"created":"2026-09-29","ready":false,"stale":false}],
"recurring":[{"id":"R1","title":"...","state":"DUE","days":3,"every":"1w","lastDone":"2026-09-19","exec":""}]}manifestis the absolute manifest path;scopeis the submodule path the view is limited to (""for the whole board) andhiddenhow many tasks that scope hides.tasksis in manifest order.statusis the effective status (manifest header plus the pending overlay),baseStatusthe manifest header alone, andeffthe display label the board page uses:waitingis a[todo]whose deps are not all done,blockeda[todo]with ablocker:,unknownan unrecognised bracket, otherwise the status.unmetlists the deps that are not done (archived ids count as done).readymarks a[backlog]task whose deps are met,stalea[doing]task pastNF_TASKS_STALE_DOING_DAYS(default 3). String fields the manifest does not set are"".countspartitionstasksbyeff(the eight status keys sum totasks.length), thenready,stale,recurring,recurringDue(NEW or DUE entries) andpending(overlay lines not yet reconciled). The text view'stodocount includes the waiting tasks; this one does not.
next --json (schema board-next/1) is the dispatch view, the same sets cyberine next prints:
{"schema":"board-next/1","manifest":"/repo/.local/tasks/ACTIVE.md","scope":"","hidden":0,
"counts":{"done":0,"runnable":1,"waiting":1,"blocked":1,"doing":0,"backlog":1,"forbidden":0,"duplicate":0},
"runnable":[{"id":"k5d45","title":"First task","priority":"","deps":[],"path":""}],
"waiting":[{"id":"kk12s","title":"Second task","unmet":["k5d45"],"cycles":[]}],
"blocked":[{"id":"kd6rf","title":"Fourth","blocker":"waiting on vendor"}],
"doing":[]}runnableis in dispatch order (p0first, then manifest order);priorityis""when the task sets none.waitingholds[todo]tasks with unmet deps andblockedthose held by ablocker:, the same wordsstatus --jsonuses. The text view ofcyberine nextlabels these two the other way round ("Blocked (deps not done)", "Waiting on external blocker"); the JSON follows the board'seffvocabulary so one reader needs one meaning.cycleslists the unmet deps whoseduplicate-of:chain loops.counts.doneis every id that satisfies a dependency, manifest[done]plus the archive, over the whole board even inside a submodule scope, exactly like the text header; the other counts are scoped. Duplicates (duplicate-of:) appear only incounts.duplicate.- An empty or missing manifest prints nothing on stdout and exits 1 with the same stderr message as the text view.
--jsonwith--dispatchexits 2: the JSON view is a read.
Known Limitations and Deferred Work: there is no JSON for status --summary, or the banner line; the banner already has cyberine tasks banner --json. Only the two schemas above are covered by the byte-identical promise; the text views still differ between the CLI and a branded bundle, whose messages name its own program. No selftest pins the shapes yet; they were compared by hand (cmp) between the full CLI and a branded bundle on a scratch board.
See what's runnable + dispatch by id — cyberine next
cyberine next derives the runnable / blocked / waiting sets from the project task manifest (.claude/TASKS.md or .local/tasks/ACTIVE.md) — the same deps + blocker logic the global oc-tasks tool's...
List + switch models — cyberine models, cyberine model
The catalog is an embedded offline seed (src/core/modelCatalog.ts) and the sole source of truth — there is no runtime cache to fall behind it. cyberine model use writes nothing but the one MODEL...