packages/adapters/claude-local/src/server/__fixtures__/setup-token-success.md
setup-token success characterization fixture2.1.205packages/adapters/claude-local/src/server/__fixtures__/setup-token-success.md<REDACTED_*> placeholder. The raw PTY capture that
produced this document was written only to a sandbox-local file and shredded
after redaction.This fixture resolves the "Deferred success-token assumption" in
setup-token.md: it records a real, end-to-end successful
login through a PTY, with the human completing the browser authorization out of
band. It is the success counterpart to that document, which characterized the
prompt, the URL, and the invalid-code retry path only.
Normalized rendered text (spinner frames, cursor-movement sequences, and other terminal control sequences omitted; word spacing restored from cursor-forward sequences):
Welcome to Claude Code v2.1.205
Opening browser to sign in…
<spinner frames>
Browser didn't open? Use the url below to sign in (c to copy)
<REDACTED_AUTHORIZATION_URL>
Paste code here if prompted > <MASKED_CODE>
✓ Long-lived authentication token created successfully!
Your OAuth token (valid for 1 year):
<REDACTED_SETUP_TOKEN>
Store this token securely. You won't be able to see it again.
Use this token by setting: export CLAUDE_CODE_OAUTH_TOKEN=<token>
The command reached the success screen and then closed the PTY and exited on its
own — no host-side kill was required (unlike the invalid-code path in
setup-token.md, which stayed at a retry UI and had to be terminated).
Unchanged from setup-token.md; confirmed again on the success run:
https://claude.com/cai/oauth/authorizeclient_id, code, code_challenge,
code_challenge_method, redirect_uri, response_type, scope, stateredirect_uri value host: https://platform.claude.com/oauth/code/callback.scope value: user:inference. Observed response_type: code.This is the operational detail that a driver must get right, and it is not obvious from the prompt characterization alone.
<authorization_code>#<state> — the # delimiter and the
trailing state match the state query value from the authorization URL.code + "\r" did not submit. The Claude Code input
is an Ink text field with paste handling: when the code and the carriage
return arrive glued together in one write burst, the trailing \r is folded
into the pasted text instead of being read as a Return (submit) key. The stream
stalls at the prompt with the code masked but unsubmitted, and no error is
emitted.\r written after the paste submits on the first
Return. The reliable sequence is: write the code bytes, let the paste buffer
settle briefly, then write \r as its own write.* characters; the code itself is never rendered by
Claude. (The non-secret state suffix may remain visible at the tail of the
masked echo, because it is public — it is the same state carried in the URL.)Implementation note for
setup-token-runner.ts: the runner now writes the code andCODE_SUBMISSION_TERMINATORas two separate writes —driver.write(code), a short settle delay (CODE_SUBMIT_SETTLE_MS), thendriver.write(CODE_SUBMISSION_TERMINATOR). A single gluedcode + "\r"burst did not submit against this Claude Code build: the trailing\rfolded into the pasted text. The separate Return, after the paste buffer settles, submits on the first Return. Confirm the exact settle delay in the live end-to-end test.
The provisional assumption in setup-token.md — an opaque token shaped like
sk-ant-oat01-<opaque> on the interactive terminal output stream after
successful authorization — is confirmed:
sk-ant-oat01- (literal; hyphen-delimited segments sk, ant,
oat01, then the opaque secret).[A-Za-z0-9_-]; it
may contain -, so a parser must not assume the token stops at the first
hyphen or non-alphanumeric after the prefix.Your OAuth token (valid for 1 year): and followed by Store this token securely. You won't be able to see it again. — these bracket the token region and are stable anchors for a
parser.claude setup-token does not persist the token. After a successful run:
~/.claude.json gained no oauthAccount and no token-bearing field (it held
only machine/user metadata: userID, machineID, migration flags, etc.).~/.claude/.credentials.json was written.Resolved by this capture:
code + "\r" vs. a separate Return).Still worth confirming in the live end-to-end implementation test before locking parser/runner assertions:
setup-token-runner.ts
treats exitCode === 0 as success — assert this against a live run.One PTY harness drove claude setup-token to completion: it captured the
redacted authorization URL, a human completed the browser authorization out of
band, the harness typed the returned code and submitted it with a separate
Return, and Claude Code printed a sk-ant-oat01-… token and exited on its own. A
literal scan of this document confirms it contains no authorization query values,
browser code, or live token.