Part of #5.
A person who was fully set up can break their install by pasting the wrong token once, and there is no way to undo it from the popover.
What is there today
POST /api/token (app/Uplink/desktop-agent.ts#L309) validates only the shape, then writes and
activates the token before checking whether it works:
writeToken(cleaned)atapp/Uplink/desktop-agent.ts#L313persists it to the Keychain.process.env.CLAUDE_CODE_OAUTH_TOKEN = cleanedat#L315injects it into the running process.checkClaude()at#L316runs afterwards, and its answer changes nothing that was just written.
tokenLooksValid (app/Uplink/settings.ts#L101) matches /^sk-ant-/, so a token that is expired, for
the wrong account, or copied from another Mac passes.
Then ClaudeEngine only drops the variable when it is empty
(app/Uplink/engine.ts#L91), so a bad token now overrides a claude CLI that was logged in
interactively and working. The person's install was fine before they touched it.
There is also no way back: deleteToken exists (app/Uplink/settings.ts#L88) and nothing in the
popover calls it.
Proposal
- Check before storing. Probe with the candidate token in a temporary environment, and write to the Keychain only if it answers.
- On failure, say which failure it was. "That token was rejected" is different from "that does not
look like a whole token", and the existing wrapped-paste message
(
app/Uplink/desktop-agent.ts#L312) should stay for the shape case. - Add a remove action that calls
deleteToken, so a person can fall back to the CLI's own login. - When the CLI is already logged in and working without a token, say so, and do not ask for one. The token exists for the background service case, not as a requirement.
Requirements
- Never persist a credential that has not answered once.
- Never leave the process environment holding a token the Keychain does not have, or a restart silently changes behaviour.
- Removing the token must restore the previous state, which means not having clobbered it: read what was there before deciding.
- Keep
cleanToken(app/Uplink/settings.ts#L92). The wrapped-paste case already bit this project once and the comment says so.
Acceptance
- Pasting a shape-valid but rejected token leaves the Keychain unchanged and reports the rejection.
- Removing the token restores a working CLI-login install.
- A Mac with a logged-in CLI and no token shows the sign-in step as satisfied.