/model picker: pressing Right on the highest effort level wraps to Low and saves it as the default

Status Fixed / completed
Reported on v2.1.288
Maintainer reply None cached
Activity 1 comment · opened Oct 3, 2026 · closed Oct 6, 2026

Summary

  • In the /model picker, the effort control (←/→) wraps around. Pressing Right on the highest level (Max) selects Low.
  • Pressing Enter then saves Low as the default effort for new sessions on that model.
  • The /effort slider in the same build stops at the ends instead, so the two effort controls behave differently.

Environment

  • Claude Code 2.1.288, macOS (arm64). Reproduced live on this version.
  • The same wrap logic is in the shipped code of 2.1.287 and 2.1.220.

Steps to reproduce

  1. Start with a scratch config: export CLAUDE_CONFIG_DIR=$(mktemp -d), then run claude in an empty folder.
  2. Accept or skip the first-run setup screens (login not required to open /model), and accept the folder trust prompt.
  3. Run /model. With the default model (Opus 5.5), the picker shows Medium effort (default) ←/→ to adjust.
  4. Press Right until it shows Max effort.
  • From Medium that takes 3 presses (High → xHigh → Max).
  • The number of Right presses depends on the starting level and the model.
  1. Press Right once more.
  2. Press Enter.
  3. Run jq .modelSettings "$CLAUDE_CONFIG_DIR/settings.json".

Effort shown after each Right press, starting from Medium (2.1.288, Opus 5.5):

| Press | Effort shown |
|---|---|
| 1 | High |
| 2 | xHigh |
| 3 | Max |
| 4 | Low (wrapped) |
| 5 | Medium |

Expected

  • Right on the highest level keeps the selection at that level (clamp), as the /effort slider does.

Actual

  • Step 5 wraps the selection to Low effort.
  • Step 6 prints: Set model to Opus 5.5 (default) and saved as your default for new sessions with low effort.
  • Step 7 returns {"claude-opus-5-5": {"effortLevel": "low"}}.
  • In the 2.1.288 bundle, the picker's step for Right is levels[(i + 1) % levels.length], and for Left it is levels[(i - 1 + levels.length) % levels.length]. The /effort slider's increase is Math.min(levels.length - 1, i + 1).
  • Left from Low therefore wraps to the top level too. Only the Right direction was exercised live.
  • On 2.1.220 the same wrap occurs, and the pick is saved to the top-level effortLevel rather than to modelSettings.

Impact

  • A user stepping up toward Max can overshoot by one keypress. The result is Low saved as the default for every new session on that model.
  • The picker does not mark the wrap. The only signal is the word "low" in the one-line confirmation, so the downgrade is easy to miss.

Related issues

  • #30726 — silent effort downgrade and persistence through the effort UI. It does not describe the wrap.
  • #49076 — mentions "max → low (triggered by scrolling through the picker)" in passing. It was closed as a duplicate of #30726.
  • #86873 — the picker's effort column writes effortLevel globally even with s (this session only).
  • #35904 — covers a separate behaviour: the confirmation says Max was saved, but it is not persisted. That is not part of this report.

Suggested fix

  • Clamp the picker's effort index at both ends, as the /effort slider does: Math.min(levels.length - 1, i + 1) for Right and Math.max(0, i - 1) for Left, instead of the modulo step.
  • Add a regression test asserting that Right on the highest level returns the highest level.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗