op-thread gives OpenCode agents a durable peer-thread orchestration surface. A root agent can create independent root sessions, run several in parallel, inspect their messages, send explicit steer or queue follow-ups, and wait for them to become idle.
Peer threads are ordinary OpenCode sessions. They remain visible and resumable like sessions created by a user; they are not task subagents and are not assigned a parentID.
| Tool | Purpose |
|---|---|
create_thread |
Create a root session in the caller's directory and start it with a prompt |
list_threads |
List peers owned by the current orchestrator and their running, queued, failed-queue, or idle state |
read_thread |
Read an owned peer's durable session state and recent messages |
send_message_to_thread |
Deliver a follow-up using explicit steer or queue semantics |
wait_for_thread |
Wait with a bounded timeout until a peer is idle |
steer inserts the message immediately so the active OpenCode loop observes it at its next safe boundary. queue persists the message in the plugin registry and dispatches it only after the target becomes idle and the orchestrator has capacity. Queue dispatch uses atomic claims and idempotent OpenCode message IDs so restarts do not duplicate delivery.
- A session may target only peers it created through
create_thread. - Ownership survives OpenCode restarts in
~/.local/share/op-thread/registry.sqlite. - One orchestrator may run at most fifteen owned peers concurrently by default. SQLite activation leases enforce this limit across creation, steering idle peers, queued-message dispatch, and cooperating OpenCode processes.
- Managed peers cannot recursively call
create_thread, preventing exponential spawn chains. - Queue workers handle only peers from their own directory, atomically claim work across processes, and stop retrying after eight failed delivery attempts.
wait_for_threadalways has a timeout and never relies on OpenCode's currently unavailable v2 wait endpoint.- Peers run only in the creator's current directory. Agents cannot use this plugin to target arbitrary directories.
The limits can be adjusted in the plugin tuple, up to the hard validation bounds:
bun install
bun run typecheck
bun test
bun run check
bun run buildThis repository's opencode.jsonc loads dev/server.ts directly. Start a new OpenCode process from this directory after installing dependencies:
opencodeOpenCode does not hot-reload plugins. Restart it after changing source or configuration.
Add the absolute development entry to ~/.config/opencode/opencode.json to make the tools available in every project:
{
"$schema": "https://opencode.ai/config.json",
"plugin": [
"file:///absolute/path/to/op-thread/dev/server.ts"
]
}Keep bun install completed in this checkout, then restart OpenCode. Remove the file entry before installing a published package to avoid loading the plugin twice.
Ask the root agent:
Break this goal into independent workstreams. Use
create_threadfor up to fifteen parallel peers. Uselist_threadsandread_threadto monitor them,send_message_to_threadwith explicit steer or queue delivery when their direction changes, thenwait_for_threadand integrate their results.
The creator receives each peer's session ID. That capability is also recorded in the durable ownership registry, so a resumed orchestrator can continue managing the same peers.
- OpenCode only. Pi is not supported.
- Peer creation and steering use the public client supplied to OpenCode server plugins, including embedded
opencode runsessions that do not expose a listening HTTP port. - Execution remains process-local because OpenCode's current session runner is process-local.
- The plugin does not merge code or create worktrees. Parallel peers sharing one checkout must coordinate file ownership, or the orchestrator should assign read-only/non-overlapping work.
{ "$schema": "https://opencode.ai/config.json", "plugin": [ ["@op1/op-thread", { "maxConcurrent": 20 }] ] }