Files
wehub-resource-sync 3e076d4dd9
CI / Mirror Official .deb to Release (push) Blocked by required conditions
CI / Update APT Repository (push) Blocked by required conditions
CI / Update DNF Repository (push) Blocked by required conditions
CI / Update AUR Package (push) Blocked by required conditions
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 / Create Release (push) Waiting to run
chore: import upstream snapshot with attribution
2026-07-13 12:29:21 +08:00

12 KiB

< Back to README

Configuration

The launcher reads a small set of opt-in CLAUDE_* environment variables; everything else — window frame, menu bar, close-to-tray, hardware acceleration — is a native setting in the official app.

Variable Default Description
CLAUDE_USE_WAYLAND unset (auto) Force the display backend on Wayland: 1 = native Wayland, 0 = XWayland. Unset auto-detects per compositor (only Niri defaults to native Wayland). See Wayland Support.
CLAUDE_DISABLE_GPU unset (auto) 1 = disable hardware acceleration (--disable-gpu --disable-software-rasterizer). 0 = suppress the sticky auto-recovery after a GPU-process crash. Unset = auto-apply the flags when the previous launch died with the GPU FATAL signature. See GPU.
CLAUDE_PASSWORD_STORE unset Explicit escape hatch: when set, the value is passed verbatim as Chromium's --password-store=. When unset, the official build's os_crypt autodetection owns the decision. See Password store.
CLAUDE_GTK_IM_MODULE unset Propagated to GTK_IM_MODULE for Electron at startup; opt-in override for broken IBus/GTK input-method integration. See Input method.

Since the v3.0.0 rebase onto the official Linux build, launcher policy is opt-in only: no default flag shadows an official code path. Several 2.x variables are therefore gone — see Removed in v3.0.0.

MCP Configuration

Model Context Protocol settings are stored in:

~/.config/Claude/claude_desktop_config.json

Quit Claude Desktop before hand-editing this file, then reopen it. The app rewrites the config on its own schedule while running, so edits made while it is open are clobbered on its next config write. mcpServers entries that were present at startup are loaded and survive restarts — the loss window is only hand-edits made against a running app.

Run claude-desktop-unofficial --doctor to validate the JSON and see how many MCP servers are configured.

Wayland Support

On Wayland sessions the launcher picks a display backend per compositor:

Compositor Backend Why
Niri native Wayland (auto) no XWayland support at all
Everything else (GNOME, KDE, Sway, Hyprland, COSMIC, …) XWayland (auto) XWayland global key grabs still work on most; mature path, broadest compatibility

By default only Niri is auto-selected for native Wayland. GNOME Wayland stays on XWayland by default even though mutter no longer honours XWayland global key grabs (#404) — flipping the default GNOME session off XWayland is a rendering/IME/HiDPI risk, so it's left opt-in for now.

To route Quick Entry's global shortcut (Ctrl+Alt+Space) through the XDG GlobalShortcuts portal on GNOME, opt into native Wayland with CLAUDE_USE_WAYLAND=1. On GNOME ≤ 49 this works after a one-time portal permission dialog (accept it to bind the shortcut). On GNOME 50 / xdg-desktop-portal ≥ 1.20 it does not work yet: the newer portal requires apps to declare identity via org.freedesktop.host.portal.Registry.Register, which Electron/Chromium doesn't do, so globalShortcut.register() fails and the shortcut stays focus-bound. Tracked upstream at electron/electron#51875.

Override the auto-detection with CLAUDE_USE_WAYLAND:

# Force native Wayland (GNOME portal route, or Sway/Hyprland)
CLAUDE_USE_WAYLAND=1 claude-desktop-unofficial

# Force XWayland (e.g. to override Niri's auto-native, or if native
# Wayland regresses rendering)
CLAUDE_USE_WAYLAND=0 claude-desktop-unofficial

# Or persist either choice
export CLAUDE_USE_WAYLAND=1

Note: portal-routed global shortcuts only work where the compositor's portal backend implements org.freedesktop.portal.GlobalShortcuts. Support is per-compositor and currently uneven — GNOME and KDE implement it (though the app-id requirement above — enforced for GlobalShortcuts since xdg-desktop-portal 1.21 — applies to all desktops, KDE included); wlroots compositors (Sway, Hyprland, Niri) and COSMIC currently ship no GlobalShortcuts backend, so the portal route is a no-op there until their portal gains one.

GPU (CLAUDE_DISABLE_GPU)

CLAUDE_DISABLE_GPU=1 makes the launcher pass --disable-gpu --disable-software-rasterizer to the official binary — the same workaround as the in-app Settings hardware-acceleration toggle, persisted via the environment instead. When the variable is unset and the previous launch died with Chromium's GPU-process FATAL signature (#583), the launcher auto-applies the same flags and keeps them applied on subsequent launches (sticky recovery). Set CLAUDE_DISABLE_GPU=0 to suppress the auto-fallback when retesting hardware acceleration after a driver fix. The flags are also applied automatically inside XRDP sessions. See troubleshooting.md for the full workflow.

Password store (CLAUDE_PASSWORD_STORE)

By default the launcher passes no --password-store flag: the official build's os_crypt autodetection owns the keyring decision (it deliberately declines weak persistence on some sessions rather than storing tokens unsafely). CLAUDE_PASSWORD_STORE is the documented escape hatch — when set, its value is passed verbatim as --password-store=<value> and overrides the autodetect:

CLAUDE_PASSWORD_STORE=gnome-libsecret claude-desktop-unofficial

The doctor reports which mode is in effect (Password store: upstream os_crypt autodetect (default) or forced to <value>).

Input method (CLAUDE_GTK_IM_MODULE)

CLAUDE_GTK_IM_MODULE is propagated to GTK_IM_MODULE for Electron at startup, so a different GTK input module (e.g. xim) can be persisted without wrapping every launch. See troubleshooting.md for symptoms and trade-offs.

Cowork

By default the official Linux client runs Cowork as a helper daemon driving QEMU/KVM. For hosts that can't do KVM (see the bubblewrap fallback below), an opt-in flag routes Cowork through a lighter sandbox instead. The full stack the default KVM path needs on the host:

Component Requirement Doctor check
KVM /dev/kvm present and read-write (sudo usermod -aG kvm $USER if not) _check_kvm
vsock /dev/vhost-vsock present (sudo modprobe vhost_vsock) _check_vhost_vsock
QEMU qemu-system-x86_64 (or qemu-system-aarch64 on arm64) on PATH _check_cowork_stack
Firmware OVMF at one of the hardcoded probe paths: /usr/share/OVMF/OVMF_CODE_4M.fd or /usr/share/OVMF/OVMF_CODE.fd (arm64: /usr/share/AAVMF/AAVMF_CODE.fd). No env override exists — firmware installed at Fedora/Arch edk2 locations is not found without a compat symlink. Our RPM package's %post creates that symlink automatically (CW-1). _check_cowork_stack
virtiofsd On PATH or at a well-known off-PATH location (/usr/libexec/virtiofsd, /usr/lib/qemu/virtiofsd, /usr/lib/virtiofsd) _check_cowork_stack

Run claude-desktop-unofficial --doctor — the Cowork Mode section reports each component with a distro-specific install hint and a one-line readiness summary. A missing stack never fails the doctor; the app works fine without Cowork.

Bubblewrap fallback (COWORK_VM_BACKEND=bwrap)

Some hosts can never satisfy the KVM stack no matter what's installed. The clearest case is ChromeOS Crostini: its Termina kernel blocks vhost_vsock at the namespace level, so /dev/vhost-vsock is absent with no flag or modprobe to bring it back (#772). On those hosts the KVM Cowork backend is a dead end.

Setting COWORK_VM_BACKEND=bwrap opts into a bubblewrap-sandboxed backend that runs Claude Code directly on the host inside a namespace sandbox, with no VM:

COWORK_VM_BACKEND=bwrap claude-desktop-unofficial

To make it persistent — including for launches from the desktop/app menu, which can't carry a per-command environment — put the flag in the launcher config file instead:

# ~/.config/claude-desktop-debian/environment
COWORK_VM_BACKEND=bwrap

The launcher reads KEY=value lines from ${XDG_CONFIG_HOME:-~/.config}/claude-desktop-debian/environment at startup. Only a fixed allowlist of launcher variables is honored — COWORK_VM_BACKEND, COWORK_NODE_PATH, CLAUDE_USE_WAYLAND, CLAUDE_PASSWORD_STORE, CLAUDE_GTK_IM_MODULE, CLAUDE_DISABLE_GPU — and only when the variable isn't already set, so an explicit VAR=… claude-desktop-unofficial on the command line still wins. The file is never executed as shell. --doctor reads it too, so diagnostics always match what a launch would see.

How it works: an asar patch (patch_cowork_bwrap) short-circuits the KVM support gate and swaps the native VM helper for a bundled Node daemon (resources/cowork-vm-service.js) that speaks the same socket protocol as the official helper but backs it with bwrap instead of QEMU. Every branch of the patch is gated on this exact flag, so on an unflagged launch every branch evaluates false and the official KVM path runs unchanged — nothing changes for the KVM majority.

Requirements when flagged:

Component Requirement Doctor check
Node.js A system node (or nodejs) on PATH providing fs.statfsSync (Node >= 18.15 / 16.19) — the bundled Electron binary ships with the RunAsNode fuse off and can't run the daemon itself. Override with COWORK_NODE_PATH. _doctor_check_bwrap_node
bubblewrap bwrap installed, with unprivileged user namespaces allowed (Ubuntu 24.04+ blocks them via AppArmor — see troubleshooting.md) _doctor_check_bwrap_fallback

Run claude-desktop-unofficial --doctor with the flag set to see the bwrap-path diagnostics. Isolation is namespace-level, not a VM — weaker than the KVM default, which is the trade for running where KVM can't. Any COWORK_VM_BACKEND value other than bwrap is a 2.x knob the official client ignores.

Removed in v3.0.0

The v3.0.0 rebase deleted the patches that read these variables. The doctor's legacy-environment check warns when any of them is still set:

2.x variable What replaces it
CLAUDE_QUIT_ON_CLOSE Native setting: Settings > General > System Tray (on = close to tray, off = quit).
CLAUDE_MENU_BAR Native app setting; the official build keeps the menu bar on by default (the build's MB-1 tripwire watches for an upstream flip).
CLAUDE_TITLEBAR_STYLE Nothing — the official build owns its window frame; the topbar shim is gone.
CLAUDE_KEEP_AWAKE Nothing — the patch that read it was deleted with the Windows pipeline.
COWORK_VM_BACKEND Still read, but only for the value bwrap, which opts into the bubblewrap fallback above. Other values are ignored.

Application Logs

Runtime logs are available at:

~/.cache/claude-desktop-debian/launcher.log

Each launch also logs an env={...} block with the session and CLAUDE_* variables that drove the display and input decisions, so bug reports carry the context.