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.
Four changes to the POSIX build, found while getting it working on Omarchy.
Colour follows the desktop theme. The sixteen ANSI slots carry no guarantee
about relative brightness and monochrome themes exploit that: under Omarchy's
Solitude, slot 36 (headings) resolves to #707070 and slot 31 (FAIL) to #565d60,
which against #cacccc body text on a #101315 ground is 3.8:1 and 2.8:1 where the
body text is 11.6:1. Headings rendered as fine print and errors as the quietest
thing on screen. The palette is now derived from the theme's own colors.toml,
with each role measured against the background it will actually be drawn on and
lifted toward the foreground when it falls short - hue kept where the theme has
any, weight substituted where it does not. Headings go 3.8:1 -> 9.4:1 and FAIL
2.8:1 -> 5.2:1. Falls back to the ANSI slots off Omarchy, with the two roles the
slots get wrong corrected.
health.json was only ever written by a switch, so a fresh install had none at
all and any reader had to guess. It is now refreshed by `status` and seeded at
install, and `claude-mode health` forces it. The installer also copies VERSION,
which cm_version() has always read and nothing ever wrote - every health.json
until now reported 0.0.0.
Preflight, because a switch that cannot work does not fail loudly: it succeeds,
and every session started afterwards breaks in a way that points at Claude Code
rather than at here. Keys, the helper, the preset's provider and the server are
all checked before the write. LM Studio is the sharp case - its token is an
inline placeholder, so nothing about the switch needs the server to exist.
Session control, because Claude Code reads settings.json once at startup: a
switch leaves running sessions on the old provider until they are restarted, and
one mid-request can lose that turn outright. `sessions` lists them, `--stop` and
`--restart` act on them behind a confirmation, `--dry-run` shows the plan.
Sessions are found through /proc/<pid>/exe rather than by process name, which
would sweep up every shell that merely mentions claude - including the one this
runs from. Two exclusions: the calling session, and forks of a session. A busy
session spawns children off its own binary that inherit the same exe, and
without filtering those the count climbed and fell with load - it read 2, 5, 11
and 40 for the same two sessions before the parent check went in.
LM Studio is no longer assumed to be on this machine. `preset url` and
`preset auth` move it to a LAN box, a tunnel or a proxy and turn authentication
on, and the probe distinguishes ok / auth / notfound / refused, because "start
the server" and "your key is wrong" are opposite remedies. It is probed wherever
it lives - a sleeping LAN box is exactly as absent as an empty loopback port -
while remote gateways are not, since those being briefly unreachable is the
network's problem and a missing key never fixes itself.
Source of truth so far has been c:\Users\smoido\projects\cli on the Windows
box, which has no git history of its own. This is that tree copied verbatim over
SSH, minus dist/ - the PowerShell build, the POSIX port under linux/, and the
presets both share.
Recorded as its own commit so that everything after it is a reviewable diff
rather than an undifferentiated first drop.