@exonomy/oc-worker
v0.1.12
Published
OpenCode in-process worker: dispatch one-shot prompts from a terminal into a running OpenCode Desktop server, with requests and responses persisted in SQLite.
Readme
oc-worker
An in-process worker for OpenCode. It lets a terminal dispatch a one-shot prompt into a running OpenCode Desktop server — no password, port, or HTTP probing — by writing a pending request into a SQLite database that the plugin polls from inside the server process.
The package ships two halves:
- The plugin (default export) — loaded by OpenCode. Runs inside the Desktop server process, claims pending request rows, creates or reuses a session, prompts the agent, and writes the response back to the row.
- The CLI (bin
oc-worker) — the terminal-facing half. Inserts a pending request and polls until the plugin marks it done or failed.
Install
Add the plugin to your OpenCode config so the server loads it:
{
"plugin": ["@exonomy/oc-worker"]
}The CLI is installed with the package:
npm install -g @exonomy/oc-workeror run directly:
npx @exonomy/oc-worker --helpUsage
oc-worker opencode/big-pickle "Explain the three-body problem"
oc-worker -m opencode/big-pickle --dir ~/projects/foo --wait-mode always --timeout 600 "Prompt text"
oc-worker -m opencode/big-pickle --project <project> --session ses_abc123 "Continue from where we left off"
oc-worker -m opencode/big-pickle --context context.json "What have our sources said about Hormuz?"
oc-worker assign --session ses_abc123 --project <project>The prompt is dispatched in-process by the plugin; the CLI prints the
response followed by the session name and ID (Name (ses_...)). The
response is printed as plain text (Markdown formatting stripped for the
terminal); the full Markdown stays in the database for the Desktop UI.
While a session answers, the CLI's live status line identifies the session
by title (session "Title" answering) when one exists, and by session id
otherwise.
Multiple CLI calls run concurrently: each terminal process writes its own
request row and polls its own result, and the plugin dispatches pending
requests through a bounded worker pool (MAX_CONCURRENT = 3), so launching
oc-worker from several terminals at once answers them in parallel through
the single plugin instance.
Sessions are pinned to a project directory so they appear in the Desktop UI:
--dir picks the project, and without it the CLI uses its own current
directory.
--project targets a specific project by its opencode project id or its
worktree directory, resolved against opencode's project list at dispatch time.
This is how prompts land on one project and then another from the same UI.
--context <file.json> grounds the answer. The file is a JSON object carrying
the selected sources and the publication date range (see docs/plans/plan.md
"Grounded-answer contract" in the bonjourno repo for the shape). Its content
is embedded verbatim in the request row, and the plugin renders it into the
model's system prompt (the native system field on the prompt call), so the
agent answers only from the given sources within the window.
Model canon
Free models come and go quickly, and even the providers' own catalogs list
models that no longer answer. oc-worker models maintains the local canon —
a probe-verified registry stored in oc-worker.db:
oc-worker models # list (dead models hidden)
oc-worker models --refresh # pull live catalogs + probe every NIM chat model
oc-worker models --json # machine-readable output for dropdowns/scripts
oc-worker models --status verified --provider nvidia--refresh pulls NVIDIA NIM's live /models list and OpenCode Zen's free
tier, then probe-verifies each NIM chat model with a 1-token call. Zen free
models are tracked from the local catalog and become verified automatically
the first time a dispatch through oc-worker succeeds against them; failures
are classified (rate-limited for 429s, dead for 410/404s). The NVIDIA key
is read from NVIDIA_API_KEY or your opencode.jsonc.
Assigning sessions to projects
Sessions started outside a git project land in opencode's global bucket,
which the Desktop UI does not surface. oc-worker assign moves such a
session to a real project:
oc-worker assign --session ses_abc123 --project <project>The CLI records the request and the plugin performs the write inside the
opencode server process (against opencode's own database), so the app never
touches opencode's database directly. The assignment only changes which
project owns the session (project_id); the session's directory is kept as
the truthful record of where it ran.
Options
| Option | Description |
| --- | --- |
| -m, --model <provider/model> | Model to use, e.g. opencode/big-pickle. |
| --dir <path> | Project directory for a new session (default: the CLI's current directory). |
| --project <id or directory> | Target a specific project, for working across multiple projects at once. Accepts an opencode project id or its worktree directory; the session is pinned to that project's directory. Mutually exclusive with --dir. |
| --session <id> | Send the prompt into an existing session. |
| --context <file.json> | JSON file with {date_from, date_to, sources: [...]}; the plugin renders it into the model's system prompt to ground the answer. |
| --wait-mode <mode> | confirm (default), always, or never. |
| --timeout <s> | Silent wait before confirmation kicks in (default 120). |
| --confirm-interval <s> | Seconds between "keep waiting?" prompts (default 30). |
| -h, --help | Show help. |
Data
Requests and responses persist in a SQLite database. The default location is
~/.local/share/oc-worker/oc-worker.db. Override it with the OC_WORKER_DB
environment variable.
Requirements
- OpenCode Desktop running, with the plugin enabled
- Node.js 22.5 or newer (for
node:sqlite)
