linux/claude-mode was 3,035 lines. It is now 177: the paths and flags, a
loader, and the command dispatch. Everything else moved, verbatim, into
twelve files under linux/lib/, one per concern - output, core, preflight,
sessions, switch, catalogue, commands, doctor, presets, menu, setup, repair.
The move was done by line range with a check that every original line landed
in exactly one file; the only thing that changed place is the switch's
running-sessions question, which now sits with session detection.
The CLI finds lib/, cm-json.py and cm-vault.sh beside itself, following the
~/.local/bin symlink, so a checkout runs its own code rather than the
installed version's (it used to mix the two). The key helper path written
into settings.json is still the installed one.
linux/install.sh ships bin/lib/, clearing old modules first so a removed one
cannot linger. The package build copies linux/ recursively, which a flat copy
would not.
tests/cli/test_install.sh runs the real installer into a sandbox home: every
file lands, the symlink runs, a reinstall keeps edited presets and drops a
stale module. docs/architecture.md lists the modules.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The README had grown to 1,010 lines of user docs and design notes in one file,
and had gone stale: it still showed the old numbered menu, set up only three
providers, and listed preflight checks and a file layout that predate the last
three releases. It now carries install, first run, the full command
reference, the providers at a glance, troubleshooting and a docs index.
docs/:
- providers.md presets, defaults, the model cache, context windows, each
provider (OpenRouter's cost guard and guardrail check are
written up for the first time), adding a provider
- live-sessions.md what a switch does to running sessions, and repair
- design.md why settings.json, why keys stay out of it (and the vault
per platform), the preflight checks as they are now
- bar-widget.md the widget as it is now: providers from health.json, every
server provider's settings, the restart after an upgrade
- architecture.md the pieces, every file on disk and who writes it, the
contracts between them, where to change what
- development.md running the tests, the conventions the code follows,
working on the widget, releasing
CONTRIBUTING.md points at it.
Also:
- The per-project session listing used awk, which the CLI avoids because it
is missing from minimal images; it uses the script's own TSV helpers now,
and tests/static.sh fails on any awk in the CLI.
- tests/static.sh checks every relative Markdown link and #anchor.
- A unit test pins the managed env keys between cm-json.py and
claude-mode.ps1, which only a comment kept in step before.
- test_sessions covers the per-project listing, which nothing ran.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Acts on docs/incident-mode-switch-corrupts-live-sessions.md, which is added here
as the record of why.
The report identifies a consequence that was not modelled. A failed call is
recoverable; a *successful* one may not be. If a running session takes even one
completion from the provider being switched to - which happens when that mode
matches the base URL it already had cached - that provider's message-id format
lands in its transcript. OpenRouter issues `gen-<epoch>-<rand>` where Anthropic
issues `msg_...`, and native Anthropic then refuses to resume the session at
all, with a 400 naming previous_message_id. The only way back is to truncate the
transcript, losing every turn after the cut. That happened here, and was fixed
by hand.
Two changes follow.
Sessions are now settled before the write, not reported after it. A switch with
anything running stops, names the sessions, explains what is about to happen to
them, and offers restart (the only answer that ends with everything on the mode
the bar now claims), close, proceed anyway, or abort - defaulting to abort.
Non-interactively it refuses outright unless given --yes. The old after-the-fact
reporter is deleted rather than left as a second, contradictory account.
`claude-mode repair-session` replaces the hand surgery: it finds a project's
transcripts, reports which are resumable, and on --apply backs the file up and
truncates to the last Anthropic-issued message. Verified against the real
corrupted transcript from the incident - it reproduces the manual cut exactly,
1921 lines to 1813, dropping the two `gen-` completions and the error
placeholders after them, leaving a transcript that ends on a genuine msg_ id. It
refuses a transcript written to in the last 90 seconds, since that one belongs
to a session still running.
The panel passes --yes, having already asked in its own card, and that card now
names the transcript risk rather than only the inconvenient one.
Requirement 4 of the report - documenting the mechanism - landed in 9c301e1;
the README now carries the unrecoverable half as well.