@becos-ai/becos-opencode
v0.37.1
Published
becos for OpenCode (formerly @becos-ai/oc-codecollab): capture sessions to and recall memory from your team's becos memory. Redacted command, output and code evidence is captured by default (each can be turned off); reasoning is not. Bundles a vendored Py
Readme
@becos-ai/becos-opencode
0.37.0: opt-in automatic recall (VONIC_CODECOLLAB_RECALL_INJECT=1) no longer breaks the
provider's prompt cache: recall is stored on each prompt's message instead of the system prompt.
See CHANGELOG.md.
becos for OpenCode. This package was @becos-ai/oc-codecollab until 0.34.x; from 0.35.0 it is
@becos-ai/becos-opencode (see Upgrading from codecollab).
Generated files (0.34.4): the project context declares enabled native file-persistence ownership. The model must not duplicate hook uploads through conversational save tools. Opt-outs/Coding Mode do not silently enable a fallback, and an enabled hook is not a verified upload receipt.
Capture + recall for Opencode. Each turn's prompt and the assistant's reply are shipped to your team's becos memory, and past sessions are recalled back into the model — so the why behind changes survives the session that produced it.
This page is the user guide. Everything needed to install, sign in, configure and troubleshoot is below. If you have access to the source repository and are working on the plugin, read
docs/DEVELOPMENT.mdthere instead — architecture, the vendored deliverer, the payload contract and the release process live in that file and are deliberately not published here.
For the complete engineering reference covering captured data, remember timing, recall/injection,
event resolution, Claude Code differences, and adapter-porting invariants, see
docs/CODECOLLAB_DATA_AND_RETRIEVAL_REFERENCE.md.
- Capture (out): the user prompt, the assistant's text reply, and resolved repository identities. Command, tool-output and code bodies are redacted, capped and stored as typed JSON; hidden reasoning stays excluded; structural paths are repository-relative; the home prefix is scrubbed from captured bodies.
- Recall (in): a
vonic_querymemory digest reaches the model, so answers benefit from past sessions. - Observed-only capture: a turn is captured only if its prompt passed through this plugin
(
chat.message) — it was loaded and enabled when you sent it. History from before the plugin loaded, a forked session's copied turns, and turns sent while it was off are never uploaded automatically; backfill (below) is the explicit path for history. - Handoff (in): each new primary session fetches prior-turn evidence for the git-origin
repository from you and your becos team (each turn names its author) once, in the
background (12k chars, ≤30 turns from the last 5 days, compact detail, no reasoning). A checkpoint
fetched for another repository or branch than the session is on when it binds is dropped. The first prompt never waits for it; once ready it is attached as a
<repository-handoff>block to the next user message. It excludes the active session, uses the current branch when available, and falls back to repository-wide history on detached HEAD. Without anorg/reposlug fromgit origin, it does not contact the server.becos_handoffreports that handoff's status, or fetches once on demand when no automatic handoff exists. - Shared handoff pilot (team-to-team, on by default;
VONIC_CODECOLLAB_SHARED_HANDOFFS=0opts out): the nativebecos_handles,becos_share, andbecos_sharedtools let the agent resolve teammates, prepare a reviewable package, and inspect the team inbox./becos-share @handle [message]drafts a package for review (sending is a separate, later confirmation), and/becos-shared [request]lists the inbox — packages addressed to your handle first — and shows, accepts, declines or downloads one on request. Both commands are static templates that route your text to those tools (never into a shell line), written to~/.config/opencode/command/at plugin load while the flag is on and removed when it is off; like every OpenCode command, they appear on the next restart. Claiming a handle, sending a reviewed draft, accepting/declining a package, and requesting an artifact download require an explicit user request and a real confirmation prompt: each of those five actions calls the host's permission request (becos_shared_handoff, defaulted toaskby the plugin) inside the tool, before any server call, and aborts without sending, changing or disclosing anything if you decline. Read-only actions (list,get,seen,me,search,resolve, anddraft, which never sends) do not prompt. A host that cannot show the prompt fails closed for the mutating actions. Draft files are workspace-relative and the shared Python core rejects escapes, symlinks, sensitive paths, unsupported types, credential-shaped text/code/JSON, changed path linkage, more than 10 files, or more than 25 MiB. Review reads each file once and upload uses those exact bytes without reopening the path; PDFs and images stay opaque. A draft can carryproject_keyplus up to 50 exactsource_event_ids, which the server resolves to stored evidence; packages report a derivedsent/seen/picked_upstatus withseen_at,seen_by_me,seen_by_me_atandnotified_me_at, andgetalso returnsproject_key,source_event_idsand that evidence (presented to the model as retrieved team evidence, not instructions). Inbox refresh runs in the background at plugin load and after each user message; newly addressed packages produce one TUI toast, are recorded on the server throughseen …notifiedso delivery state is durable rather than only local, and are then consumed so OS notifications do not repeat — all non-blocking and fail-open. Intentional tenant-wide visibility is unchanged. - Automatic file persistence — projects without a git repository only (part of the same pilot
flag): when a session's project is a
nocode:project, the files that turn created or modified are snapshotted and uploaded in the background after the turn, so the agent's own output is not the only copy. Git-repo sessions are unchanged: nothing is persisted automatically. Persisted files are private to you — the server lists only your own — and a teammate sees one only through the normal confirmed share flow, by naming it in a draft (persisted_file_ids/persisted_paths), seeing it in the draft review, and approving the send prompt. Attaching is not sending. The same screening as an explicit share applies (workspace confinement, symlink/linkage checks, extension allowlist, sensitive paths, credential-shaped content), except that a rejected file is skipped instead of failing the turn; at most 10 files / 25 MiB per turn; unchanged bytes are never re-uploaded; files expire after 30 days. SetVONIC_CODECOLLAB_PERSIST_FILES=0to turn just this off. It never blocks or delays a turn.
Privacy contract
Visible prose and deterministic evidence are retained. Command, output and code bodies default ON
(schema_version: 2) and each can be disabled independently — see the flag table below. All of them
must pass secret redaction, sensitive-path withholding and byte caps before persistence or delivery.
Hidden reasoning is excluded unless trusted user configuration explicitly enables it.
Outputs or edits targeting .env*, *secret*, *.pem, *.key, id_rsa* or credentials* are
withheld entirely.
Requirements
python3 on PATH — the deliverer that does the capture and recall work is Python.
Install
Pin an exact version in ~/.config/opencode/opencode.jsonc; opencode installs it on next launch and
caches by version, so bumping the pin is the upgrade:
{ "plugin": ["@becos-ai/[email protected]"] }Then fully quit (Cmd-Q) and relaunch opencode.
npm view @becos-ai/becos-opencode version # latest published
npm view @becos-ai/becos-opencode versions # every published versionUpgrading from codecollab
The plugin was published as @becos-ai/oc-codecollab (tools codecollab_*, commands
/codecollab-*, CLI codecollab-oc) up to 0.34.x. From 0.35.0 it is @becos-ai/becos-opencode.
Your sign-in, pending turns and history carry over: local state stays in ~/.cache/codecollab/,
the token script stays ~/.config/opencode/codecollab-mint-jwt.sh, the config file stays
~/.config/opencode/oc-codecollab.env, and every VONIC_* setting (including VONIC_CODECOLLAB_*)
keeps its name, so you do not sign in again.
In
~/.config/opencode/opencode.jsonc(andtui.json, if you registered the sign-in dialog there), replace the old pin:// before { "plugin": ["@becos-ai/[email protected]"] } // after { "plugin": ["@becos-ai/[email protected]"] }Fully quit (Cmd-Q) and relaunch opencode. On first load the plugin removes the
/codecollab-*command files it wrote earlier (only its own, recognised by their marker) and writes the/becos-*ones; like every OpenCode command, they appear on the next relaunch.
If you only bump the old package, @becos-ai/[email protected] is a retired stub: it captures
nothing, recalls nothing and has no tools or commands. It only shows
codecollab is now becos. Change your opencode plugin pin to
@becos-ai/[email protected], then quit and relaunch opencode. Your sign-in and history carry over.
when opencode starts and on a session's first prompt. Having both pinned never captures twice.
What you will notice:
| Before | Now |
| --- | --- |
| /codecollab-login, -login-text, -backfill, -project, -rulebook, -share, -shared, -team | /becos-login, /becos-login-text, /becos-backfill, /becos-project, /becos-rulebook, /becos-share, /becos-shared, /becos-team |
| tools codecollab_recall, codecollab_handoff, codecollab_status, codecollab_team, codecollab_rulebook, codecollab_project, codecollab_handles, codecollab_share, codecollab_shared | becos_recall, becos_handoff, becos_status, becos_team, becos_rulebook, becos_project, becos_handles, becos_share, becos_shared |
| permission keys codecollab_shared_handoff, codecollab_project_switch, codecollab_backfill_deliver | becos_shared_handoff, becos_project_switch, becos_backfill_deliver |
| CLI codecollab-oc login / codecollab-oc backfill (bunx @becos-ai/oc-codecollab …) | becos-oc login / becos-oc backfill (bunx @becos-ai/becos-opencode …) |
| toasts CodeCollab recall: …, CodeCollab: … | becos recall: …, becos: … |
Permission rules: if your opencode.json permission (or an agent's tools / permission
block) names codecollab_shared_handoff, codecollab_project_switch, codecollab_backfill_deliver
or a codecollab_* tool, rename it to the becos_* name; the old names no longer match anything,
and an unset key falls back to ask. Gateway tools (vonic_*, e.g. vonic_resolve_event) keep
their names.
Sign in
/becos-login inside the opencode terminal UI opens a sign-in dialog:
- the sign-in link on its own line — click it or press
cto copy it, Cmd/Ctrl+click to open it, Enter to open it in your browser (opened automatically when opencode runs on your own machine) - Tab to paste the code the browser page shows; Esc cancels
Over SSH, opencode can't open a browser on your computer; copy or Cmd+click instead. Copying uses OSC 52, so it reaches your local clipboard through SSH and tmux — in iTerm2, enable Settings → General → Selection → Applications in terminal may access clipboard.
The dialog is a TUI plugin (exports["./tui"]). opencode plugin @becos-ai/becos-opencode registers
it; for a local checkout, add the package to ~/.config/opencode/tui.json:
{ "plugin": ["file:///path/to/becos-oc-plugin"] }Clients without the terminal UI (web, desktop, opencode run) use the text fallback
/becos-login-text, then /becos-login-text <UUID>. Or from a terminal:
bunx @becos-ai/becos-opencode loginNo gateway URL and no environment variables — it resolves the hosted gateway, mints its own
short-lived credential, and takes your identity from the login. Pass --gateway only for a
self-hosted gateway.
Backfill — sweep PAST sessions into memory
Live capture only records turns it observes, going forward. Backfill ingests history, normalized
through the same privacy strip as live capture. Safe to Ctrl-C; re-running is idempotent. Forked
sessions (OpenCode titles them … (fork #N)) are never backfilled: their copied turns are the
parent's. The model-callable backfill tool stops for a confirmation prompt
(becos_backfill_deliver) before it ingests anything.
becos-oc backfill # dry run: projects → sessions → turns
becos-oc backfill --project myrepo # filter by directory substring
becos-oc backfill --deliver # upload and hand off to the worker
becos-oc backfill --deliver --watch # then poll status to completion
becos-oc backfill --deliver --campaign myrun # name the batch (stable, resumable)Requires login first, and opencode on PATH (or set OPENCODE_BIN) so a headless server can read
history. Limitation: opencode's global scratch project (non-repo "Default Project" sessions) is
skipped — those turns are unscoped and would be dropped anyway. The dry run prints every project it
scanned, so coverage is auditable.
Three ways to run it:
/becos-backfillin the opencode TUI. The plugin installs this command automatically on load, writing~/.config/opencode/command/becos-backfill.mdwith absolute paths (resolved via your login shell, so it works in a GUI-launched app with a minimal PATH). It appears on the next relaunch after the plugin first loads.- Ask the agent — a model-callable
backfilltool, dry-run by default: it reports what would be ingested and only ingests when you ask it to deliver. Scope is the current project unless you ask for all projects. - The terminal CLI above — the deterministic option.
Passive recall via MCP
Register becos as a remote MCP server so the model can call vonic_query / becos_get on demand.
Add to opencode.json:
{
"mcp": {
"becos": { "type": "remote", "url": "https://<your-gateway>/mcp/", "enabled": true,
"headers": { "Authorization": "Bearer <gateway-JWT>" } }
}
}Opencode also supports OAuth for remote MCP (RFC 7591 dynamic client registration).
Configuration
A hosted install needs none of this — install, sign in, done. The gateway, endpoint, identity mode, credential and author are all resolved from your login. The variables below are overrides.
Behaviour flags are read from ~/.config/opencode/oc-codecollab.env or
<project>/.oc-codecollab.env. Privacy-expanding capture flags and their caps are accepted only
from the trusted user-global file or the inherited process environment — a repository's
.oc-codecollab.env cannot enable or loosen them.
| Flag | Default | Effect |
|------|---------|--------|
| VONIC_CODECOLLAB_PROVENANCE | on | Inject repo-provenance instructions each turn (0 disables). |
| VONIC_CODECOLLAB_ENTITY_HISTORY | off | 1: a file's recorded history is appended to its first read result; the first edit of a file never shown it fails once with the history (the retry applies). Once per file per session, fail-open |
| VONIC_CODECOLLAB_ENTITY_HISTORY_CHARS | 2500 | Per-file history budget (1000–4000) |
| VONIC_CODECOLLAB_RULEBOOK | off | 1: your accepted repository rules (/becos-rulebook, becos_rulebook tool) ride the system prompt as "## Rulebook", read from a local cache refreshed in the background; the tool/command work either way |
| VONIC_CODECOLLAB_PROJECTS | on | Every session is saved to a project; 0 opts out. A git repo with an origin remote is its own project (a toast says so; it can't be changed). Elsewhere the project comes from your entry in the nearest .becos-project (never ~ itself; a toast names it), else a dialog asks (your projects, the team's, or a new one) and the answer is written there. /becos-project or the becos_project tool switches for the session only; unanswered by the second turn, a project is named for you (toast). Needs the TUI plugin (tui.json) for the dialog |
| VONIC_RULEBOOK_TIMEOUT | 20 | Seconds for one vonic_rulebook call |
| VONIC_CODECOLLAB_WORKING_AGREEMENT | off | 1: the shared "Working agreement" (engineering rules + definition of done) is the first system-prompt section; only exactly 1 enables it; not in legacy instructions mode |
| VONIC_ENTITY_HISTORY_TIMEOUT | 8 | Seconds the lookup may take before the tool runs without it |
| VONIC_CODECOLLAB_RECALL_TOOL | on | Offer the visible becos_recall tool + its instruction (0 disables the instruction). Repeatable within a turn, not once-per-turn. |
| VONIC_CODECOLLAB_RECALL_SUBAGENTS | on | Let subagents (agents configured with mode subagent) call becos_recall. 0 restricts it to the primary agent; an all-mode agent is never restricted (ambiguous — fails open). |
| VONIC_CODECOLLAB_RECALL_FEEDBACK | on | Ask the model for the [recall-relevance] grade line (0 disables). |
| VONIC_CODECOLLAB_HANDOFF_AUTO | on | Background repository handoff for every new primary session. 0 disables it; becos_handoff then fetches on demand (once per session). |
| VONIC_CODECOLLAB_SHARED_HANDOFFS | on | Shared-handoff tools and non-blocking inbox/toast refresh are enabled by default; 0 opts out. Mutating actions require an explicit user request and an approved becos_shared_handoff permission prompt; when enabled the plugin registers that key as ask (your own setting for it wins). Explicit empty/invalid values disable it. |
| VONIC_SHARED_HANDOFF_TIMEOUT | 30 | Seconds for one shared-handoff server or artifact operation. |
| VONIC_CODECOLLAB_PERSIST_FILES | on | Automatic per-turn persistence of session-generated files, in projects without a git repository only and only while VONIC_CODECOLLAB_SHARED_HANDOFFS=1. 0 turns it off and leaves shared handoffs working. Persisted files are private to you until you share them; 10 files / 25 MiB per turn; 30-day retention. |
| VONIC_CODECOLLAB_RECALL_INJECT | off | Opt-in automatic recall. Only 1 enables it: recall is looked up once when you submit a prompt (it may hold the prompt up to 20 s) and stored as a hidden part on that prompt's message, never in the system prompt, so the provider's prompt cache keeps working. It is saved with the session (and appears in exports) but never captured. When off, memory reaches the model solely via the becos_recall tool. |
| VONIC_RECALL_MAXCHARS | 12000 | Cap recalled opaque text. Values 1..20000 are honored; larger values clamp to the hard maximum 20000; unset, blank, malformed, zero or negative values fall back to 12000. Use VONIC_RECALL_ENABLED=0 to disable recall. |
| VONIC_CAPTURE_COMMANDS | on | Capture redacted typed tool inputs (2 KB per text field). 0 disables. |
| VONIC_CAPTURE_OUTPUTS | on | Capture redacted tool outputs (8 KB per output: 5 KB head + 3 KB tail). 0 disables. |
| VONIC_CAPTURE_CODE | on | Capture redacted patches, edit bodies, writes and visible prose code fences (16 KB per field). 0 disables. |
| VONIC_CAPTURE_THINKING | off | 1 captures assistant reasoning, via the trusted global configuration path only. |
| VONIC_CAPTURE_ASYNC_DELIVER | on | Any value other than 1 forces synchronous delivery. |
| VONIC_HANDOFF_TIMEOUT | 30 | Timeout (seconds) for the read-only vonic_repository_checkpoint call. |
| VONIC_CODECOLLAB_DEBUG | off | 1 logs to ~/.cache/codecollab/oc-plugin.log, and the injected digest to oc-injected.log. |
Recall has three practical modes:
| Mode | RECALL_INJECT | RECALL_TOOL | Behaviour |
|------|-----------------|---------------|-----------|
| Tool-only (default) | 0 | 1 | The agent calls becos_recall first; its visible result persists in the transcript. |
| Inject-only | 1 | 0 | Each eligible prompt gets its own recall, attached to that prompt, without instructions to call the visible tool. |
| Hybrid | 1 | 1 | Each eligible prompt gets its own recall, attached to that prompt; the visible tool is reserved for targeted later calls with a standalone query. |
In hybrid mode, automatic recall searches with the current user message. A targeted tool query
replaces that original search text rather than narrowing or appending to it. Do not make an opening
tool call without query, because the shared per-turn cache would return the same automatic result
and the visible output would duplicate it in the transcript.
Captured bodies ride in a structured code_changes JSON object (up to a 90 KB budget). The small
capture_context object stays a body-free index under the server's 32 KiB metadata limit.
Troubleshooting
Run with VONIC_CODECOLLAB_DEBUG=1. Configuration failures print a [becos] WARNING: line
naming the cause, and every delivery outcome is logged to ~/.cache/codecollab/delivery.log — a
status=succeeded line means a turn reached memory.
Licence
Apache-2.0.
