@maiife-ai-pub/workbench-tether
v0.1.5
Published
Gradus Workbench tether for opencode — presence, plan-time overlap prevention, and landing-queue submission for team-coordinated coding agents
Maintainers
Readme
@maiife-ai-pub/workbench-tether
Gradus Workbench tether for opencode — puts your coding agent on the team plane: live presence on the team board, plan-time overlap prevention against teammates' declared intents, and clean single-player degradation when the plane is off.
What it does
- Presence — registers the session on the org's team board and heartbeats every 30s with the files the agent is actually touching.
- Intent — on the agent's first file write, declares a write-set intent; widens it as the write set grows. If the plane reports an overlap with a teammate's live intent, the proposal ("queue after" / "negotiate the interface") is injected into the agent's context — a suggestion the agent reasons about, never an error.
- Degrade —
workbench_disabled, missing credits, bad token, network down: all read as "plane absent". Every hook becomes a no-op and the agent behaves exactly like stock opencode. Plane-absent is cached (5 min) so a dark plane costs one failed request, not one per tool call.
What's new in 0.1.5
- Activity-driven heartbeats — in
opencode runone-shot mode the 30s interval timer never fires, so sessions registered once and then went silent (no liveness, no usage). Beats now also ride the event bus, throttled to the same 30s cadence, so unattended builds stay live on the board. Interactive sessions keep the timer as belt-and-braces. - Final usage flush on dispose — accumulated token usage since the last beat is sent before the session releases, so the board's ended-session card shows the run's true totals.
What's new in 0.1.4
- Token usage on presence — per-model token usage is accumulated from
opencode's
message.updatedevents and reported on the presence heartbeat, so the team board can show live usage per session alongside the files being touched. - Board messages reach the agent — messages posted to the Workbench board are injected into the agent's context via the system-transform channel, and acknowledged on the next heartbeat so a message is never delivered twice.
- Heartbeat timer is resilient to a failed first beat — the heartbeat timer now starts unconditionally; if the first beat fails (dark plane, network blip), the timer still runs and retries on schedule instead of silently dying.
Setup
1. Get a token
An org owner must have enabled the Workbench (gradus.maiife.ai → Settings → Workbench) — it is off by default. Then mint an MCP token on vibecop.maiife.ai → Settings → "Plan Review MCP · Agent Auth" (raw value shown once; valid 90 days). Mint one per developer: presence identity derives from the token's minter, so a shared org token collapses the whole team into one board identity.
2. Add the plugin
// opencode.json
{
"plugin": ["@maiife-ai-pub/workbench-tether"]
}opencode installs the package automatically on next start.
3. Configure via environment
opencode passes plugins no options, so the tether reads env vars:
export GRADUS_WORKBENCH_TOKEN="<your mcp-scoped token>" # required
export GRADUS_WORKBENCH_CODEBASE="<GradusCodebase id>" # required
export GRADUS_WORKBENCH_PROJECT="<GradusProject id>" # optional — enables graph-aware overlap
export GRADUS_WORKBENCH_BASE_URL="https://api.gradus.maiife.ai" # default
export GRADUS_WORKBENCH_SURFACE="ide" # ide | cli | worker (default ide)Ask your org admin for the codebase and project ids (they identify the connected repo on the plane — surfacing them in Workbench settings is on the roadmap alongside per-dev token minting).
4. Verify
Start any opencode session — it appears on the team board (gradus.maiife.ai/board) within a heartbeat. The first file write declares an intent; overlaps with teammates come back as proposals in the agent's context ("queue after" / "negotiate the interface") — never errors.
Missing token or codebase id? The plugin loads and stays silent — single-player by definition, zero network calls.
Programmatic use
The main entry exports only the plugin function (opencode's loader invokes every function export as a plugin). The REST client and helpers live on subpaths:
import { WorkbenchClient } from "@maiife-ai-pub/workbench-tether/client";
import { extractFilePath, formatOverlapNote } from "@maiife-ai-pub/workbench-tether/helpers";WorkbenchClient speaks the Workbench REST surface (/workbench/*) with
the same degrade contract — every failure resolves to "plane_absent",
nothing throws.
Troubleshooting
| Symptom | Cause |
|---|---|
| Session never appears on the board | Workbench not enabled for the org (owner: Settings → Workbench), bad/expired token, or wrong GRADUS_WORKBENCH_CODEBASE |
| Appears, then vanishes after ~5 min | Session ended without dispose — stale rows are reaped automatically |
| No overlap notes despite teammates on the same files | Overlap needs a live teammate intent (their agent must have written the file this session), and hot-spot files (manifests, lockfiles, index.ts, docs, migrations) are exempt by design |
| Everything silent | That is the degrade contract working — check env vars are exported in the shell that launches opencode |
