* fix: forward userSelectedFolders[0] as sharedCwdPath on cowork spawn (#412) The cowork-vm-service daemon already honors a `sharedCwdPath` field on the spawn IPC payload with priority over `cwd` (resolveWorkDir in scripts/cowork-vm-service.js:500), but the upstream Electron app never populates it on Linux backends. Every spawn arrives with only `cwd=/sessions/{name}`, so the daemon derives the host path from mountMap heuristics (PRs #389/#392/#411 cover the symptoms). Patch 12 threads the user-selected folder through three sites so the daemon receives the host path explicitly: 12a. At `this.getVMSpawnFunction({...})` config assembly, inject `sharedCwdPath: SESSION.userSelectedFolders?.[0]` alongside the existing mount config. 12b. At the Kyr() -> VMClient.spawn() call, forward `SESSION.sharedCwdPath` as a new 13th positional argument. 12c. In the spawn() method body, accept a new trailing parameter and set it on the IPC payload with a `VAR && (I.sharedCwdPath=VAR)` guard matching the existing setter chain. All three sub-patches detect prior application and no-op on re-run (idempotent). If any site fails to match on a future upstream, the daemon-side fallback from #392 keeps cwd resolution working — the daemon workarounds in #389/#392/#411 remain as safety nets. Verified against app.asar extracted from Claude-Setup-x64.exe for version 1.3109.0. All three edits apply, output parses cleanly, a second run is a no-op. Co-Authored-By: Claude <claude@anthropic.com> * refactor: simplify Patch 12 block Reduce Patch 12 (#412) by 25 lines without changing the patched output: - 12a: use extractBlock('{') directly on the getVMSpawnFunction argument and splice before its closing '}', removing the inverted backward walk over the parenthesised block. - 12a: replace the exec-until-null loop with matchAll + last element to read the session-var name. - 12c: replace the whole.replace().replace() + code.replace(whole) reassembly chain with an index-based splice using spawnMatch.index. - 12c: drop the unneeded .split('') on the letter bag and inline newArgList. - Trim the prologue comment to match the density of Patches 1-10. Patched index.js is byte-identical against the 1.3109.0 fixture and the three idempotency log lines still fire on re-run. Co-Authored-By: Claude <claude@anthropic.com> * fix: address aaddrick's review — robust 12a anchor, 12b uniqueness assertion Two fixes from PR #436 review: 1. **12a: drop fragile backscan, route through this.sessions.get().** The previous `VAR.userSelectedFolders` backscan returned 10 matches across 4 distinct vars (t, se, Ke, We) in the v1.3109.0 window — last-match landed on `t` by coincidence, and `We` in particular is a for-loop variable one upstream re-order away from becoming the new "last". Swap to the canonical accessor the class already uses: `this.sessions.get(sessionId)?.userSelectedFolders?.[0]`. The sessionId var is extracted from the config's first field `{sessionId:VAR` — scoped to the config block, 100% guaranteed present, immune to unrelated references leaking in. 2. **12b: matchAll + uniqueness assertion.** The previous code used `code.match()` which silently took the first hit if a second upstream call site ever appeared. Switch to `matchAll` with `length === 1` assertion; WARN-and-skip on anything else so a wrong-site forwarding becomes detectable instead of silent. 3. **Drop misleading ordering comment in 12c.** The "12c before 12b so property name is fixed" note was wrong — the property name is a hardcoded string literal in both sub-patches, so the ordering is cosmetic. Verified: dry-run still applies all three patches on 1.3109.0 source, output passes `node --check`, the three sharedCwdPath edits are byte-stable across runs (the non-idempotency in Patch 9 is pre-existing and orthogonal). Co-Authored-By: Claude <claude@anthropic.com> --------- Co-authored-by: Claude <claude@anthropic.com>
Claude Desktop for Linux
This project provides build scripts to run Claude Desktop natively on Linux systems. It repackages the official Windows application for Linux distributions, producing .deb packages (Debian/Ubuntu), .rpm packages (Fedora/RHEL), distribution-agnostic AppImages, an AUR package for Arch Linux, and a Nix flake for NixOS.
Note: This is an unofficial build script. For official support, please visit Anthropic's website. For issues with the build script or Linux implementation, please open an issue in this repository.
⚠️ EXPERIMENTAL: Cowork Mode Support Cowork mode is enabled by default in this build with a pluggable isolation backend:
Backend Isolation Requirements bubblewrap (default) Namespace sandbox bwrapinstalled and functionalhost (fallback) None — runs directly on host No additional requirements The best available backend is auto-detected at startup. Run
claude-desktop --doctorto check which backend will be used and which dependencies are missing.Note: The bubblewrap backend mounts your home directory as read-only (only the project working directory is writable). The host backend provides no isolation — use it only if you understand the security implications.
KVM status: The KVM/QEMU backend code exists but is non-functional — VM file downloads are disabled on Linux to prevent a checksum loop (#337). The backend code remains for potential future use.
Features
- Native Linux Support: Run Claude Desktop without virtualization or Wine
- MCP Support: Full Model Context Protocol integration
Configuration file location:
~/.config/Claude/claude_desktop_config.json - System Integration:
- Global hotkey support (Ctrl+Alt+Space) - works on X11 and Wayland (via XWayland)
- System tray integration
- Desktop environment integration
Screenshots
Installation
Using APT Repository (Debian/Ubuntu - Recommended)
Add the repository for automatic updates via apt:
# Add the GPG key
curl -fsSL https://aaddrick.github.io/claude-desktop-debian/KEY.gpg | sudo gpg --dearmor -o /usr/share/keyrings/claude-desktop.gpg
# Add the repository
echo "deb [signed-by=/usr/share/keyrings/claude-desktop.gpg arch=amd64,arm64] https://aaddrick.github.io/claude-desktop-debian stable main" | sudo tee /etc/apt/sources.list.d/claude-desktop.list
# Update and install
sudo apt update
sudo apt install claude-desktop
Future updates will be installed automatically with your regular system updates (sudo apt upgrade).
Using DNF Repository (Fedora/RHEL - Recommended)
Add the repository for automatic updates via dnf:
# Add the repository
sudo curl -fsSL https://aaddrick.github.io/claude-desktop-debian/rpm/claude-desktop.repo -o /etc/yum.repos.d/claude-desktop.repo
# Install
sudo dnf install claude-desktop
Future updates will be installed automatically with your regular system updates (sudo dnf upgrade).
Using AUR (Arch Linux)
The claude-desktop-appimage package is available on the AUR and is automatically updated with each release.
# Using yay
yay -S claude-desktop-appimage
# Or using paru
paru -S claude-desktop-appimage
The AUR package installs the AppImage build of Claude Desktop.
Using Nix Flake (NixOS)
Install directly from the flake:
# Basic install
nix profile install github:aaddrick/claude-desktop-debian
# With MCP server support (FHS environment)
nix profile install github:aaddrick/claude-desktop-debian#claude-desktop-fhs
Or add to your NixOS configuration:
# flake.nix
{
inputs.claude-desktop.url = "github:aaddrick/claude-desktop-debian";
outputs = { nixpkgs, claude-desktop, ... }: {
nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
modules = [
({ pkgs, ... }: {
nixpkgs.overlays = [ claude-desktop.overlays.default ];
environment.systemPackages = [ pkgs.claude-desktop ];
})
];
};
};
}
Using Pre-built Releases
Download the latest .deb, .rpm, or .AppImage from the Releases page.
Building from Source
See docs/BUILDING.md for detailed build instructions.
Configuration
Model Context Protocol settings are stored in:
~/.config/Claude/claude_desktop_config.json
For additional configuration options including environment variables and Wayland support, see docs/CONFIGURATION.md.
Troubleshooting
Run claude-desktop --doctor for built-in diagnostics that check common issues (display server, sandbox permissions, MCP config, stale locks, and more). It also reports cowork mode readiness — which isolation backend will be used, and which dependencies (KVM, QEMU, vsock, socat, virtiofsd, bubblewrap) are installed or missing.
For additional troubleshooting, uninstallation instructions, and log locations, see docs/TROUBLESHOOTING.md.
Acknowledgments
This project was inspired by k3d3's claude-desktop-linux-flake and their Reddit post about running Claude Desktop natively on Linux.
Special thanks to:
- k3d3
- Original NixOS implementation
- Native bindings insights
- emsi
- Title bar fix
- Alternative implementation approach
- leobuskin for the Playwright-based URL resolution approach
- yarikoptic
- Codespell support
- Shellcheck compliance
- IamGianluca for build dependency check improvements
- ing03201 for IBus/Fcitx5 input method support
- ajescudero for pinning @electron/asar for Node compatibility
- delorenj for Wayland compatibility support
- Regen-forest for suggesting Gear Lever as AppImageLauncher replacement
- niekvugteveen for fixing Debian packaging permissions
- speleoalex for native window decorations support
- imaginalnika for moving logs to
~/.cache/ - richardspicer for the menu bar visibility fix on Linux
- jacobfrantz1
- Claude Desktop code preview support
- Quick window submit fix
- janfrederik for the
--exeflag to use a local installer - MrEdwards007 for discovering the OAuth token cache fix
- lizthegrey for version update contributions
- mathys-lopinto
- AUR package
- Automated deployment
- pkuijpers for root cause analysis of the RPM repo GPG signing issue
- dlepold for identifying the tray icon variable name bug with a working fix
- Voork1144
- Detailed analysis of the tray icon minifier bug
- Root-cause analysis of the Chromium layout cache bug
- Direct child
setBounds()fix approach
- sabiut
--doctordiagnostic command- SHA-256 checksum validation for downloads
- Post-build integration tests for deb, rpm, and AppImage artifacts
- milog1994
- Popup detection
- Functional stubs
- Wayland compositor support
- jarrodcolburn
- Passwordless sudo support in container/CI environments
- Identifying the gh-pages 4GB bloat fix
- Identifying the virtiofsd PATH detection issue on Debian
- Detailed analysis of the CI release pipeline failure caused by runner kills during compare-releases
- Diagnosing the session-start hook sudo blocking issue with three solution approaches
- chukfinley for experimental Cowork mode support on Linux
- CyPack for orphaned cowork daemon cleanup on startup
- IliyaBrook for fixing the platform patch for Claude Desktop >= 1.1.3541 arm64 refactor
- MichaelMKenny
- Diagnosing the
$-prefixed electron variable bug - Root cause analysis and workaround
- Diagnosing the
- daa25209 for detailed root cause analysis of the cowork platform gate crash and patch script
- noctuum
CLAUDE_MENU_BARenv var with configurable menu bar visibility- Boolean alias support
- typedrat
- NixOS flake integration with build.sh
- node-pty derivation
- CI auto-update
- Fixing the flake package scoping regression
- cbonnissent
- Reverse-engineering the Cowork VM guest RPC protocol
- Fixing the KVM startup blocker
- Fixing RPC response id echoing for persistent connections
- Configurable bwrap mount points via a dedicated Linux config file
- joekale-pp for adding
--doctorsupport to the RPM launcher - ecrevisseMiroir for the bwrap backend sandbox isolation with tmpfs-based minimal root
- arauhala for detailed root cause analysis of the NixOS
isPackagedregression - cromagnone for confirming the VM download loop on bwrap installs with detailed logs that disproved the initial triage
- aHk-coder for diagnosing the hardcoded minified variable crash in the cowork smol-bin patch
- RayCharlizard
- Detailed analysis of the self-referential
.mcpb-cachesymlink ELOOP bug - Fixing auto-memory path translation on HostBackend
- Detailed analysis of the self-referential
- reinthal for fixing the NixOS build breakage caused by the nixpkgs
nodePackagesremoval - gianluca-peri
- Reporting the GNOME quit accessibility issue
- Confirming tray behavior with AppIndicator
- martin152 for detailed diagnosis and a complete patch for three launcher cleanup bugs:
cleanup_orphaned_cowork_daemonself-match,cleanup_stale_cowork_socketsocat dependency no-op, and the same self-match in--doctor - hfyeh for diagnosing the Ubuntu 24.04 AppArmor unprivileged-userns block on Cowork bwrap and contributing the AppArmor profile workaround
Sponsorship
If this project is useful to you, consider sponsoring on GitHub.
License
The build scripts in this repository are dual-licensed under:
- MIT License (see LICENSE-MIT)
- Apache License 2.0 (see LICENSE-APACHE)
The Claude Desktop application itself is subject to Anthropic's Consumer Terms.
Contributing
Contributions are welcome! By submitting a contribution, you agree to license it under the same dual-license terms as this project.

