[FEATURE] Session-only flag for typed /model <name> (or a setting to disable global persistence)

Status Open
Maintainer reply None cached
Activity 3 comments · opened May 28, 2026

Summary

In v2.1.153 the typed form of the model switch — /model <name> — was changed to persist the chosen model to ~/.claude/settings.json as the new global default. The interactive picker offers s for session-only switching, but the typed form has no equivalent. There is also no settings flag to opt out of the new persistence behavior.

Why this matters

Persisting a model choice as a side effect of an in-session command is surprising. The typed form is the natural way to switch models quickly during a session ("let me try this on Opus, then back to Sonnet") and silently rewriting the user's global default on every such toggle is the opposite of what most users want from a transient switch.

Today, working around it requires either:

  1. Falling back to the picker UI and pressing s (slower).
  2. Restarting with claude --model <name> (also slower; loses the current session).
  3. Manually re-editing ~/.claude/settings.json after every switch to remove the line.

None of these match the muscle memory of /model <name> as a lightweight per-session toggle, which is how it behaved before v2.1.153.

Requested behavior

Any one of the following would close the gap:

a. A typed flag, e.g. /model opus --session or /model opus s, that switches for the current session only and does not write to settings.
b. A settings.json option such as "persistModelOnSwitch": false that opts users out of the new persistence behavior globally.
c. Make the typed form default to session-only (matching the picker's s) and require an explicit --save to persist — i.e., invert today's default.

(a) is the least disruptive and most discoverable. (c) is the cleanest from a principle-of-least-surprise standpoint but is a breaking change for anyone who has come to rely on the v2.1.153 behavior.

Related

  • v2.1.153 model-config docs: https://code.claude.com/docs/en/model-config.md
  • Possibly related: #60404 ([DOCS] Model configuration docs still say /model selections persist across restarts) — different issue (docs accuracy vs. opt-out mechanism) but in the same problem space.

Disclosure & context

Drafted by Claude Code at my request after I hit this unexpectedly. /model opus is a command I've used many times for quick in-session toggles; the v2.1.153 change silently rewrote my global settings as a side effect, and the only way to undo it was to hand-edit ~/.claude/settings.json. Silent behavior changes on long-standing commands erode trust, especially for a typed form that had stable session-only semantics for a long time before the flip. Please weigh that when prioritizing — filing while it's still fresh so the signal isn't sanitized.

Environment

  • Claude Code version: v2.1.153+

View original on GitHub ↗

3 Comments

spiveym · 2 months ago

Needs fixing please, it feels like the new /model behaviour is a dark pattern.

andb · 1 month ago

Confirming this is still happening on 2.1.201.

Reproduction: pin a model in ~/.claude/settings.json (e.g. "model": "sonnet") → in a separate window, switch via /model to something else → exit that session → start a fresh session (same or different project). The new session starts on the switched-to model, not the pinned default.

Additional evidence: watching ~/.claude/settings.json with inotifywait across several concurrent sessions, I captured live atomic-rename writes changing model and effortLevel to values I hadn't set myself — confirms it's a temp-file-then-rename write (not a hand edit), landing in the global user-level file. I didn't isolate which exact command in which session caused each write, only that the values changed under me.

Possibly useful for scoping a fix: in my testing, a .claude/settings.local.json pin (project-scoped, higher precedence than the global user-settings file) was not affected by the same drift — only ~/.claude/settings.json gets overwritten.

Workaround in the meantime: a shell function wrapping claude that forces --model/--effort flags on every launch unless already specified:

claude() {
  local pass=("$@") want_model=1 want_effort=1
  for a in "${pass[@]}"; do
    case "$a" in
      --model|--model=*)  want_model=0 ;;
      --effort|--effort=*) want_effort=0 ;;
    esac
  done
  local defaults=()
  [ "$want_model" = 1 ]  && defaults+=(--model sonnet)
  [ "$want_effort" = 1 ] && defaults+=(--effort high)
  command claude "${defaults[@]}" "${pass[@]}"
}

CLI flags apply only to that invocation and aren't persisted, so this reasserts the default at every launch regardless of what another concurrent session leaves in the shared file. Doesn't help non-interactive invocations (scripts, cron, editor-spawned processes) that bypass shell rc files.

Given the history already listed in #66402, this looks like the same underlying cause recurring rather than a new one.

benthepsychologist · 5 days ago

Filed a follow-up with a concrete flag precedent (in-TUI --flag syntax already exists via /plugin tag's -f|--force): #89548