anomalyco / anomalyco/opencode

tui: /models selection is lost on exit unless a message is sent first

Open
#49,516 0 comments 0 reactions 1 assignee View on GitHub

@simonklee is already working on this.

Since Sep 17, 2026.

Dominant language
TypeScript
Stars
209k
Forks
27.5k
PR merge metrics
PR metrics pending

Description

Summary

In opencode V2 (v2.0.5), a model chosen with /models is not persisted to the
session unless the session is used (at least one message sent) after the switch.
If the user exits immediately after choosing a model, resuming the session
(--session / --continue) uses the previous model again.

Environment

  • opencode version: 2.0.5
  • OS: Linux 7.2.6-arch2-1 (x86_64)
  • Terminal: ghostty (TERM=xterm-256color, TERM_PROGRAM=ghostty, COLORTERM=truecolor)
  • Shell: /bin/bash
  • Install/channel: global install, opencode on PATH
  • Active plugins: ./plugin/conv-log.ts, ./plugin/sync.ts, ./plugin/force-instruction.ts (from ~/.config/opencode)

Reproduction

  1. Start opencode in a project and resume an existing session (opencode --session <id>).
  2. Run /models and select a different model.
  3. Exit opencode without sending any message.
  4. Start opencode again and resume the same session.
  5. The previously selected model is active again.

Repeat, but send a short message between steps 2 and 3. After step 4 the newly
selected model is still active.

Expected Behavior

The model selected with /models applies to the current session and is
persisted, so resuming the session uses the newly selected model — regardless of
whether a message was sent afterwards.

Actual Behavior

The selection is lost on exit unless at least one message is sent after the
switch. Resuming the session falls back to the previously stored model.

Additional Context

  • Frequency: reproducible/consistent (A/B test, then confirmed by live observation).
  • Live observation (same session, read via GET /api/session):
    1. Session stored model before: {"id":"deepseek-flash","providerID":"deepseek","variant":"high"}, time.updated=1789633445029.
    2. User selected Qwen3-Coder 30B-A3B Instruct in /models and sent no message.
    3. Session record afterwards: unchanged — same model, same time.updated.
    4. User then sent a trivial message ("ok").
    5. Session record afterwards: {"id":"qwen/qwen3-coder-30b-a3b-instruct","providerID":"openrouter","variant":"default"}, time.updated=1789634133996.
      → The selection is committed only when the next prompt is sent.
  • Server vs TUI: calling POST /api/session/{sessionID}/model (operationId
    session.switchModel) directly does persist immediately — verified by
    creating a session, switching the model via the API, and exporting the session
    (new model present, no message sent). So server-side persistence works; the
    TUI appears to hold the selection client-side until the next prompt.
  • Reporter setup: two machines share the session DB via an externally synced
    opencode.db snapshot (out-of-band, not part of opencode), which is unrelated
    to this behaviour.
  • Impact: users who switch the model and immediately exit silently keep the old
    model on the next start. Workaround: send at least one short message after
    /models, then exit.
  • Related existing issues (same area; none matches this exact case):
    • #38940 — TUI: session model hydration is lost under OPENCODE_FAST_BOOT
      (hydrates from the session's last user message; fast-boot race → falls back
      to recents/config).
    • #45204 — Resuming a session after switching the global default model still
      uses the old recorded session.model (stored session model takes precedence).
    • #47968 — Mid-session model resolution silently falls back to global
      config.model, ignoring the TUI-selected model.
      This report is the deterministic variant without fast-boot: a selection that is
      never used is never written to the session, so resuming falls back to the
      previously used model.
  • No crash and no error output.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.