[BUG] Claude Desktop (Linux): sign-in not persisted on headless/xrdp sessions; error misattributes cause to missing keyring
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Sign-in is not persisted across restarts on a headless Linux session. Every launch shows:
"Your sign-in won't be saved on this device. Install and unlock a system keyring (such as GNOME Keyring), then restart the app."
The keyring was installed, running with --components=pkcs11,secrets, and unlocked the entire time. The real fault is Chromium's password-store backend selection, not a missing keyring.
Chromium detects the backend from XDG_CURRENT_DESKTOP / DESKTOP_SESSION. Neither is populated in an XFCE-over-xrdp session, so detection falls back to a store that cannot reach the secret service and the token is never written.
Launching with --password-store=gnome-libsecret fixes it completely. The flag must be applied to every launch path — menu entry, desktop shortcut, autostart entry, and any script-driven restart. Missing one reproduces the failure: an app update replaced /usr/share/applications/com.anthropic.Claude.desktop and silently reverted one path, and a separate ~/Desktop/*.desktop shortcut carried its own hardcoded Exec=.
Environment
| | |
|---|---|
| claude-desktop | 1.30096.1 (amd64, official Anthropic apt repo — not a community repackage) |
| OS | Ubuntu 24.04.4 LTS, kernel 7.0.0-28-generic |
| Session | XFCE over xrdp, headless VM (Proxmox guest, no physical display) |
| Keyring | gnome-keyring 46.1-2ubuntu0.2, libsecret-1-0 0.21.4-1build3 |
Prior art — the same detection failure is documented for community builds, with the fix already analysed:
- The Arch AUR
claude-desktoppackage lists it as a known caveat: on desktops Chromium doesn't recognise (Hyprland, Sway, …) sign-in is stored insecurely and switching DEs logs you out; remedy is a~/.local/share/applications/override adding--password-store=gnome-libsecret, followed byupdate-desktop-database(skipping that breaks theclaude://sign-in redirect). aaddrick/claude-desktop-debian#719 covers the mirror case (kwallet6 wrongly chosen on a non-KDE session) and proposes: prefer whichever backend actually ownsorg.freedesktop.secrets.
This report is against the official Linux package, where the same detection path is in use.
What Should Happen?
- Correct the error text. "Install and unlock a system keyring" is factually wrong when the keyring is installed, running, and unlocked. It sent me investigating keyring configuration, daemon components, and D-Bus reachability for hours when the fault was backend selection. Something like:
> "Could not select a credential store for this session — try launching with --password-store=gnome-libsecret"
...would have resolved this in minutes. Highest-value fix even if nothing else changes.
- Probe the secret service before declaring it unavailable. When desktop detection yields nothing, query whoever owns
org.freedesktop.secretsand use it, instead of falling back to a store that cannot reach it.
- Expose the backend as a setting, so it doesn't require a command-line flag replicated across every launcher and re-applied after each app update.
Error Messages/Logs
**In-app message (every launch):**
Your sign-in won't be saved on this device. Install and unlock a system keyring
(such as GNOME Keyring), then restart the app.
**`~/.config/Claude/Local State` — detection failure recorded directly:**
{"os_crypt":{"portal":{"prev_desktop":"","prev_init_success":false}},"uninstall_metrics":{"installation_date2":"1776531875"}}
`prev_desktop` is empty and `prev_init_success` is false — no desktop identified, so no usable backend selected.
**Secret service is reachable and unlocked (contradicting the error):**
$ python3 -c "import secretstorage; b=secretstorage.dbus_init(); c=secretstorage.get_default_collection(b); print('locked:', c.is_locked())"
locked: False
**gnome-keyring is running with the secrets component:**
$ pgrep -af gnome-keyring-daemon
1218 /usr/bin/gnome-keyring-daemon --foreground --components=pkcs11,secrets --control-directory=/run/user/123/keyring
2652 /usr/bin/gnome-keyring-daemon --start --foreground --components=secrets
2653 /usr/bin/gnome-keyring-daemon --foreground --components=pkcs11,secrets --control-directory=/run/user/1000/keyring
**Failing launch (no flag) vs. working launch (flag present):**
$ pgrep -af "/usr/lib/claude-desktop/claude-desktop" | head -1
18728 /usr/lib/claude-desktop/claude-desktop # prompts for sign-in
$ pgrep -af "/usr/lib/claude-desktop/claude-desktop" | head -1
3313 /usr/lib/claude-desktop/claude-desktop --password-store=gnome-libsecret # sign-in persists
**Session environment — the variables detection relies on are absent:**
$ systemctl --user show-environment | grep -E "XDG_CURRENT_DESKTOP|DESKTOP_SESSION"
(no output)
Steps to Reproduce
- Provision an Ubuntu 24.04 VM with no physical display; install XFCE and xrdp.
- Connect over RDP and confirm
XDG_CURRENT_DESKTOPis unset:
systemctl --user show-environment | grep XDG_CURRENT_DESKTOP → no output
- Install claude-desktop from the official apt repo (
downloads.claude.ai/claude-desktop/apt/stable). - Confirm gnome-keyring is running and unlocked:
pgrep -af gnome-keyring-daemon → shows --components=pkcs11,secrets
secret-tool / secretstorage query → collection reports locked: False
- Launch Claude Desktop from the applications menu or desktop icon. Sign in.
- Quit the app and relaunch it the same way.
Result: prompted to sign in again, with the "install and unlock a system keyring" message — despite the keyring being installed and unlocked.
Control: quit, then launch with /usr/bin/claude-desktop --password-store=gnome-libsecret. Sign in once; the session now persists across restarts.
Claude Model
None
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
version 1.30096.1 (194d93) - claude desktop for linux
Platform
Anthropic API
Operating System
Ubuntu/Debian Linux
Terminal/Shell
Xterm
Additional Information
_No response_
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗