Files
aaddrick--claude-desktop-de…/docs/troubleshooting.md
T
wehub-resource-sync 3e076d4dd9
Deploy Worker / deploy (push) Failing after 1s
Shellcheck / Check shell scripts (push) Failing after 1s
CI / Build Packages (amd64 - appimage) (push) Has been skipped
CI / Build Packages (amd64 - deb) (push) Has been skipped
CI / Build Packages (amd64 - rpm) (push) Has been skipped
CI / Build Packages (arm64 - appimage) (push) Has been skipped
CI / Build Packages (arm64 - deb) (push) Has been skipped
CI / Test Flags Parsing (push) Failing after 1s
BATS Tests / BATS unit tests (push) Failing after 1s
CI / Build Packages (arm64 - rpm) (push) Has been skipped
CI / Test Build Artifacts (amd64) (push) Has been skipped
CI / Test Build Artifacts (arm64) (push) Has been skipped
CI / Update APT Repository (push) Has been cancelled
CI / Mirror Official .deb to Release (push) Has been cancelled
CI / Update DNF Repository (push) Has been cancelled
CI / Update AUR Package (push) Has been cancelled
CI / Create Release (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:29:21 +08:00

686 lines
29 KiB
Markdown

[< Back to README](../README.md)
# Troubleshooting
Run the built-in doctor first — it detects most of the problems on this page and prints fix commands inline:
```bash
# Deb / RPM install
claude-desktop-unofficial --doctor
# AppImage
./claude-desktop-unofficial-*.AppImage --doctor
```
## Built-in Diagnostics
`--doctor` runs this check set (from `scripts/doctor.sh`) and prints pass/fail results with suggested fixes:
| Check | What it verifies |
|-------|-----------------|
| Installed version | Package version from the manager that owns the install (rpm ownership of the binary is probed first, then dpkg) |
| Version drift | Installed upstream version vs the newest in Anthropic's official APT pool (network best-effort; skipped offline) |
| Package-name collision | Warns when a legacy pre-rename `claude-desktop` install from this project sits alongside Anthropic's official APT repo — before the rename to `claude-desktop-unofficial` both pools shipped a package named `claude-desktop`, and whichever version sorts higher wins on upgrade |
| Display server | Wayland/X11 detection and the XWayland/native-Wayland mode in effect |
| Input method | IBus/GTK immodule sanity (ibus-gtk3 installed, immodules cache fresh, XWayland-routes-IBus-through-XIM note) |
| Legacy environment | Warns on 2.x variables no longer honored (`CLAUDE_TITLEBAR_STYLE`, `CLAUDE_MENU_BAR`, `CLAUDE_KEEP_AWAKE`); `CLAUDE_QUIT_ON_CLOSE` gets a pointer to its native replacement, Settings > General > System Tray |
| Electron binary | The official ELF at `/usr/lib/claude-desktop-unofficial/claude-desktop` exists and is executable |
| Chrome sandbox | `/usr/lib/claude-desktop-unofficial/chrome-sandbox` has 4755/root |
| User namespaces | AppArmor userns restriction and whether the `claude-desktop-unofficial` profile is loaded (Ubuntu 24.04+; run with `sudo` to confirm the kernel-loaded state) |
| SingletonLock | Stale lock file detection |
| Password store | Reports upstream `os_crypt` autodetect vs a `CLAUDE_PASSWORD_STORE` override (informational) |
| MCP config | JSON validity and server count |
| Node.js | Version (v20+ recommended for MCP servers) |
| Desktop entry | `.desktop` file presence |
| Disk space | Free space on the config partition |
| Cowork: KVM | `/dev/kvm` present and read-write |
| Cowork: vsock | `/dev/vhost-vsock` present |
| Cowork: QEMU stack | Arch-matched `qemu-system-*` on `PATH`, firmware at the officially probed paths, virtiofsd (off-PATH locations tolerated), plus a one-line readiness summary |
| Filename limit | `NAME_MAX` ≥ 200 under `~/.claude/projects` (catches eCryptfs) |
| Cowork daemon (2.x leftover) | Orphaned `cowork-vm-service.js` from a 2.x install still holding locks |
| Recent crashes | 3+ Electron coredumps in the last 7 days → GPU-FATAL pointer ([#583](https://github.com/aaddrick/claude-desktop-debian/issues/583)) |
| Log file | Launcher log size |
Setting `COWORK_VM_BACKEND=bwrap` additionally runs the legacy bubblewrap diagnostics for the parked `scripts/cowork-fallback/` path — the shipped client has no bwrap backend.
When opening an issue, include the output of `--doctor` to help with diagnosis.
## Application Logs
Runtime logs are available at:
```
~/.cache/claude-desktop-debian/launcher.log
```
## Common Issues
### Window Scaling Issues
If the window doesn't scale correctly on first launch:
1. Right-click the Claude Desktop tray icon
2. Select "Quit" (do not force quit)
3. Restart the application
This allows the application to save display settings properly.
### Global Hotkey Not Working (Wayland)
If the global hotkey (Ctrl+Alt+Space) doesn't work, ensure you're not running in native Wayland mode:
1. Check your logs at `~/.cache/claude-desktop-debian/launcher.log`
2. Look for "Using X11 backend via XWayland" - this means hotkeys should work
3. If you see "Using native Wayland backend", unset `CLAUDE_USE_WAYLAND` or ensure it's not set to `1`
**Note:** Native Wayland mode routes the shortcut through the XDG GlobalShortcuts portal, which only works on some compositors (GNOME ≤ 49, KDE) due to Electron/Chromium limitations.
See [configuration.md](configuration.md#wayland-support) for more details on the `CLAUDE_USE_WAYLAND` environment variable.
### Keyboard Input Doesn't Work (IBus / GTK Input Method)
If typing into the chat does nothing, characters get swallowed, or
dead-key sequences (e.g. ``` `e ``` → `è`) don't compose, your GTK
input module integration with the bundled GTK is broken.
Common symptoms:
- No characters appear when typing into any text field
- The first keystroke after focus is dropped, subsequent ones work
- CJK input methods (IBus, Fcitx) not engaging
- Compose key / dead-key sequences silently drop
**First step: run `claude-desktop-unofficial --doctor`.** It checks for the
common misconfigurations and prints fix commands inline:
- `ibus-gtk3` package missing while `GTK_IM_MODULE=ibus`
- GTK immodules cache stale (the active module isn't listed by
`gtk-query-immodules-3.0`)
- XWayland session routing IBus through XIM (lossy for some IMEs —
set `CLAUDE_USE_WAYLAND=1` to use native Wayland IME)
- Active value of `CLAUDE_GTK_IM_MODULE` if you've set the override
If `--doctor` is clean but input still misbehaves, switch the
launcher to a different GTK input module. Set `CLAUDE_GTK_IM_MODULE`
and Claude Desktop will propagate it as `GTK_IM_MODULE` to Electron
at startup:
```bash
# Bypass IBus entirely — uses the X Input Method (XIM) protocol
CLAUDE_GTK_IM_MODULE=xim claude-desktop-unofficial
# To make it persistent, export it from your shell profile:
# echo 'export CLAUDE_GTK_IM_MODULE=xim' >> ~/.profile
```
Valid values: anything your GTK installation supports (`xim`, `ibus`,
`fcitx`, `simple`, etc.). When the override is active, the launcher
logs a line to `~/.cache/claude-desktop-debian/launcher.log`:
```
GTK_IM_MODULE override: ibus -> xim (via CLAUDE_GTK_IM_MODULE)
```
**Trade-off:** `xim` is the lowest-common-denominator input module
and does not support advanced IME features like CJK candidate
windows or rich compose-key sequences. Only reach for it if your
real input method (IBus/Fcitx) is broken; if you depend on CJK or
compose, prefer fixing the IBus/Fcitx integration instead.
### Repeated Electron Crashes / GPU Process FATAL ([#583](https://github.com/aaddrick/claude-desktop-debian/issues/583))
If Claude Desktop crashes repeatedly on launch or shortly after,
the most common cause on Linux is the Chromium GPU process hitting
a FATAL exhaustion path. `claude-desktop-unofficial --doctor` surfaces this
when `systemd-coredump` shows 3+ Electron crashes in the last 7
days, pointing at this issue.
Two ways to disable hardware acceleration as a workaround:
1. **In-app:** Settings → toggle hardware acceleration off →
restart Claude Desktop. Persists in the upstream config.
2. **Env var (headless / persists across reinstalls):** set
`CLAUDE_DISABLE_GPU=1` in the environment before launching.
```bash
# One-off:
CLAUDE_DISABLE_GPU=1 claude-desktop-unofficial
# Persistent (shell profile):
echo 'export CLAUDE_DISABLE_GPU=1' >> ~/.profile
```
When `CLAUDE_DISABLE_GPU=1` is set, the launcher passes
`--disable-gpu --disable-software-rasterizer` to the official binary
(see `scripts/launcher-common.sh`). This is the same pair of flags
applied automatically inside XRDP sessions, where software
rendering is required regardless. Either signal is sufficient —
the launcher won't stack duplicate flags.
If the previous launch already died with the GPU-process FATAL
signature and `CLAUDE_DISABLE_GPU` is unset, the next launch
auto-applies the same flags and keeps them applied on subsequent
launches. Set `CLAUDE_DISABLE_GPU=0` to suppress the auto-fallback
when retesting hardware acceleration after a driver fix — any
explicitly set value suppresses it; only `1` forces the flags on.
**When to prefer which:** the in-app toggle is friendlier if you
can reach Settings without the app crashing. Reach for
`CLAUDE_DISABLE_GPU=1` when the app crashes before you can open
Settings, when running in environments with no GPU available
(XRDP, headless CI smoke tests, some VMs), or when you want the
behavior to persist across reinstalls and config resets.
Tracking issue: [#583](https://github.com/aaddrick/claude-desktop-debian/issues/583).
### Black screen on Fedora KDE with Intel Iris Xe ([#706](https://github.com/aaddrick/claude-desktop-debian/issues/706))
If the window opens but renders entirely black on Fedora KDE with
Intel Iris Xe graphics (TigerLake-LP GT2), force Mesa's reference
software rasterizer:
```bash
MESA_LOADER_DRIVER_OVERRIDE=softpipe claude-desktop-unofficial
```
The failing launch logs this signature in
`~/.cache/claude-desktop-debian/launcher.log`:
```
KMS: DRM_IOCTL_MODE_CREATE_DUMB failed: Permission denied
```
**Try the faster fallbacks first.** softpipe renders everything on
the CPU with no acceleration of any kind and is noticeably slow.
Before reaching for it:
1. `CLAUDE_DISABLE_GPU=1 claude-desktop-unofficial` — disables
hardware acceleration entirely (see the previous section).
2. `LIBGL_ALWAYS_SOFTWARE=1 claude-desktop-unofficial` — selects llvmpipe,
Mesa's supported software fallback, several times faster than
softpipe.
Use `MESA_LOADER_DRIVER_OVERRIDE=softpipe` only if
`LIBGL_ALWAYS_SOFTWARE=1` also produces a black screen. To make it
persistent:
```bash
echo 'export MESA_LOADER_DRIVER_OVERRIDE=softpipe' >> ~/.profile
```
Tracking issue:
[#706](https://github.com/aaddrick/claude-desktop-debian/issues/706).
Credit: workaround discovered and confirmed by
[@dubreal](https://github.com/dubreal) while diagnosing
[#593](https://github.com/aaddrick/claude-desktop-debian/issues/593)
and
[#599](https://github.com/aaddrick/claude-desktop-debian/pull/599).
### AppImage Sandbox Warning
AppImages run with `--no-sandbox` because Electron's chrome-sandbox requires root privileges for unprivileged namespace creation, which the FUSE-mounted AppImage cannot provide. This is a known limitation of the AppImage format with Electron applications.
For enhanced security, consider:
- Using the .deb or .rpm package instead
- Running the AppImage within a separate sandbox (e.g., bubblewrap)
- Using Gear Lever's integrated AppImage management for better isolation
### Claude Desktop crashes immediately on launch (Ubuntu 24.04+, AppArmor blocks user namespaces)
The `.deb` handles this automatically — this section is for the rare case
where it doesn't. Ubuntu 24.04+ sets
`apparmor_restrict_unprivileged_userns=1`, blocking the user namespaces
Chromium's sandbox needs, which kills the app on startup before any window
appears. The deb's `postinst` installs a scoped AppArmor profile
(`/etc/apparmor.d/claude-desktop-unofficial`) that grants `userns` to the official
Electron binary only — exactly as the `google-chrome`, `code`, and `slack`
packages do — so a normal install needs no action. (X11 sessions only:
on Wayland the deb launcher runs with `--no-sandbox`, and AppImage builds
always do, so neither can hit this crash.)
You only need to act if the app still crashes on launch with:
- `FATAL:sandbox/linux/services/credentials.cc:131] Check failed: . :
Permission denied (13)` in
`~/.cache/claude-desktop-debian/launcher.log` (the line number varies by
Electron version), and
- a `Trace/breakpoint trap` / core dump (exit code 133).
Run `sudo claude-desktop-unofficial --doctor` first — the **User namespaces** check
reports whether the profile is actually loaded into the kernel (reading the
loaded set needs root; without `sudo` it can only confirm the profile is
present on disk). To (re)install it manually:
```bash
sudo tee /etc/apparmor.d/claude-desktop-unofficial <<'EOF'
abi <abi/4.0>,
include <tunables/global>
profile claude-desktop-unofficial /usr/lib/claude-desktop-unofficial/claude-desktop flags=(unconfined) {
userns,
include if exists <local/claude-desktop-unofficial>
}
EOF
sudo apparmor_parser -r /etc/apparmor.d/claude-desktop-unofficial
```
To customize the profile on a `.deb` install, put overrides in
`/etc/apparmor.d/local/claude-desktop-unofficial` — they survive upgrades; direct
edits to the managed profile are rewritten by the `postinst` on every
upgrade (a profile without the package's marker header is treated as
hand-made and preserved instead).
Don't use `--no-sandbox` as a permanent fix on the `.deb` — it disables the
Chromium sandbox entirely, which the package is built to keep.
**Security note:** the profile grants the unconfined profile plus the
`userns` capability to the official Electron binary only, not system-wide —
narrower than relaxing `kernel.apparmor_restrict_unprivileged_userns`
globally, which would lift the restriction for every program on the host.
Review against your threat model before applying.
### Cowork unavailable (doctor: "Cowork: unavailable until the KVM stack is complete")
Cowork on the official Linux client is KVM-only — there is no bubblewrap or
host-direct fallback. If Cowork won't start, run
`claude-desktop-unofficial --doctor`;
the Cowork Mode section reports each missing piece with a fix:
- **`/dev/kvm` not present** — enable hardware virtualization (VT-x/AMD-V)
in your BIOS/UEFI, then `sudo modprobe kvm`.
- **`/dev/kvm` not read-write** — `sudo usermod -aG kvm $USER`, then log
out and back in.
- **`/dev/vhost-vsock` missing** — `sudo modprobe vhost_vsock`; persist
with `echo vhost_vsock | sudo tee /etc/modules-load.d/vhost_vsock.conf`.
- **`qemu-system-x86_64` (or `qemu-system-aarch64`) not on PATH** —
install your distro's QEMU/KVM packages; the doctor prints the exact
command.
- **Firmware missing at the probed paths** — the official client hardcodes
its firmware probe list (`/usr/share/OVMF/OVMF_CODE_4M.fd`,
`/usr/share/OVMF/OVMF_CODE.fd`; arm64: `/usr/share/AAVMF/AAVMF_CODE.fd`)
with no env override, so edk2 firmware installed elsewhere is not found.
Our RPM package's `%post` creates a compat symlink at the probed path
automatically (CW-1); on other layouts, symlink your edk2 firmware to
one of the probed paths by hand.
- **virtiofsd not found** — install it (Debian/Ubuntu:
`qemu-system-common`; Fedora: `virtiofsd`).
### Cowork: virtiofsd not found (Fedora/RHEL)
On Fedora and RHEL, `virtiofsd` installs to `/usr/libexec/virtiofsd`, which
is outside `$PATH`. The `--doctor` check searches the well-known off-PATH
locations (`/usr/libexec/virtiofsd`, `/usr/lib/qemu/virtiofsd`,
`/usr/lib/virtiofsd`) and reports `found at ... (not on PATH)` in that case.
The official client's virtiofsd spawn semantics haven't been verified
against those off-PATH locations — if the doctor finds virtiofsd off PATH
but Cowork still fails to start a VM, put it on `PATH`:
```bash
sudo ln -s /usr/libexec/virtiofsd /usr/local/bin/virtiofsd
```
### Cowork: cross-device link error on Fedora tmpfs /tmp
On Fedora, `/tmp` is a tmpfs by default. VM bundle downloads may fail with `EXDEV: cross-device link not permitted` when moving files from `/tmp` to `~/.config/Claude/`. This was reported against the 2.x backend and has not been re-verified against the official client; if you hit it:
**Fix:** Set `TMPDIR` to a directory on the same filesystem:
```bash
mkdir -p ~/.config/Claude/tmp
TMPDIR=~/.config/Claude/tmp claude-desktop-unofficial
```
Or add `TMPDIR=%h/.config/Claude/tmp` to the `Exec=` line in your `.desktop` file.
### Cowork on Ubuntu 24.04+: bwrap fallback probe fails (parked diagnostics only)
This applies **only** to the opt-in bubblewrap fallback
(`COWORK_VM_BACKEND=bwrap`, `scripts/cowork-fallback/`). The default Cowork
backend is KVM and is not affected by the user-namespace restriction below.
Ubuntu 24.04+ sets `apparmor_restrict_unprivileged_userns=1`, which blocks
the user namespaces bwrap needs, so the doctor's `bubblewrap: sandbox probe
failed` warning is expected there whether or not you ever set
`COWORK_VM_BACKEND=bwrap`.
**No package installs a bwrap AppArmor profile.** The only workaround we
can document attaches the profile to the **shared** `/usr/bin/bwrap`
binary, which grants `userns` to *every* program on the host that runs
bwrap through that same path — Flatpak, Steam, your own scripts — not just
Claude:
```bash
sudo tee /etc/apparmor.d/bwrap <<'EOF'
abi <abi/4.0>,
include <tunables/global>
profile bwrap /usr/bin/bwrap flags=(unconfined) {
userns,
include if exists <local/bwrap>
}
EOF
sudo apparmor_parser -r /etc/apparmor.d/bwrap
```
Review that blast radius against your threat model before applying it.
**Why this can't be scoped to Claude in documentation alone:** the
per-application AppArmor pattern that opam and Apptainer use (see
[opam's profile](https://gitlab.com/apparmor/apparmor/-/blob/master/profiles/apparmor.d/opam)
and [Apptainer#2262](https://github.com/apptainer/apptainer/pull/2262))
attaches `flags=(unconfined)` to a binary *they own* that creates the
namespace — opam's `bwrap` copy, Apptainer's `starter-suid`. Claude has no
equivalent owned binary in this path: the namespace is created by the
system's shared `/usr/bin/bwrap`, and the scoped
`/etc/apparmor.d/claude-desktop-unofficial` profile installed above covers
only the Electron binary — a separate `bwrap` child process is not covered
by it (see `scripts/packaging/deb.sh`). Narrowing this for real needs a
Claude-owned wrapper binary at a stable path for a profile to attach to;
that's tracked as follow-up work on
[#542](https://github.com/aaddrick/claude-desktop-debian/issues/542) and is
not implemented yet.
This only affects launches that opt into `COWORK_VM_BACKEND=bwrap` on
Ubuntu 24.04+ — the default KVM backend never spawns bwrap and is
unaffected either way.
**AppImage:** the mount path changes every run
(`/tmp/.mount_claudeXXXXXX/…`), so an AppImage build can't ship or pin a
profile keyed to its own binary path. That doesn't matter for bwrap
specifically, though: `/usr/bin/bwrap` is a fixed host path regardless of
where the AppImage mounts, so the same system-wide recipe and warning above
apply unchanged to an AppImage-launched bwrap fallback. (The Electron
launch-crash profile above never applies to AppImage builds — they always
run with `--no-sandbox`, see
["AppImage Sandbox Warning"](#appimage-sandbox-warning) — so there's
nothing AppImage-specific to add there either.)
No package ships a bwrap profile as of v3.0.0+; the deb's `postrm` still
removes the 2.x-era `/etc/apparmor.d/claude-desktop-bwrap` leftover (and a
`claude-desktop-unofficial-bwrap` sibling, if one exists) on purge.
**Credit:** [@hfyeh](https://github.com/hfyeh)
([#351](https://github.com/aaddrick/claude-desktop-debian/issues/351)) for
the original profile workaround;
[@slovdahl](https://github.com/slovdahl) for flagging the system-wide
over-scope and the opam/Apptainer precedent, in
[PR #434](https://github.com/aaddrick/claude-desktop-debian/pull/434#issuecomment-4352273336)
(tracked in [#542](https://github.com/aaddrick/claude-desktop-debian/issues/542)).
### Cowork: ENAMETOOLONG on encrypted home (eCryptfs)
Cowork sessions can fail with an opaque `ENAMETOOLONG` error when
`$HOME` is on a filesystem with a short filename limit. The common
case is **eCryptfs** — the legacy "encrypted home" option on older
Ubuntu and Linux Mint installs, which caps individual filenames at
143 chars because of filename-encryption overhead. Standard
filesystems (ext4, btrfs, xfs, zfs) cap at 255 chars and are fine.
**Why it happens:** Claude Code creates one directory per session
under `~/.claude/projects/`, named after the sanitized host CWD. For
cowork sessions the host CWD is the deeply nested outputs dir under
`~/.config/Claude/local-agent-mode-sessions/<accountId>/<orgId>/local_<uuid>/outputs`,
which sanitizes to ~180 chars — fits ext4 but exceeds the eCryptfs
143-char ceiling.
**Diagnosis:** `claude-desktop-unofficial --doctor` detects this automatically
and emits a `[WARN] Filename limit: NAME_MAX=143…` line, plus an
eCryptfs-specific hint when the filesystem type matches. You can
also check by hand:
```bash
df -T $HOME # look for type "ecryptfs"
getconf NAME_MAX $HOME # eCryptfs reports 143; ext4 reports 255
```
**Workaround:** move Claude's data onto a separate LUKS-encrypted
ext4 volume (NAME_MAX = 255) and symlink the original paths back.
`~/.claude/` is the critical one — that's where Claude Code creates
the long-named per-session dirs that overflow the limit — and
`~/.config/Claude/` plus `~/.cache/claude-desktop-debian/` are
relocated alongside it so all Claude state lives on the same volume.
This keeps the data encrypted at rest while sidestepping the
eCryptfs filename-length cap.
```bash
# 1. Create a 2 GB LUKS container
sudo dd if=/dev/urandom of=/opt/claude-secure.img bs=1M count=2048 \
status=progress
sudo cryptsetup luksFormat /opt/claude-secure.img
sudo cryptsetup open /opt/claude-secure.img claude-secure
sudo mkfs.ext4 /dev/mapper/claude-secure
# 2. Mount and move Claude's data in
sudo mkdir -p /mnt/claude-secure
sudo mount /dev/mapper/claude-secure /mnt/claude-secure
sudo chown "$USER:$USER" /mnt/claude-secure
mv ~/.config/Claude /mnt/claude-secure/Claude-config
mv ~/.cache/claude-desktop-debian /mnt/claude-secure/claude-cache
# ~/.claude may not exist yet on a fresh install — create the target
# either way so the symlink below resolves.
if [ -e ~/.claude ]; then
mv ~/.claude /mnt/claude-secure/claude-home
else
mkdir -p /mnt/claude-secure/claude-home
fi
ln -s /mnt/claude-secure/Claude-config ~/.config/Claude
ln -s /mnt/claude-secure/claude-cache ~/.cache/claude-desktop-debian
ln -s /mnt/claude-secure/claude-home ~/.claude
# 3. Verify the filename limit and the symlinks
getconf NAME_MAX /mnt/claude-secure # should print 255
mountpoint /mnt/claude-secure # confirms the volume is mounted
readlink ~/.claude # /mnt/claude-secure/claude-home
readlink ~/.config/Claude # /mnt/claude-secure/Claude-config
```
**If you've set `CLAUDE_CONFIG_DIR`** (or otherwise reconfigured
Claude Code to use a directory other than `~/.claude/`), the
`~/.claude` symlink above doesn't apply — adapt the path to wherever
your Claude Code config actually lives. The constraint is the same:
the directory tree where Claude Code creates per-session project
dirs must sit on a filesystem with `NAME_MAX` ≥ ~200.
**Auto-mount at login** with `pam_mount` so the volume unlocks
without a manual `cryptsetup open`:
```bash
sudo apt install libpam-mount
```
Add a `<volume>` entry to `/etc/security/pam_mount.conf.xml`
(replace `YOUR_USERNAME` with your login name):
```xml
<volume user="YOUR_USERNAME" fstype="crypt"
path="/opt/claude-secure.img"
mountpoint="/mnt/claude-secure"
options="" />
```
`libpam-mount` registers itself with `/etc/pam.d/common-auth` and
`/etc/pam.d/common-session` automatically on install.
**Notes:**
- Tested on Linux Mint with LightDM as the display manager.
- **LUKS passphrase tradeoff:** for `pam_mount` to unlock silently
at login the LUKS passphrase must match your login password. That
means one compromise unlocks both your session and the encrypted
volume — equivalent to the threat surface eCryptfs already had,
but worth a deliberate choice. Use a distinct LUKS passphrase if
you'd rather be prompted on each unlock.
- **Confidentiality posture vs eCryptfs.** The LUKS image lives at
`/opt/claude-secure.img`, outside `$HOME` and outside whatever
encryption envelope eCryptfs gives you. If `pam_mount` ever fails
silently — wrong passphrase, mount race at login, profile error —
Claude won't start (the symlink targets won't exist), so writes
fail loudly rather than landing on plaintext disk. Verify with
`mountpoint /mnt/claude-secure` after login if you're unsure.
- 2 GB is a conservative starting size; the Claude config
directory can exceed 500 MB once cowork session history
accumulates. Resize if needed.
- This is a system-wide change that affects login flow — review
the pam_mount config against your threat model before applying.
Credit: reported with detailed `--doctor` output by
[@michelsfun](https://github.com/michelsfun); LUKS-volume workaround
contributed by [@proffalken](https://github.com/proffalken) in
[#590](https://github.com/aaddrick/claude-desktop-debian/issues/590).
### Autostart ("Run on startup") launches without launcher policy
When "Run on startup" is enabled, the official app writes its own XDG
autostart entry pointing `Exec=` at the raw Electron binary (or, under
AppImage, at the ephemeral `/tmp/.mount_claude*` path, which breaks
entirely after the image unmounts). A login-time launch through that entry
bypasses every launcher policy — Wayland backend selection, GPU-crash
recovery, `--class`, `CLAUDE_PASSWORD_STORE`.
**Fix:** launch Claude Desktop manually once. The launcher rewrites the
autostart entry's `Exec=` to point at itself
(`/usr/bin/claude-desktop-unofficial`, or the AppImage path) on every
start (AUTO-1, `heal_autostart_entry` in
`scripts/launcher-common.sh`). The heal repeats per launch because the
app rewrites the entry each time the Settings toggle is switched on; the
toggle itself keeps working, since upstream's is-enabled check reads only
file existence, never the `Exec` content. Entries pointing at a
hand-rolled wrapper are left alone.
### Authentication Errors (401)
If you encounter recurring "API Error: 401" messages after periods of inactivity, the cached OAuth token may need to be cleared. This is an upstream application issue reported in [#156](https://github.com/aaddrick/claude-desktop-debian/issues/156).
To fix manually (credit: [MrEdwards007](https://github.com/MrEdwards007)):
1. Close Claude Desktop completely
2. Edit `~/.config/Claude/config.json`
3. Remove the line containing `"oauth:tokenCache"` (and any trailing comma if needed)
4. Save the file and restart Claude Desktop
5. Log in again when prompted
A scripted solution is also available at the bottom of [this comment](https://github.com/aaddrick/claude-desktop-debian/issues/156#issuecomment-2682547498).
### trying to overwrite '/usr/share/metainfo/io.github.aaddrick.claude-desktop-debian.metainfo.xml', which is also in package claude-desktop ([#769](https://github.com/aaddrick/claude-desktop-debian/issues/769))
`apt install` / `dpkg -i` fails with that `trying to overwrite`
message, or `dnf install` / `rpm -i` fails with `file
/usr/share/metainfo/io.github.aaddrick.claude-desktop-debian.metainfo.xml
... conflicts between attempted installs`.
The other package is a **pre-rename build of this project itself** —
never Anthropic's official `claude-desktop` package, which ships no
AppStream metainfo file at all and can never own that path. Before
this fix, releases at Claude ≥ `1.16000` (for example
`v2.0.22+claude1.18286.0`) hardcoded the installed metainfo filename
to the frozen AppStream ID instead of deriving it from the package
name, so it did not follow the `claude-desktop` →
`claude-desktop-unofficial` rename and stayed byte-shared between the
old and new package names.
A version at or above `1.16000` does **not** prove the conflicting
`claude-desktop` package is Anthropic's official build in this
specific case — that version-number heuristic does not apply here.
Instead, check which package actually owns the metainfo file:
```bash
dpkg -L claude-desktop | grep metainfo # rpm -ql claude-desktop on Fedora
```
If that lists
`.../io.github.aaddrick.claude-desktop-debian.metainfo.xml`, the
installed `claude-desktop` is this project's own pre-rename build and
is safe to remove:
```bash
sudo apt remove claude-desktop # sudo dnf remove claude-desktop
```
Then install `claude-desktop-unofficial` as usual. Releases built
after this fix ships no longer share this path with either package,
so the conflict cannot recur.
## Uninstallation
### For APT repository installations (Debian/Ubuntu)
```bash
# Remove package
sudo apt remove claude-desktop-unofficial
# Remove the repository and GPG key
sudo rm /etc/apt/sources.list.d/claude-desktop-unofficial.list
sudo rm /usr/share/keyrings/claude-desktop-unofficial.gpg
```
### For DNF repository installations (Fedora/RHEL)
```bash
# Remove package
sudo dnf remove claude-desktop-unofficial
# Remove the repository
sudo rm /etc/yum.repos.d/claude-desktop-unofficial.repo
```
### For legacy pre-rename installations (`claude-desktop` from this project)
Installs from before the rename to `claude-desktop-unofficial` used the
package name `claude-desktop` — the same name Anthropic's official
package uses. Check whose package you have before removing anything:
```bash
dpkg -s claude-desktop | grep '^Version:' # rpm -q claude-desktop on Fedora
```
A version below `1.16000` is this project's legacy package; remove it
with `sudo apt remove claude-desktop` (or `sudo dnf remove
claude-desktop`). A version of `1.17377.1` or higher is **Anthropic's
official package** — leave it alone unless you mean to uninstall the
official app too.
### For AUR installations (Arch Linux)
```bash
# Using yay
yay -R claude-desktop-appimage
# Or using paru
paru -R claude-desktop-appimage
# Or using pacman directly
sudo pacman -R claude-desktop-appimage
```
### For .deb packages (manual install)
```bash
# Remove package
sudo apt remove claude-desktop-unofficial
# Or: sudo dpkg -r claude-desktop-unofficial
# Remove package and configuration
sudo dpkg -P claude-desktop-unofficial
```
### For .rpm packages
```bash
# Remove package
sudo dnf remove claude-desktop-unofficial
# Or: sudo rpm -e claude-desktop-unofficial
```
### For AppImages
1. Delete the `.AppImage` file
2. Remove the `.desktop` file from `~/.local/share/applications/`
3. If using Gear Lever, use its uninstall option
### Remove user configuration (all formats)
```bash
rm -rf ~/.config/Claude
```