The picker cache the old rows came from is taken away, not just stopped being written (#1185) - #1249
Merged
Merged
Conversation
…ed being written (#1185) Found on sv-mag while checking #1185 on a real host, and reproduced against the real client before fixing. Before #1185 the Waired rows reached the /model picker by waired writing Claude Code's own discovery cache and setting the flag that makes the picker read it. #1185 stopped writing both. It did not take either away — the flag is scrubbed at the next root `waired claude enable`, and the file was not removed at all. So a host that upgrades and has not re-run enable as root carries a stale cache that Claude Code still reads. Measured on 2.1.261: the picker shows BOTH, the three old rows under their old names and the new ones beside them. sv-mag is in exactly that state today — a cache written on 2026-09-03 naming claude-waired-auto, anthropic-waired-local and claude-waired-peer. The per-user picker write takes it away now. That is the half that needs no elevation and runs on every `claude` launch through the SessionStart hook, so it closes the window without waiting for anybody to re-run enable; by the time the root half scrubs the flag there is nothing left to read. Ownership as everywhere else: only a document that names THIS gateway and whose every row is a Waired id. A cache describing some other gateway is somebody else's — and Claude Code ignores it anyway, since it compares baseUrl against the live ANTHROPIC_BASE_URL by exact string. Absent, unreadable, unparseable or foreign are all left alone without an error, because this runs inside a hook on every launch. Verified on sv-mag with a build of this branch: the file was there before the write and gone after it, and the rows in settings.json are the new ones. Refs #1185 Refs waired-ai/waired#1313 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HJUUSmAfbRdjER1seDdjXm Signed-off-by: gen16k <gen16k@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
#1185 stopped writing Claude Code's discovery cache and the flag that makes the picker read it. It did not take either away — the flag is scrubbed at the next root
waired claude enable, and the file was never removed. So a host that upgrades and has not re-run enable as root carries a stale cache the picker still reads.Found on sv-mag while doing L97's on-device after-check, and reproduced against the real client before fixing.
The state a host is actually in
sv-mag, right now:
Written 2026-09-03. Both survive an upgrade, and both are removed only by a root
waired claude enable.What that looks like — measured, not inferred
Claude Code 2.1.261, an isolated
CLAUDE_CONFIG_DIRholding that cache and amodelPickerlineup, discovery enabled,/modelopened in a pty:ZZOLD-Waired-auto(cache)ZZOLD-Waired-local(cache)ZZOLD-Waired-peer(cache)ZZNEW-Waired(modelPicker)ZZNEW-Waired-local(modelPicker)Both lists. Three of the rows are the same destinations under their old names.
The fix
RemoveRetiredCacheininternal/integration/claudecode/retiredcache.go, called from the per-user picker write. That is the half that needs no elevation and runs on everyclaudelaunch through the SessionStart hook, so it closes the window without waiting for anybody to re-run enable as root; by the time the root half scrubs the flag there is nothing left to read.waired claude disableclears it too.Ownership, the same discipline as the rest of #1185: only a document that names this gateway and whose every row is a Waired id. A cache describing some other gateway is somebody else's — and Claude Code ignores it anyway, since it compares
baseUrlagainst the liveANTHROPIC_BASE_URLby exact string, so the narrow rule is also the complete one. Absent, unreadable, unparseable and foreign are all left alone without an error: this runs inside a hook on every launch, and a surprise there would be a failure on a path whose whole job is best-effort.Verified on sv-mag with a build of this branch
and the rows it wrote are the new ones, with per-peer entries from the live mesh:
Checks
go build ./...,go test ./...,gofmt -l,golangci-lint run --max-same-issues=0. New table test covers ours / a different gateway / a foreign model id / one waired id among foreign ones / an empty list / not JSON / no live base URL / no file /CLAUDE_CONFIG_DIR.docs-not-needed: the cache file is named to users nowhere on the site — #1241 already rewrote the one troubleshooting section that mentioned it, and this change only deletes a file waired itself wrote.
Refs #1185
Refs waired-ai/waired#1313
🤖 Generated with Claude Code
https://claude.ai/code/session_01HJUUSmAfbRdjER1seDdjXm