One preset per mode, and a first-run setup that fills it in

The openrouter default moves its hot tiers: opus to z-ai/glm-5.3-flash and
sonnet to deepseek/deepseek-v4-flash-0731. haiku and fable are unchanged.

`cheap` and `lmstudio-qwen` are gone, leaving exactly one preset per mode so
`claude-mode <mode>` is never ambiguous and there is no menu to read before the
thing you asked for happens. The surviving lmstudio preset keeps the Qwen3.6
model rather than KAT-Coder: the two differed mainly in that KAT's chat template
carries the message-order assertion this README already warns about, so between
two presets that had to become one, the one that is known to work won.

More presets are still a `preset new` away; the shipped set is a starting point,
not a ceiling.

Which is the other half of this. A shipped preset was never a working
configuration - OpenRouter and Z.AI have no key stored, and lmstudio's model ids
were whatever happened to be installed on the machine this was packaged on. That
was left for the user to discover through a failure. Now the shipped presets
carry `configured: false`, preflight blocks on it, and `claude-mode setup <mode>`
walks through what is actually needed: key, server URL and auth for LM Studio,
then models chosen from the provider's own catalogue rather than typed from
memory. A switch that trips this in a terminal offers to run setup there and
then instead of printing a command to type next.

Absent means configured, deliberately: presets that predate this and any built
by hand with `preset new` do not suddenly start demanding a wizard.

The panel gets a "Set up <mode>…" button that hands the whole flow to a terminal,
since a bar popup can host neither a hidden key prompt nor a filter-select list.

Two bugs found while testing it, both real:

ask_value printed its prompt to stdout while being called inside $( ), so the
prompt text came back glued to the front of the answer and set-url rejected the
result. Moved to stderr, which is why warn and err already go there.

lms_catalogue never sent the API key. On a server with authentication switched
on - the case just added support for - /api/v0/models answers 401 like anything
else, so the catalogue came back empty and every caller silently concluded the
server had no models installed. It now sends the preset's credential, as do the
three other call sites that read it.
This commit is contained in:
smoido
2026-08-31 01:48:17 +03:00
parent 9c301e10a1
commit 9ff9b82c25
9 changed files with 394 additions and 77 deletions
+54 -17
View File
@@ -127,13 +127,15 @@ used" — so `claude-mode openrouter` always means `default`.
## Presets shipped
One per mode, so `claude-mode <mode>` is never ambiguous and there is no
menu to read before the thing you asked for happens. Build more with
`preset new` whenever one stops being enough.
| preset | provider | opus | sonnet | haiku | fable |
|---|---|---|---|---|---|
| `default` | openrouter | `deepseek/deepseek-v4-flash-0731` | `qwen/qwen3.7-flash` | `openrouter/free` | `z-ai/glm-5.3` |
| `cheap` | openrouter | `deepseek/deepseek-v4-pro` | `deepseek/deepseek-v4-flash-0731` | `qwen/qwen3.7-flash` | `openai/gpt-5.6-luna-pro` |
| `default` | openrouter | `z-ai/glm-5.3-flash` | `deepseek/deepseek-v4-flash-0731` | `openrouter/free` | `z-ai/glm-5.3` |
| `zai` | zai | `glm-5.3` | `glm-5.3` | `glm-4.7` | `glm-5.3` |
| `lmstudio` | lmstudio | `kwaipilot_kat-coder-v2.5-dev` (all tiers) | | | |
| `lmstudio-qwen` | lmstudio | `qwen3.6-35b-a3b-uncensored-heretic-native-mtp-preserved` (all tiers) | | | |
| `lmstudio` | lmstudio | whatever setup finds on your server (all tiers) | | | |
Presets are plain JSON in `~/.claude-mode/presets/`. A preset declares its
`provider`; `claude-mode lmstudio default` is rejected rather than silently
@@ -164,8 +166,8 @@ CLAUDE_CODE_AUTO_COMPACT_WINDOW = <contextTokens>
| preset | contextTokens |
|---|---|
| `default`, `cheap`, `zai` | 1,000,000 |
| `lmstudio`, `lmstudio-qwen` | 262,144 |
| `default`, `zai` | 1,000,000 |
| `lmstudio` | 262,144 |
`doctor` cross-checks the declared window against each tier's *actual* model
window and names any tier that falls short — `default` maps haiku to
@@ -246,17 +248,18 @@ Scanning your installed models' templates:
| **`qwen/qwen3.5-9b`**, **`prism-ml/bonsai-27b`** | **assert** |
`doctor` now reports this per model, and `models` flags affected entries with
`TEMPLATE RISK`. **The fix is to use a model without the flag** — which is
exactly the `lmstudio-qwen` preset, verified end-to-end with a cold JIT load,
streaming, and tool calls.
`TEMPLATE RISK`. **The fix is to use a model without the flag.** The Qwen3.6
line above is what the single `lmstudio` preset ships pointed at, verified
end-to-end with a cold JIT load, streaming, and tool calls.
Honest caveat: KAT-Coder's template *does* contain the assertion, but I could not
reproduce the failure against it here — cold JIT, streaming, tools, system
blocks, and multi-turn `tool_result` all succeeded. Whether it trips seems to
depend on which parser strategy the runtime picks. If it spams, switch:
depend on which parser strategy the runtime picks. If the model setup lands on
does spam, run setup again and pick another:
```powershell
claude-mode lmstudio lmstudio-qwen
```bash
claude-mode setup lmstudio
```
Other notes: use a model with **>25k context** (`doctor` warns below that), and
@@ -402,6 +405,38 @@ active configuration: mode, preset, model map, context window, key backend, and
the switchable preset catalogue. No key material. A switch and a `status` both
refresh it; the command exists for anything that wants to force it.
## First-run setup
A shipped preset is a starting point, not a working configuration. OpenRouter
and Z.AI have no key stored. LM Studio's model ids are whatever happened to be
installed on the machine this was packaged on, which is almost certainly not
yours.
So the shipped presets carry `configured: false`, and preflight treats that as a
blocker with its own remedy:
```bash
claude-mode setup openrouter # key, then models from OpenRouter's catalogue
claude-mode setup zai # key, then per-tier GLM models
claude-mode setup lmstudio # server URL, auth, then models from that server
claude-mode setup anthropic # nothing to do; it uses your existing login
```
Setup asks only what it cannot work out, shows the current model map before
offering to change it, and picks from the provider's own catalogue rather than
asking anyone to type a model id from memory. LM Studio maps one model across
every tier, since a local server has one loaded at a time and per-tier mapping
would just pay the load cost on every tier change; the remote gateways ask per
tier, which is the point of them.
In a terminal, a switch that trips this offers to run setup there and then
rather than printing a command to type next. It sets `configured: true` on the
way out.
**Absent means configured.** Presets that predate this, and any built by hand
with `preset new`, are nobody's business but yours and will not start demanding
a wizard.
## Refusing a switch that would not work
A switch writes settings.json and is picked up by the *next* `claude` launch, so
@@ -417,6 +452,7 @@ So the preconditions are checked before the write, not after:
| mode | checked | when it fails |
|---|---|---|
| any gateway | the preset has been through setup at least once | `claude-mode setup <mode>` |
| `anthropic` | nothing to check | — |
| `openrouter`, `zai` | a key exists for the preset's `keyRef`, and the helper is executable | `claude-mode set-key <ref>` |
| `lmstudio` (anywhere) | the server answers, and accepts the credential the preset would send | see below |
@@ -554,11 +590,12 @@ stock glyph in this bar measures:
Choosing a target does not switch immediately — it runs the same two checks the
CLI does, and both can stop it:
1. **Preflight.** If the mode has no key stored, or its server is not answering,
the panel says which and offers the fix: *Store the key…* opens a terminal
for the hidden prompt (a bar popup has nowhere to host one), *Check again*
re-runs the preflight once the server is up, and *Server settings…* opens the
form below. The gear on any LM Studio preset row opens the same form without
1. **Preflight.** If the mode has not been set up, has no key stored, or its
server is not answering, the panel says which and offers the fix: *Set up
<mode>…* opens a terminal and runs the whole first-run flow there (a bar popup
can host neither a hidden key prompt nor a filter-select model list), *Store
the key…* opens a terminal for just the prompt, *Check again* re-runs the
preflight, and *Server settings…* opens the form below. The gear on any LM Studio preset row opens the same form without
waiting for a failure — per row, because two LM Studio presets can point at
two different machines.