## Summary - OpenCode **2.2.5** becomes the **recommended** (qualified) runtime. The **2.2.3 minimum** and the 2.1.0 `@opencode/client`/`plugin`/`schema` pins stay: neither 2.2.4 nor 2.2.5 changes a contract CodeNomad consumes. - `RECOMMENDED_OPENCODE_VERSION` is 2.2.5, and the reviewed-publication shortcut in `contractProfile` lists 2.2.3 and 2.2.5; other versions, 2.2.4 included, keep negotiating their authenticated schema. The CI `latest` lane already resolves the latest stable CLI. - Help (all ten locales), READMEs, `CONTRIBUTING.md`, `dev-docs/OPENCODE_COMPATIBILITY.md` and the architecture skill state two separate versions again: minimum 2.2.3 with its reason, recommendation 2.2.5. ## Contract review (v2.2.3 → v2.2.4 → v2.2.5; 31 + 19 commits) Reviewed from the exact tags `v2.2.3` (`082ac6281f`), `v2.2.4` (`45898d0f85`) and `v2.2.5` (`9bbb8ce18c`), the published npm packages, and an authenticated OpenAPI dump from each official CLI running in its own sandbox. The [changelog](https://opencode.ai/changelog) has full notes for 2.2.4 and 2.2.5 (both 30 October); everything below was also checked against the commit log and source. CodeNomad side: `origin/dev` `605820669`. **Headline:** neither release changes a contract CodeNomad consumes. 2.2.4 adds opt-in **artifacts** (seven `/api/experimental/artifacts` operations, four tools, a plugin hook), **renamable persistent terminals**, and moves background-job recovery markers from `kv` into a new **`job` table**. 2.2.5 is a bug-fix release; its one schema change is that `compaction.buffer` accepts a percentage such as `"20%"`. The image tool contract adopted in #1209 (`experimental_image_generate`, on by default) is unchanged through 2.2.5, and still nothing writes `session_part`. - **Authenticated OpenAPI:** 134 → **138** → 138 paths, 162 → **169** → 169 operations, schemas 351 → 362 → 363. - **Added operations (2.2.4):** `GET /api/experimental/artifacts/providers`, `GET|POST /api/experimental/artifacts`, `GET|PATCH|DELETE /api/experimental/artifacts/{artifactID}`, `GET /api/experimental/artifacts/{artifactID}/view/*` ([#60351](https://github.com/anomalyco/opencode/pull/60351)). None removed in either release. - **Changed operations (2.2.4):** `GET /api/event`, where the `types` filter enum gains `persistent-pty.updated` and `artifact.updated` (94 → 96 types, none removed). `PUT /api/experimental/persistent-pty/{ptyID}` can also rename (`title`; `null` clears it), `size` becomes optional, and a 501 `PtyFeatureUnsupportedError` is returned while an older terminal service can't rename ([#60329](https://github.com/anomalyco/opencode/pull/60329)). - **Changed operations (2.2.5):** none. - **Consumed schemas:** same family selector as the 2.2.3 review, 97 schemas at every version. - 2.2.3 → 2.2.4: 95 byte-identical. The two that change, `PersistentPty.Info` (+ `userTitle`, nullable, required) and `PersistentPty.UpdateInput` (`size` optional, + `title`), are both additive. - 2.2.4 → 2.2.5: all 97 byte-identical. - `V2EventEncoded`, `Session.*`, `Form.*`, `Permission.*`, `Prompt*`, `Event.*`, `Location.*`, PTY/Shell are byte-identical from 2.2.3 to 2.2.5. - **`Config.InfoEncoded`:** 2.2.4 adds `experimental.artifacts` (boolean, opt-in). 2.2.5 turns `compaction.buffer` into `Config.Compaction.Percent | integer` ([#60647](https://github.com/anomalyco/opencode/pull/60647)). `experimental.image_generate`, `experimental.media_blob` and `experimental.schedules` are unchanged. - **Admission:** every predicate in `compatibility/negotiate.ts` (unchanged on origin/dev) holds on 2.2.3, 2.2.4 and 2.2.5. `contractProfile` lists only `2.2.3` as reviewed, so 2.2.4/2.2.5 are admitted through authenticated contract recognition. - **Instance proxy:** the allowlist is unchanged on origin/dev. No added or changed route is proxied: artifacts and persistent PTYs are outside it. The proxied `GET /api/config` returns the additive config fields above. - **Published declarations** (2.2.3 → 2.2.5): - **Client:** 185 → **192** → 192 methods. 2.2.4 adds `experimental.artifacts.{providers,list,create,get,update,delete,view}`, the artifact and `PersistentPtyUpdated` types, and `PtyFeatureUnsupportedError`. It removes `createPtyClient`/`PtyConnectInput` from `@opencode/client/solid/pty`, which CodeNomad doesn't import. 2.2.5 adds `ConfigCompactionPercent`. - **Schema:** 2.2.4 adds the `artifact` module and `PersistentPty.Updated`; 2.2.5 adds `config/compaction` `Percent`. - **Plugin:** 2.2.4 adds `effect/artifact` and `promise/artifact` and `ctx.experimental.artifact` (`transform`, `reload`). 2.2.5 has no export changes. - **Typecheck:** the server and UI typecheck with **0 errors** against the 2.2.4 and 2.2.5 client/schema/plugin/effect declarations. The pinned 2.1.0 control is also clean. - **Host modules:** the bundles' host imports are identical to the 2.2.3 review. A probe plugin in an isolated **2.2.4** and **2.2.5** daemon resolves every module and binding. `runtime-modules.ts` is unchanged from v2.2.3 to v2.2.5. - **Host Effect:** stays **4.0.6** (`bun.lock` sha512 identical; published `dependencies.effect` 4.0.6). - **Persistent PTY binary:** the 2.2.4 and 2.2.5 CLIs ship `@opencode/pty` **0.4.0** (string `opencode-pty 0.4.0` in the Windows binary; 2.2.3: `0.3.3`). `process-daemon-v0.4.0` adds only terminal renaming ([#60324](https://github.com/anomalyco/opencode/pull/60324)): an additive `rename` request and `features: ["rename"]` with an unchanged `PROTOCOL_VERSION`. CodeNomad only lists persistent PTYs (worktree deletion guard) and reads `status`/`cwd`. - **Private native services:** the keys (`LocationServiceMap`, `Form`, `Permission`, `Location`, `Job`, `Database`, `Session`, `Bus`, `Shell`) and the members CodeNomad calls are unchanged. The changes are additive: `Job.cancelSession` (2.2.4), `Permission.allows` (2.2.5; never asks, used by `edit` to decide whether to quote file lines), and `Session.remove` now calls `jobs.cancelSession`. The Missions recurrence clock calls `Job.get/start/cancel`. Its Job metadata carries no `sessionID`, so deleting a session doesn't cancel it. - **Storage:** one migration, `20261030054400_job` (2.2.4, [#60491](https://github.com/anomalyco/opencode/pull/60491)). It creates `job`, copies every `kv` row `job.background/%` into it and deletes those `kv` rows. 2.2.5 adds none. - CodeNomad reads only its own `kv` keys (Missions, pruning receipts and claims), never `job.background/*`. - Native migration 2.2.3 → 2.2.4 passes. Every 2.2.4/2.2.5 fixture DB inspected holds the `job` table, **0** `job.background/` rows and no leftover `schedule:leader` lease. - **`session_part`:** still **not written**. `history.ts`/`projector.ts` are unchanged from v2.2.3 to v2.2.5, the projector still only rewrites existing part rows, and every inspected 2.2.4/2.2.5 fixture DB has **0** rows. The forward risk from the 2.2.3 review stands (Recommendations). - **Behavior changes checked** (plain-language list in [What users will notice](#what-users-will-notice)): - **Image tool** (#1209 contract): `image-generate.ts` is unchanged from v2.2.3 to v2.2.5. 2.2.4 refactors restart recovery into one `restartMessage` but keeps `metadata.source: "experimental_image_generate"`, `jobID`, `state`, `path` and the `<image id state>` notice text. Design companion, activation, content and image settings pass natively on 2.2.4. - **Schedules** (2.2.4, [#60478](https://github.com/anomalyco/opencode/pull/60478), then `da87c475a7`): the loop now runs in every server process, including `opencode serve`, and elects a leader through a `kv` lease `schedule:leader` (claimed at boot, released when there are no active schedules). Firing stays opt-in (`experimental.schedules === true`). CodeNomad uses neither OpenCode schedules nor that key; Missions recurrence uses its own storage and the Job service. - **Sessions:** deleting a session now cancels its running background jobs (shell, image, subagent) and drops their markers (2.2.4). That is the intended upstream cleanup; CodeNomad's session deletions (blank-session cleanup, temporary workspaces) get it automatically. - **Events:** `persistent-pty.updated` and `artifact.updated` reach CodeNomad's shared event relay. The relay routes generically (`instance-events.ts`), the 2.1.0 client's SSE reader doesn't validate types, and the UI handles neither type. The native relay suite passes on 2.2.4. - **Tools** (2.2.5): a model call to `bash` runs as `shell` with shell permissions, and the result carries a note ([#60687](https://github.com/anomalyco/opencode/pull/60687)). CodeNomad already groups and renders `bash` and `shell` alike (`message-part-grouping.ts:48`, `tool-call/utils.ts`). `read`/`edit` failure texts are richer ([#60688](https://github.com/anomalyco/opencode/pull/60688), [#60689](https://github.com/anomalyco/opencode/pull/60689)). - **Compaction** (2.2.5): the prompt is capped at the context window when a catalog's input limit is larger ([#60660](https://github.com/anomalyco/opencode/pull/60660)), and `compaction.buffer` may be `"N%"`. CodeNomad never reads or writes `compaction.buffer`. LiteLLM context errors now trigger compaction ([#60692](https://github.com/anomalyco/opencode/pull/60692)). - **Reasoning replay** (2.2.5, [#60498](https://github.com/anomalyco/opencode/pull/60498)): reasoning is no longer re-sent as plain text after a model switch, and interrupted or errored reasoning is dropped from the request. This changes provider requests only; stored transcripts and `Session.Message.*` are byte-identical. - **MCP** (2.2.5): stdio messages over 10 MiB no longer disconnect a server ([#60694](https://github.com/anomalyco/opencode/pull/60694)), and an idle Location no longer restarts its MCP servers right after shutting down ([#60668](https://github.com/anomalyco/opencode/pull/60668)). - **Providers:** a Console-supplied provider can now be overridden by user, project and remote config (2.2.4). The Claude Agent provider only replaces Claude Code's `/login` hint with `claude auth login` in its errors ([#60592](https://github.com/anomalyco/opencode/pull/60592)); the guided setup ([#60603](https://github.com/anomalyco/opencode/pull/60603)) is OpenCode Desktop only. The provider ID (`Provider.ID.claudeAgent`) and its use of Claude Code's own login are unchanged, so CodeNomad's `claude-agent` quota reader (#1214) is unaffected. - **Service lifecycle:** the CLI now adds `127.0.0.1,localhost,::1` to `NO_PROXY`/`no_proxy` for itself and its children ([#60441](https://github.com/anomalyco/opencode/pull/60441)), so loopback traffic from daemon-hosted code, CodeNomad's plugins included, bypasses environment proxies. CodeNomad sets no proxy variables. - **Code Mode, Forms, permission prompts, media blobs:** no source changes from v2.2.3 to v2.2.5 (`packages/codemode` only bumps its version). The Code Mode run-to-completion regression passes on 2.2.4: `{ total: 2000, beforeAwait: 1000, count: 1000 }`. - **`@opencode/ai`:** one `ai` object for Promise and Effect ([#60516](https://github.com/anomalyco/opencode/pull/60516); left out of the changelog by [#60631](https://github.com/anomalyco/opencode/pull/60631)). CodeNomad doesn't import `@opencode/ai`. - Desktop/TUI-only changes (desktop terminals on persistent PTYs, base-branch and worktree shortcuts, quote sending, flat inputs, palette ordering) don't affect CodeNomad. One indirect effect follows. - **Worktree deletion:** OpenCode Desktop terminals now live as persistent PTYs that survive restarts ([#60346](https://github.com/anomalyco/opencode/pull/60346)). CodeNomad's guard (`routes/worktrees.ts`, "Running persistent PTY blocks deletion: <id>") will therefore refuse more often for users who also open terminals in OpenCode Desktop. The behavior is correct, but the message names the PTY ID rather than the terminal's title. **Verdict:** - The **2.1.0 client/plugin pins can stay**. Bumping them would bring only artifacts, PTY renaming and a config type, none of which CodeNomad consumes. - The **2.2.3 minimum has no reason to move**. No consumed HTTP, plugin, private-service or storage contract broke in 2.2.4 or 2.2.5. - **Recommend 2.2.5.** It is admitted today through contract recognition. Recommending it is CodeNomad-side bookkeeping: `RECOMMENDED_OPENCODE_VERSION` (`runtime-support.ts`), the reviewed-version check in `contractProfile` (`compatibility/runtime.ts`), the version texts in docs and help, and CI's qualification target. This is subject to the full native suite on the exact 2.2.5 CLI, run separately. - **No CodeNomad bug found** in 2.2.3 → 2.2.5. Risks: the `session_part` forward risk (unchanged) and the more frequent worktree-deletion refusal (UX). **Not verified here:** - the full native suite on 2.2.5: only a host-module probe ran natively on 2.2.5, and everything else for 2.2.5 is source and OpenAPI review (Appendix I); - the 2.2.4 recurring Missions journey (`test-recurring-simple-native` ABCDGELFWQN), which was interrupted by a server restart; - the `kv` → `job` migration with a real pending background marker: only the empty case ran, and upstream `job.test.ts` covers the copy; - whether a `bash` call is stored as `bash` or `shell` (source suggests the model's name is kept; CodeNomad renders both); - artifacts, Claude Agent and MCP stdio framing at runtime (source only); - macOS/Linux. --- ## What users will notice **OpenCode 2.2.4** - **Persistent desktop terminals:** OpenCode Desktop terminals belong to the session, keep their scrollback across server restarts, stay in sync with the TUI and other windows, and can be renamed. Renamed terminals keep their names. - **Artifacts (opt-in):** with `"experimental": { "artifacts": true }`, agents can publish, update and serve HTML or static artifacts (`artifact_create`, `artifact_read`, `artifact_update`, `artifact_delete`) through a built-in local provider, which stores files under OpenCode's data folder, or a plugin-provided one. - **Schedules:** enabled schedules also fire under `opencode serve`, and only once when several OpenCode processes share a database. They stay off unless `experimental.schedules` is `true`. - **Claude Agent:** OpenCode Desktop guides installation, `claude auth login` and connection checking. Error messages now say `claude auth login` instead of `/login`. - **Config:** user, project and remote configuration can override Console-supplied provider names, limits, variants, settings and headers. - **Networking:** requests to the local OpenCode service no longer go through `HTTP(S)_PROXY`. - **Sessions:** deleting a session also stops its running background work, such as shells, image generations and subagents. - **Desktop/TUI:** base-branch shortcut, simpler location popover, faster Markdown streaming and various fixes. **OpenCode 2.2.5** - **Compaction:** `"compaction": { "buffer": "20%" }` keeps a share of each model's context free; token counts still work. Compaction no longer overfills models whose catalog input limit exceeds their context window, and LiteLLM context errors trigger compaction instead of stopping. - **Tools:** a model calling `bash` gets `shell` (with shell permissions) instead of an error. `read` names the missing folder, and `edit` shows the closest lines when `oldString` isn't found. - **Reasoning:** switching models or resuming an interrupted reply no longer resends reasoning as plain text, which some providers rejected. - **MCP:** large stdio messages (over 10 MiB) no longer disconnect a server, and idle locations don't immediately restart their MCP servers. - **Desktop/TUI:** worktree and base-branch shortcuts, a shell-mode toggle, sending a single quote from its popup, and MCP servers removed from the connect menu. ## Follow-ups (outside this PR) - Hardening for `session_part` (independent of this upgrade; 2.2.5 still writes no rows): make the direct `session_message.data.content` readers and the pruning transaction fail safe when `session_part` has rows for the target messages. - Optional UX: when the worktree deletion guard finds a running persistent PTY, name it by `userTitle ?? title` (2.2.4+) and say it may be an OpenCode Desktop terminal. - Any future reader of `compaction.buffer` must accept `"N%"` as well as a token count. ## Isolated Windows qualification Base: dev `605820669`; Node 25.2.1 (local; CI runs the pinned 24.20.0); exact official CLI **2.2.5**; locked client/plugin **2.1.0**; `CODENOMAD_NATIVE_FIXTURE_PARENT` outside the user profile. - **Native suites on 2.2.5, all passing:** Code Mode jobs, plugin runtime, automation, session pruning (history, navigation, media blobs, proxy, session images), Location/worktrees/event relay, permission receipts, Git init/degraded, Missions (contract, family control, native, trajectory) and all 11 recurring journeys, sessions (environment, fork, aside, interrupt, lifecycle, blank cleanup, compaction isolation, prompt skills), providers (usage, accounts, account selection), service usage, web search settings, plugin packages, output limit, Promise-tool failure, subagent depth, temporary workspaces, Design companion/activation/content, image settings, history migrations from 2.1.2/2.2.3/2.2.4, shared install of the 2.2.3 minimum. - **Installer suites after the bump:** upgrade (installed `opencode v2.2.5`) and legacy replacement (target `2.2.5`) install the new recommendation and pass. - **Builds and checks after the change:** server build, native plugin builds and root typecheck clean; server **2,840 passed, 9 skipped, 1 cancelled** (`index.test.ts` shutdown test timed out under full-suite load; **4/4** alone); runtime-support/transport/update **35/35**; browser `opencode-setup` **34/34**; ten-locale help **31/31**.
8.7 KiB
OpenCode setup
CodeNomad connects to a shared OpenCode service on the execution host. Selecting a CLI, updating its files, restarting that service and reloading configuration are different operations; none is a substitute for the others.
Select or install the CLI
- Open Settings → OpenCode and use the OpenCode Binary card, below OpenCode version, to select the executable.
- Leave the automatic entry selected to prefer the server's PATH, unless it holds an older OpenCode, then its user npm OpenCode 2 installation; or use Browse for Binary… or enter a path and choose Add.
- Use Check status and updates. If OpenCode is missing, choose Install and start OpenCode; review the host and installation scope first.
- If setup offers Connect and continue, use it after resolving the reported problem.
Installation uses bundled Node/npm for a standard user installation shared with other clients. Install for the user and configure PATH changes that user's terminal setup; open a new terminal afterward. A browser connects to the CodeNomad server: its file picker and executable selection concern that server, not the browsing device.
When an older OpenCode comes first on PATH, the offered action depends on how it was installed. For OpenCode 1.x installed with npm, Replace OpenCode {version} with OpenCode 2 asks for confirmation, removes that npm package and installs OpenCode 2 in the same npm folder; the OpenCode data folder is kept, and OpenCode 2 imports 1.x conversations itself. An older or unusable OpenCode installed another way (winget, Homebrew, manual) is never modified: Install OpenCode 2 for CodeNomad installs OpenCode 2 in the user npm folder beside it, and CodeNomad then uses that copy. If that older command itself sits in the user npm folder (for example a link in ~/.local/bin), or that folder cannot be written, setup explains why instead of offering the action: move or rename the command, or fix the folder's permissions, then choose Check status and updates. A terminal's opencode command may still start the older version. An explicitly selected custom executable is never replaced.
The installed executable and the running service can have different versions. Compare Installed version with Running service in the OpenCode version card rather than assuming that selecting another executable has replaced the live daemon; Version details lists the minimum and recommended versions. If installation is busy or the executable is locked, wait for the installer or process to release it and check status before retrying; do not run competing installers.
Required, recommended and unverified versions
| Classification | Current requirement | Meaning |
|---|---|---|
| Minimum | OpenCode 2.2.3 | The image generation tool used by the Images settings and the Design extension, alongside correct JavaScript job ordering in Code Mode and the native replay and compaction format; conversations saved by earlier versions stay readable after updating. |
| Recommended | OpenCode 2.2.5 | Qualified target, distinct from the technical minimum. |
| Unverified | A newer or custom version not fully validated | Not rejected merely for being untested; the connected service's actual API contracts are checked. |
The required session, permission, Form, inbox and session-environment contracts must also be available. An executable version alone does not prove that the connected service supports them. If setup reports an unsupported running service, select/install a supported CLI and use the explicit shared-service restart when ready.
Host, WSL and shared-service scope
On Windows, a selected WSL executable runs inside its chosen distribution. Install/update it there and use paths meaningful inside that distribution. WSL connectivity depends on Windows localhost forwarding. A Windows CLI and a WSL CLI are not interchangeable execution environments.
OpenCode owns its global service registration, sessions, messages and database. CodeNomad does not create a private OpenCode database per window or project. Closing a project tab closes that project in CodeNomad; sessions continue in OpenCode and reappear when you reopen the project. CodeNomad never unloads native Locations. Closing a whole window, quitting or reloading preserves project connections for restoration; neither those actions nor backend shutdown stops the shared daemon. See Projects.
Update, restart or reload
- In Settings → OpenCode, choose Check status and updates.
- To replace installed CLI files, choose Update to OpenCode {version} when offered. Wait for completion.
- Review the running-service status. Use Restart shared service only when you intend to activate the selected installation for every connected client.
- For a process restart without installing anything, expand Troubleshooting and choose Restart OpenCode service, then confirm.
| Action | Scope and effect | Safe recovery |
|---|---|---|
| Update CLI | Changes the supported installed executable; does not implicitly restart the running daemon. | Check both installed and running versions after a failure; retry explicitly only after resolving the error. |
| Restart service | Replaces the shared process and interrupts active work in all connected OpenCode clients; session history remains. | Reconnect and inspect conversations and scheduled Missions; a restart is not automatic continuation. |
| Reload OpenCode configuration | Keeps the process but rebuilds every loaded Location for all clients. Cancels pending permissions/Forms and closes terminals/background commands; active work may be interrupted. | Recheck resources and pending work after reload. Do not repeat a prompt or mutation merely because its reply was lost. |
Use Reload OpenCode configuration, under Troubleshooting when the running service supports it, explicitly when a saved configuration or installed plugin remains unavailable and the disruption is acceptable. It is not a harmless display refresh. CodeNomad will not use an older selected CLI to downgrade a newer running daemon.
Session environment
- Open Settings → Advanced and expand Environment Variables.
- Add, change or remove the profile's overrides; each change is saved immediately.
- Send the next prompt, custom command or session shell request through CodeNomad to apply the current environment to that conversation.
This is a configuration-profile setting, applied server-side before each send. Merely opening/reading a conversation or saving settings does not alter a native session. Removing an override restores the execution host's inherited value, or removes it if absent there. Failure to apply the environment blocks the send instead of using stale values.
The environment controls subsequent local shell launches in that native session. Already running processes retain their environment. It does not reconfigure providers, MCP/LSP servers, independent terminals or Location-only background shells. Queued prompts do not each capture their own environment, and another OpenCode client can replace the same session environment. Do not assume child sessions created wholly within OpenCode receive a CodeNomad send-time update.
Allowed variables are also passed when starting a stopped service; connecting to an existing daemon does not change its process environment. In WSL, values are combined with the Linux execution environment, not Windows PATH/HOME. Changing these overrides does not relocate OpenCode's database or service registration.
Edit native configuration files
- Open Settings → Config Files and select File.
- Check the displayed path, edit, then choose Save.
- Use Reload to reread the file; this is not Reload OpenCode configuration.
This editor exposes only its listed global opencode.json and opencode.jsonc files under the CodeNomad server user's .config/opencode directory. It is not an arbitrary-file editor, a Project-config selector or a guarantee that a WSL/custom-discovery daemon reads that file. Use the displayed path to verify the target; use the daemon's own tooling for other roots.
Saving writes the file as text; it does not validate the entire native configuration or restart/reload OpenCode. Coordinate edits with other clients: this surface does not offer an external-change merge. Keep a copy before replacing substantial configuration. Switching files or reloading a dirty draft asks whether to discard it.
See Integrations, Providers, Missions and OpenCode documentation for configuration-specific workflows.