Skip to content

chore(opencode): recommend OpenCode 2.2.5 - #1222

Merged
pascalandr merged 1 commit into
devfrom
chore/qualify-opencode-2.2.5
Oct 31, 2026
Merged

pascalandr merged 1 commit into
devfrom
chore/qualify-opencode-2.2.5

Conversation

@pascalandr

@pascalandr pascalandr commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

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 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). 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).
    • 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). 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): 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). 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):
    • Image tool (fix(opencode): require OpenCode 2.2.3 and adopt its image tool contract #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, 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). 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, #60689).
    • Compaction (2.2.5): the prompt is capped at the context window when a catalog's input limit is larger (#60660), and compaction.buffer may be "N%". CodeNomad never reads or writes compaction.buffer. LiteLLM context errors now trigger compaction (#60692).
    • Reasoning replay (2.2.5, #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), and an idle Location no longer restarts its MCP servers right after shutting down (#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); the guided setup (#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 (fix(usage): show Claude Agent quota from Claude Code's login #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), 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; left out of the changelog by #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). CodeNomad's guard (routes/worktrees.ts, "Running persistent PTY blocks deletion: ") 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.

OpenCode 2.2.4 and 2.2.5 change no contract CodeNomad consumes: the authenticated OpenAPI dumps keep every consumed schema byte-identical or additive, the published client and plugin declarations typecheck, the native plugin host modules resolve, and the image tool, Claude Agent provider, Code Mode and permission contracts are unchanged. Users therefore get the qualified, current runtime offered as the recommendation.

RECOMMENDED_OPENCODE_VERSION becomes 2.2.5 and the reviewed-publication shortcut in contractProfile lists 2.2.3 and 2.2.5; every other version, 2.2.4 included, still negotiates its authenticated schema. The 2.2.3 minimum, its image tool contract reason and the 2.1.0 client/plugin/schema pins stay. Help in all ten locales, the READMEs, CONTRIBUTING.md, the compatibility doc and the architecture skill state the minimum and the recommendation as two versions again.

Validation on the exact 2.2.5 CLI: every native suite, including Design, image settings, Missions with all recurring journeys, history migrations from 2.1.2/2.2.3/2.2.4 and install/upgrade/legacy replacement; typecheck, server units, update/compatibility tests, the browser OpenCode setup test and the ten-locale help checks.
@pascalandr

Copy link
Copy Markdown
Contributor Author

Gatekeeper review

ZERO FINDINGS (P0: 0, P1: 0, P2: 0, P3: 0).

Round 1 found no code or documentation defects and one P3: the description listed upgrade and legacy replacement among the 2.2.5 native suites, but those runs predated the recommendation bump and installed 2.2.3. Both suites were rerun after the bump: upgrade installed opencode v2.2.5 without restarting the daemon, and legacy replacement targeted 2.2.5. The description now separates the shared install of the 2.2.3 minimum from the post-bump installer suites; round 2 confirmed it matches the evidence.

Verified:

  • Minimum (2.2.3) and recommendation (2.2.5) are separate, the 2.1.0 pins are unchanged, update semantics (tested/untested, optional upgrade below the latest release) and the CI minimum/latest lanes are correct. The reviewed-publication shortcut listing 2.2.3 and 2.2.5 follows the earlier qualifications; 2.2.4 negotiates its authenticated schema.
  • All ten locales keep the minimum's reason and name 2.2.5 as the recommendation, with no wording left that equates the two. Remaining version literals in browser tests are scenario inputs.
  • The reviewed 2.2.4/2.2.5 behavior changes need no implementation here; the listed follow-ups (session_part hardening, persistent PTY naming in the worktree deletion guard, percentage compaction.buffer) are appropriately scoped.
  • Runtime support, compatibility and OpenCode update tests pass (84 passed, 1 skipped); ten-locale help 31/31.

@pascalandr
pascalandr merged commit a2274d6 into dev Oct 31, 2026
23 of 38 checks passed
@pascalandr
pascalandr deleted the chore/qualify-opencode-2.2.5 branch October 31, 2026 00:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant