Skip to content

feat(core): enable the Code Mode VM by default in dev builds via the flag registry - #62444

Merged
jlongster merged 1 commit into
devfrom
codemode-vm-dev-default
Nov 6, 2026
Merged

jlongster merged 1 commit into
devfrom
codemode-vm-dev-default

Conversation

@jlongster

@jlongster jlongster commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

Summary

codemode_vm is now a regular entry in the feature-flag registry (ConfigFlag.registry), so it resolves through Flag.resolve like todo, media_blob, schedules and artifacts. The hand-written vmEnabled in packages/core/src/codemode/tool.ts is gone. Both execute and check now read Flag.enabled("codemode_vm"). The per-engine runtime caches are unchanged.

  • packages/schema/src/config/flag.ts: registers codemode_vm.
  • packages/schema/src/config/experimental.ts: drops the hand-written codemode_vm field. The registry spread generates experimental.codemode_vm with the shared "Defaults to on in local and dev builds and off in releases." description. The codemodeVm → codemode_vm config normalisation is kept.
  • Regenerated openapi.json and the client types. Only the field order and description change.

Default per channel

The rule comes from onByDefault in packages/core/src/flag.ts: channel === "local" || channel === "dev".

Build Channel codemode_vm default
From source (bun run dev) local on (VM)
Dev snapshots (push to dev) dev on (VM)
Stable release latest off (legacy)
Beta beta off
PR / branch previews pr, <branch> off
Unknown / no app metadata unknown off

Why a production binary resolves it to false: .github/release/plan-release.sh sets channel="latest" for a dispatch with a bump or version on dev. release.yml passes it as OPENCODE_CHANNEL. packages/script exposes it as Script.channel, and packages/cli/script/build.ts bakes it in with define: { OPENCODE_CHANNEL: "'latest'" }. Then packages/cli/src/version.ts → App.Metadata.channel → Flag.resolver → onByDefault("latest") === false.

Opt in / opt out

Precedence is OPENCODE_FLAGS > experimental.codemode_vm > experimental.all_flags: true > channel default.

  • Opt in (any build): OPENCODE_FLAGS=codemode_vm, OPENCODE_FLAGS=all, experimental.codemode_vm: true (or codemodeVm), or experimental.all_flags: true.
  • Opt out (any build): OPENCODE_FLAGS=-codemode_vm (also all,-codemode_vm), or experimental.codemode_vm: false. An explicit false beats all_flags: true.
  • Behaviour change: the camelCase OPENCODE_FLAGS=codemodeVm env form is no longer accepted. Env flags use registry keys, the same as every other flag. The camelCase config key still works.

Verification

  • New tool-execute.test.ts cases run the real execute tool and detect which engine ran:
    • local/dev with no config → VM
    • latest, beta, pr, branch and unknown → legacy
    • latest plus OPENCODE_FLAGS=codemode_vm, config true, all or all_flags → VM
    • dev plus -codemode_vm, all,-codemode_vm, config false, or all_flags with codemode_vm: false → legacy
  • flag.test.ts: every registered flag, including codemode_vm, is off on latest.
  • Simulated the release define: bundled a probe of cli/src/version.ts + Flag.all with bun build --define OPENCODE_CHANNEL='latest':
    • latest {"enabled":false,"source":"default"}
    • beta → false
    • dev → true
    • unbundled (local) → true
    • latest with OPENCODE_FLAGS=codemode_vm → {"enabled":true,"source":"env"}
  • packages/core: bun test test/codemode* test/flag.test.ts test/tool* test/config passed 766, failed 0.
  • packages/schema: bun test passed 92. packages/client: test/promise.test.ts passed 41.
  • typecheck:tsc is clean for core, schema, client and protocol. protocol check:generated is clean.

Visual

<svg xmlns="http://www.w3.org/2000/svg" width="240" height="72" viewBox="0 0 240 72" fill="none" stroke="currentColor" font-family="ui-monospace,monospace" font-size="10">
<style>.k{animation:t 3s ease-in-out infinite alternate}@keyframes t{from{transform:translateX(0)}to{transform:translateX(18px)}}@media (prefers-reduced-motion:reduce){.k{animation:none}}</style>
<text x="16" y="26" fill="currentColor" stroke="none">dev</text>
<rect x="70" y="16" width="40" height="14" rx="7" opacity=".9"/><circle cx="102" cy="23" r="5" fill="currentColor"/>
<text x="122" y="26" fill="currentColor" stroke="none">vm</text>
<text x="16" y="54" fill="currentColor" stroke="none" opacity=".6">release</text>
<rect x="70" y="44" width="40" height="14" rx="7" opacity=".4"/><circle cx="78" cy="51" r="5" fill="currentColor" opacity=".5"/>
<text x="122" y="54" fill="currentColor" stroke="none" opacity=".6">legacy</text>
<circle class="k" cx="190" cy="23" r="3" fill="currentColor" opacity=".5"/>
</svg>

Added by the opencode bot (AI-generated).

Public API: codemode_vm moves to the flag registry: on by default in local/dev builds, included in all_flags/OPENCODE_FLAGS=all; OPENCODE_FLAGS=codemodeVm (camelCase env) no longer accepted (config keys unchanged)

@opencodejr opencodejr Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change looks good. The new tool-execute.test.ts cases fail on the base branch (local/dev with no config, and OPENCODE_FLAGS=all on latest, all run the legacy engine) and pass with this PR. The core Code Mode, flag and execute tests pass (60/60), and typecheck:tsc is clean for core and schema. Flag.enabled needs no new services in execute/check: App.Metadata and Flag.Overrides have defaults, and Config is still optional.

Public API impact:

  • experimental.codemode_vm (config/OpenAPI): the key is kept. Only its description and position in the schema change. The default changes from always off to on in local/dev builds and off in every other channel.
  • experimental.all_flags: true and OPENCODE_FLAGS=all now also turn on codemode_vm.
  • OPENCODE_FLAGS=codemodeVm / -codemodeVm (env): no longer recognised. Users of that form need to switch to codemode_vm. The camelCase config key still works.

Release builds keep their current behaviour, and configs that set the key explicitly are unaffected. The camelCase env form is the only break.

No blocking concerns.

@jlongster
jlongster merged commit 07f492b into dev Nov 6, 2026
24 checks passed
@jlongster
jlongster deleted the codemode-vm-dev-default branch November 6, 2026 23:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant