claude-code - 💡(How to fix) Fix claude setup-token silently fails on headless Linux servers (no system keyring) [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#56045Fetched 2026-05-05 05:59:37
View on GitHub
Comments
1
Participants
2
Timeline
4
Reactions
0
Author
Timeline (top)
labeled ×3commented ×1

claude setup-token runs the OAuth browser flow successfully and exits cleanly, but no credentials are persisted on a headless Linux server lacking a system keyring. The next claude -p ... invocation still returns Not logged in · Please run /login.

Error Message

Browser flow opens, code is pasted, command exits with no error

  1. Detect missing keyring at the start of setup-token and warn loudly ("no keyring backend; will write to ~/.claude/.credentials.json with mode 0600 — OK?"), then write to FS

Root Cause

Anyone deploying Claude Code on a server (CI workers, autonomous-agent runtimes, headless dev VMs, etc.) hits this exact silent-fail. The standard advice — "run `claude setup-token`" — fails silently, and the FS fallback only happens to work because the desktop install path differs.

Fix Action

Workaround

The token is account-bound, not device-bound, so copying ~/.claude/.credentials.json from a desktop machine where OAuth landed correctly works:

```bash scp /.claude/.credentials.json server:/.claude/.credentials.json ssh server 'chmod 600 ~/.claude/.credentials.json' ```

After this, claude -p \"ping\" returns the response immediately. Caveat: when OAuth refreshes silently in the desktop's claude session, the server's copy goes stale; needs periodic re-scp.

RAW_BUFFERClick to expand / collapse

Summary

claude setup-token runs the OAuth browser flow successfully and exits cleanly, but no credentials are persisted on a headless Linux server lacking a system keyring. The next claude -p ... invocation still returns Not logged in · Please run /login.

Environment

  • claude version: 2.1.126 (also reproduced on 2.1.x older builds)
  • OS: Ubuntu 24.04 LTS (server install — no desktop session)
  • No keyring daemon installed: secret-tool, gnome-keyring-daemon, kwalletd6 all absent
  • Same OAuth flow on a desktop Ubuntu host (KDE + kwalletd6 running) succeeds and writes ~/.claude/.credentials.json as plain JSON

Reproduction

On a headless Linux VM with no keyring daemon installed:

```bash $ claude setup-token

Browser flow opens, code is pasted, command exits with no error

$ ls -la ~/.claude/.credentials.json ls: cannot access '/home/user/.claude/.credentials.json': No such file or directory $ claude -p "ping" Not logged in · Please run /login ```

Expected behavior

Either:

  1. Detect missing keyring at the start of setup-token and warn loudly ("no keyring backend; will write to ~/.claude/.credentials.json with mode 0600 — OK?"), then write to FS
  2. Always prefer FS storage on Linux (the desktop host already does this — both desktop and server were on the same client version), making behavior consistent
  3. At minimum, fail visibly when the keychain write fails so the user knows OAuth didn't actually persist

Currently the silent-fail mode wastes the OAuth browser dance and leaves users guessing why claude -p still says "not logged in".

Workaround

The token is account-bound, not device-bound, so copying ~/.claude/.credentials.json from a desktop machine where OAuth landed correctly works:

```bash scp /.claude/.credentials.json server:/.claude/.credentials.json ssh server 'chmod 600 ~/.claude/.credentials.json' ```

After this, claude -p \"ping\" returns the response immediately. Caveat: when OAuth refreshes silently in the desktop's claude session, the server's copy goes stale; needs periodic re-scp.

Why this matters

Anyone deploying Claude Code on a server (CI workers, autonomous-agent runtimes, headless dev VMs, etc.) hits this exact silent-fail. The standard advice — "run `claude setup-token`" — fails silently, and the FS fallback only happens to work because the desktop install path differs.

Suggested fix

In the OAuth-persist code path, after the keychain write call:

  1. Verify the credential is actually retrievable (round-trip read), or
  2. If keyring backend reports unavailable / no-op, fall through to FS storage with a chmod 0600 and a clear message to the user about the storage location.

extent analysis

TL;DR

The most likely fix is to modify the OAuth-persist code path to fall back to file system storage with a clear message when the keyring backend is unavailable.

Guidance

  • Verify if the keyring backend is available before attempting to write credentials, and provide a clear error message if it's not.
  • Implement a fallback to file system storage with appropriate permissions (e.g., chmod 0600) when the keyring backend is unavailable.
  • Consider adding a round-trip read verification to ensure the credential is actually retrievable after writing.
  • Review the current implementation to ensure consistent behavior across different environments (e.g., desktop and server).

Example

No code snippet is provided as the issue does not contain sufficient information about the implementation details.

Notes

The suggested fix assumes that the keyring backend is the primary storage mechanism, and falling back to file system storage is a suitable alternative. However, this may not be the case in all scenarios, and additional considerations may be necessary.

Recommendation

Apply a workaround by manually copying the ~/.claude/.credentials.json file from a desktop machine where OAuth was successful, and periodically updating it to ensure the token remains valid. This is not a permanent fix but can help mitigate the issue until a proper solution is implemented.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

Either:

  1. Detect missing keyring at the start of setup-token and warn loudly ("no keyring backend; will write to ~/.claude/.credentials.json with mode 0600 — OK?"), then write to FS
  2. Always prefer FS storage on Linux (the desktop host already does this — both desktop and server were on the same client version), making behavior consistent
  3. At minimum, fail visibly when the keychain write fails so the user knows OAuth didn't actually persist

Currently the silent-fail mode wastes the OAuth browser dance and leaves users guessing why claude -p still says "not logged in".

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING