2025-08-04 19:13:40 -04:00
# Claude Desktop for Linux
2025-04-05 20:15:38 -04:00
2026-02-26 18:48:52 -08:00
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 ](https://aur.archlinux.org/packages/claude-desktop-appimage ) for Arch Linux, and a Nix flake for NixOS.
2025-04-05 20:15:38 -04:00
2025-08-04 19:18:59 -04:00
**Note:** This is an unofficial build script. For official support, please visit [Anthropic's website ](https://www.anthropic.com ). For issues with the build script or Linux implementation, please [open an issue ](https://github.com/aaddrick/claude-desktop-debian/issues ) in this repository.
2025-04-05 20:15:38 -04:00
2026-02-16 14:16:44 -05:00
---
> **⚠️ EXPERIMENTAL: Cowork Mode Support**
feat: KVM/bwrap isolation backends for cowork mode (#269)
* feat: add KVM/bwrap isolation backends for cowork mode
Refactor cowork-vm-service.js from monolithic VMManager into a pluggable
backend architecture with three isolation levels:
- HostBackend: direct execution on host (existing Phase 1 behavior)
- BwrapBackend: bubblewrap namespace sandbox (PID/mount isolation)
- KvmBackend: full QEMU/KVM VM with vsock, virtiofs, QMP monitor
Backend auto-detected at startup (KVM > bwrap > host) or overridden
via COWORK_VM_BACKEND env var. Shared helpers extracted for env
filtering, arg cleanup, command resolution, and work dir handling.
Also:
- Add Cowork Mode section to --doctor diagnostics with per-tool
checks and distro-specific install hints
- Update Patch 4 to extract real win32 file entries for linux
bundle manifest (enables app download infrastructure)
- Update handover documentation for Phase 2/3 architecture
Co-Authored-By: Claude <claude@anthropic.com>
* fix: correct KvmBackend vsock port, direction, and kernel cmdline
The guest sdk-daemon connects TO the host (CID=2), not the other way
around. Confirmed via disassembly of the guest binary: the vsock port
is 51234 (0xC822), matching the Hyper-V GUID in the Windows service.
- Change VSOCK_GUEST_PORT from 2222 to 51234
- Reverse socat bridge: VSOCK-LISTEN (host listens) instead of
VSOCK-CONNECT (host connecting to guest)
- Add bridge server to accept persistent guest connection and route
events/responses via callback map
- Fix kernel cmdline: root=LABEL=cloudimg-rootfs (matches fstab)
Co-Authored-By: Claude <claude@anthropic.com>
* fix: patch VM download to use disk-backed temp dir on Linux
Linux systems often mount /tmp as a small tmpfs (3-4GB). The VM
rootfs download decompresses to ~9GB, causing ENOSPC. Patch the
app's mkdtemp("wvm-") call to use the bundle directory (on real
disk) instead of os.tmpdir() on Linux.
Uses regex-based dynamic variable extraction to remain
version-agnostic across minified code changes.
Co-Authored-By: Claude <claude@anthropic.com>
* fix: handle stale cowork socket (ECONNREFUSED) on Linux
Stale sockets from previous sessions give ECONNREFUSED instead of
ENOENT, bypassing the retry loop and auto-launch entirely. Fix:
- Expand ENOENT check in retry loop to include ECONNREFUSED on Linux
- Add cleanup_stale_cowork_socket() to launcher scripts (all formats)
that removes dead sockets before Electron starts
- Increase tmpdir patch search window from 1000 to 2000 chars
Co-Authored-By: Claude <claude@anthropic.com>
* fix: preserve DNS resolution inside bwrap sandbox
On systems using systemd-resolved, /etc/resolv.conf is a symlink to
/run/systemd/resolve/stub-resolv.conf. The bwrap --tmpfs /run option
wiped this out, breaking DNS resolution inside the sandbox and
preventing the spawned Claude process from reaching the API.
Bind-mount the resolved /run/systemd/resolve/ directory back into
the sandbox as read-only to restore DNS.
Co-Authored-By: Claude <claude@anthropic.com>
* fix: harden cowork isolation and build patches
- Remove broken _setupEventForwarding (events already flow through
_handleGuestData); the second bridge connection was silently ignored
- Mount $HOME read-only in bwrap sandbox; only workDir and explicit
mounts are writable (prevents writes to ~/.ssh, ~/.gnupg, etc.)
- Scope Patch 4 win32 extraction to actual win32:{} block via brace
counting to avoid crossing into darwin/linux sections
- Set _qmpAvailable flag on QMP timeout instead of silently continuing
- Wrap CID allocation at 65535 to prevent unbounded growth
- Use execFileSync instead of execSync('which ...') in detectBackend
- Coerce response ID to String for Map lookup in _handleGuestData
- Use non-greedy [\s\S]*? in Patch 6 regex for nested brace robustness
- Update patch count threshold from 4 to 5 after adding Patch 8
- Add age-based fallback for stale socket cleanup when socat is missing
- Use indexOf-based splice in Patch 8 instead of string.replace()
- Extract shared resolveSdkBinary helper to deduplicate SDK resolution
- Remove dead retryFuncRe/retryFuncMatch variables from Patch 6
Co-Authored-By: Claude <claude@anthropic.com>
* fix: address security and correctness issues from code review
- Replace execSync string interpolation with execFileSync for qemu-img
calls to eliminate shell injection risk
- Add path validation to readFile in both LocalBackend and KvmBackend
to restrict reads to within the user's home directory
- Fix QMP _sendQmpCommand timer leak by clearing timeout on success
- Fix _pendingCallbacks.delete() to use String(msg.id) matching the
String(msg.id) used in the .get() lookup
- Extract FORWARDED_EVENTS constant, cleanup helper, extractBlock
helper, and consolidate doctor tool checks (from simplifier pass)
Co-Authored-By: Claude <claude@anthropic.com>
* docs: update README cowork notice with isolation backends and doctor info
Co-Authored-By: Claude <claude@anthropic.com>
---------
Co-authored-by: Claude <claude@anthropic.com>
2026-02-28 21:13:09 -05:00
> Cowork mode is **enabled by default** in this build. It uses Anthropic's native VM images with a pluggable isolation backend:
>
> | Backend | Isolation | Requirements |
> |---------|-----------|-------------|
> | **KVM** (preferred) | Full VM via QEMU/KVM | `/dev/kvm`, `qemu-system-x86_64`, `/dev/vhost-vsock`, `socat`, `virtiofsd` |
> | **bubblewrap** (fallback) | Namespace sandbox | `bwrap` installed and functional |
> | **host** (last resort) | None — runs directly on host | No additional requirements |
>
> The best available backend is auto-detected at startup. Run `claude-desktop --doctor` to 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.
2026-02-16 14:16:44 -05:00
---
2025-08-04 19:13:40 -04:00
## Features
2025-04-05 20:15:38 -04:00
2025-08-04 19:13:40 -04:00
- **Native Linux Support**: Run Claude Desktop without virtualization or Wine
2026-01-05 19:54:43 -05:00
- **MCP Support**: Full Model Context Protocol integration
2025-08-04 19:13:40 -04:00
Configuration file location: `~/.config/Claude/claude_desktop_config.json`
2026-01-05 19:54:43 -05:00
- **System Integration**:
- Global hotkey support (Ctrl+Alt+Space) - works on X11 and Wayland (via XWayland)
2025-08-04 19:13:40 -04:00
- System tray integration
- Desktop environment integration
2025-04-03 01:27:06 -04:00
2025-08-04 19:13:40 -04:00
### Screenshots
2024-12-26 11:08:01 -05:00
2026-02-16 19:47:44 -05:00
<p align="center">
<img src="https://raw.githubusercontent.com/aaddrick/claude-desktop-debian/main/docs/images/claude-desktop-screenshot1.png" alt="Claude Desktop running on Linux" />
</p>
2024-12-26 11:08:01 -05:00
2026-02-16 19:47:44 -05:00
<p align="center">
<img src="https://raw.githubusercontent.com/aaddrick/claude-desktop-debian/main/docs/images/claude-desktop-screenshot2.png" alt="Global hotkey popup" />
</p>
2024-12-26 11:08:01 -05:00
2025-08-04 19:13:40 -04:00
## Installation
2025-01-17 11:17:57 +01:00
2026-01-24 11:06:05 -05:00
### Using APT Repository (Debian/Ubuntu - Recommended)
2026-01-24 08:53:57 -05:00
Add the repository for automatic updates via `apt` :
```bash
# 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` ).
2026-01-24 11:06:05 -05:00
### Using DNF Repository (Fedora/RHEL - Recommended)
Add the repository for automatic updates via `dnf` :
```bash
# 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` ).
2026-02-08 14:33:18 -05:00
### Using AUR (Arch Linux)
The [`claude-desktop-appimage` ](https://aur.archlinux.org/packages/claude-desktop-appimage ) package is available on the AUR and is automatically updated with each release.
```bash
# 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.
2026-02-26 18:48:52 -08:00
### Using Nix Flake (NixOS)
Install directly from the flake:
```bash
# 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:
```nix
# 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 ];
})
];
};
};
}
```
2025-08-04 19:13:40 -04:00
### Using Pre-built Releases
2025-01-17 11:17:57 +01:00
2026-01-24 10:59:53 -05:00
Download the latest `.deb` , `.rpm` , or `.AppImage` from the [Releases page ](https://github.com/aaddrick/claude-desktop-debian/releases ).
2024-12-26 11:08:01 -05:00
2025-08-04 19:13:40 -04:00
### Building from Source
2024-12-26 11:08:01 -05:00
2026-02-16 19:45:40 -05:00
See [docs/BUILDING.md ](docs/BUILDING.md ) for detailed build instructions.
2025-04-03 01:27:06 -04:00
2025-08-04 19:13:40 -04:00
## Configuration
2025-04-03 01:27:06 -04:00
2025-08-04 19:13:40 -04:00
Model Context Protocol settings are stored in:
```
~/.config/Claude/claude_desktop_config.json
```
2024-12-26 11:08:01 -05:00
2026-02-16 19:45:40 -05:00
For additional configuration options including environment variables and Wayland support, see [docs/CONFIGURATION.md ](docs/CONFIGURATION.md ).
2025-03-29 02:31:42 -04:00
2025-08-04 19:13:40 -04:00
## Troubleshooting
feat: KVM/bwrap isolation backends for cowork mode (#269)
* feat: add KVM/bwrap isolation backends for cowork mode
Refactor cowork-vm-service.js from monolithic VMManager into a pluggable
backend architecture with three isolation levels:
- HostBackend: direct execution on host (existing Phase 1 behavior)
- BwrapBackend: bubblewrap namespace sandbox (PID/mount isolation)
- KvmBackend: full QEMU/KVM VM with vsock, virtiofs, QMP monitor
Backend auto-detected at startup (KVM > bwrap > host) or overridden
via COWORK_VM_BACKEND env var. Shared helpers extracted for env
filtering, arg cleanup, command resolution, and work dir handling.
Also:
- Add Cowork Mode section to --doctor diagnostics with per-tool
checks and distro-specific install hints
- Update Patch 4 to extract real win32 file entries for linux
bundle manifest (enables app download infrastructure)
- Update handover documentation for Phase 2/3 architecture
Co-Authored-By: Claude <claude@anthropic.com>
* fix: correct KvmBackend vsock port, direction, and kernel cmdline
The guest sdk-daemon connects TO the host (CID=2), not the other way
around. Confirmed via disassembly of the guest binary: the vsock port
is 51234 (0xC822), matching the Hyper-V GUID in the Windows service.
- Change VSOCK_GUEST_PORT from 2222 to 51234
- Reverse socat bridge: VSOCK-LISTEN (host listens) instead of
VSOCK-CONNECT (host connecting to guest)
- Add bridge server to accept persistent guest connection and route
events/responses via callback map
- Fix kernel cmdline: root=LABEL=cloudimg-rootfs (matches fstab)
Co-Authored-By: Claude <claude@anthropic.com>
* fix: patch VM download to use disk-backed temp dir on Linux
Linux systems often mount /tmp as a small tmpfs (3-4GB). The VM
rootfs download decompresses to ~9GB, causing ENOSPC. Patch the
app's mkdtemp("wvm-") call to use the bundle directory (on real
disk) instead of os.tmpdir() on Linux.
Uses regex-based dynamic variable extraction to remain
version-agnostic across minified code changes.
Co-Authored-By: Claude <claude@anthropic.com>
* fix: handle stale cowork socket (ECONNREFUSED) on Linux
Stale sockets from previous sessions give ECONNREFUSED instead of
ENOENT, bypassing the retry loop and auto-launch entirely. Fix:
- Expand ENOENT check in retry loop to include ECONNREFUSED on Linux
- Add cleanup_stale_cowork_socket() to launcher scripts (all formats)
that removes dead sockets before Electron starts
- Increase tmpdir patch search window from 1000 to 2000 chars
Co-Authored-By: Claude <claude@anthropic.com>
* fix: preserve DNS resolution inside bwrap sandbox
On systems using systemd-resolved, /etc/resolv.conf is a symlink to
/run/systemd/resolve/stub-resolv.conf. The bwrap --tmpfs /run option
wiped this out, breaking DNS resolution inside the sandbox and
preventing the spawned Claude process from reaching the API.
Bind-mount the resolved /run/systemd/resolve/ directory back into
the sandbox as read-only to restore DNS.
Co-Authored-By: Claude <claude@anthropic.com>
* fix: harden cowork isolation and build patches
- Remove broken _setupEventForwarding (events already flow through
_handleGuestData); the second bridge connection was silently ignored
- Mount $HOME read-only in bwrap sandbox; only workDir and explicit
mounts are writable (prevents writes to ~/.ssh, ~/.gnupg, etc.)
- Scope Patch 4 win32 extraction to actual win32:{} block via brace
counting to avoid crossing into darwin/linux sections
- Set _qmpAvailable flag on QMP timeout instead of silently continuing
- Wrap CID allocation at 65535 to prevent unbounded growth
- Use execFileSync instead of execSync('which ...') in detectBackend
- Coerce response ID to String for Map lookup in _handleGuestData
- Use non-greedy [\s\S]*? in Patch 6 regex for nested brace robustness
- Update patch count threshold from 4 to 5 after adding Patch 8
- Add age-based fallback for stale socket cleanup when socat is missing
- Use indexOf-based splice in Patch 8 instead of string.replace()
- Extract shared resolveSdkBinary helper to deduplicate SDK resolution
- Remove dead retryFuncRe/retryFuncMatch variables from Patch 6
Co-Authored-By: Claude <claude@anthropic.com>
* fix: address security and correctness issues from code review
- Replace execSync string interpolation with execFileSync for qemu-img
calls to eliminate shell injection risk
- Add path validation to readFile in both LocalBackend and KvmBackend
to restrict reads to within the user's home directory
- Fix QMP _sendQmpCommand timer leak by clearing timeout on success
- Fix _pendingCallbacks.delete() to use String(msg.id) matching the
String(msg.id) used in the .get() lookup
- Extract FORWARDED_EVENTS constant, cleanup helper, extractBlock
helper, and consolidate doctor tool checks (from simplifier pass)
Co-Authored-By: Claude <claude@anthropic.com>
* docs: update README cowork notice with isolation backends and doctor info
Co-Authored-By: Claude <claude@anthropic.com>
---------
Co-authored-by: Claude <claude@anthropic.com>
2026-02-28 21:13:09 -05:00
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.
2026-02-28 15:47:37 -05:00
For additional troubleshooting, uninstallation instructions, and log locations, see [docs/TROUBLESHOOTING.md ](docs/TROUBLESHOOTING.md ).
2025-04-03 01:27:06 -04:00
2025-08-04 19:13:40 -04:00
## Acknowledgments
2025-04-03 01:27:06 -04:00
2025-08-04 19:13:40 -04:00
This project was inspired by [k3d3's claude-desktop-linux-flake ](https://github.com/k3d3/claude-desktop-linux-flake ) and their [Reddit post ](https://www.reddit.com/r/ClaudeAI/comments/1hgsmpq/i_successfully_ran_claude_desktop_natively_on/ ) about running Claude Desktop natively on Linux.
2025-04-03 01:27:06 -04:00
2025-08-04 19:13:40 -04:00
Special thanks to:
- **k3d3** for the original NixOS implementation and native bindings insights
- **[emsi ](https://github.com/emsi/claude-desktop )** for the title bar fix and alternative implementation approach
2026-01-05 17:35:53 -05:00
- **[leobuskin ](https://github.com/leobuskin/unofficial-claude-desktop-linux )** for the Playwright-based URL resolution approach
2026-02-08 14:33:18 -05:00
- **[yarikoptic ](https://github.com/yarikoptic )** for codespell support and shellcheck compliance
- **[IamGianluca ](https://github.com/IamGianluca )** for build dependency check improvements
- **[ing03201 ](https://github.com/ing03201 )** for IBus/Fcitx5 input method support
- **[ajescudero ](https://github.com/ajescudero )** for pinning @electron/asar for Node compatibility
- **[delorenj ](https://github.com/delorenj )** for Wayland compatibility support
- **[Regen-forest ](https://github.com/Regen-forest )** for suggesting Gear Lever as AppImageLauncher replacement
- **[niekvugteveen ](https://github.com/niekvugteveen )** for fixing Debian packaging permissions
- **[speleoalex ](https://github.com/speleoalex )** for native window decorations support
- **[imaginalnika ](https://github.com/imaginalnika )** for moving logs to `~/.cache/`
- **[richardspicer ](https://github.com/richardspicer )** for the menu bar visibility fix on Linux
- **[jacobfrantz1 ](https://github.com/jacobfrantz1 )** for Claude Desktop code preview support and quick window submit fix
- **[janfrederik ](https://github.com/janfrederik )** for the `--exe` flag to use a local installer
- **[MrEdwards007 ](https://github.com/MrEdwards007 )** for discovering the OAuth token cache fix
- **[lizthegrey ](https://github.com/lizthegrey )** for version update contributions
- **[mathys-lopinto ](https://github.com/mathys-lopinto )** for the AUR package and automated deployment
- **[pkuijpers ](https://github.com/pkuijpers )** for root cause analysis of the RPM repo GPG signing issue
- **[dlepold ](https://github.com/dlepold )** for identifying the tray icon variable name bug with a working fix
2026-02-19 13:29:48 -05:00
- **[Voork1144 ](https://github.com/Voork1144 )** for detailed analysis of the tray icon minifier bug, root-cause analysis of the Chromium layout cache bug, and the direct child `setBounds()` fix approach
2026-02-28 15:46:10 -05:00
- **[sabiut ](https://github.com/sabiut )** for the `--doctor` diagnostic command
2026-02-16 13:56:29 -05:00
- **[milog1994 ](https://github.com/milog1994 )** for Linux UX improvements including popup detection, functional stubs, and Wayland compositor support
2026-02-16 14:00:51 -05:00
- **[jarrodcolburn ](https://github.com/jarrodcolburn )** for passwordless sudo support in container/CI environments
2026-02-16 14:09:43 -05:00
- **[chukfinley ](https://github.com/chukfinley )** for experimental Cowork mode support on Linux
2026-02-19 13:47:49 -05:00
- **[IliyaBrook ](https://github.com/IliyaBrook )** for fixing the platform patch for Claude Desktop >= 1.1.3541 arm64 refactor
2026-02-24 01:30:47 -05:00
- **[MichaelMKenny ](https://github.com/MichaelMKenny )** for diagnosing the `$` -prefixed electron variable bug with root cause analysis and workaround
2026-02-25 06:16:05 -05:00
- **[daa25209 ](https://github.com/daa25209 )** for detailed root cause analysis of the cowork platform gate crash and patch script
2026-03-19 07:43:20 -04:00
- **[noctuum ](https://github.com/noctuum )** for the `CLAUDE_MENU_BAR` env var with configurable menu bar visibility and boolean alias support
2026-02-28 21:30:28 -05:00
- **[typedrat ](https://github.com/typedrat )** for the NixOS flake integration with build.sh, node-pty derivation, and CI auto-update
2026-03-19 07:07:02 -04:00
- **[cbonnissent ](https://github.com/cbonnissent )** for reverse-engineering the Cowork VM guest RPC protocol and fixing the KVM startup blocker
2024-12-26 11:08:01 -05:00
2026-02-24 00:44:48 -05:00
## Sponsorship
2026-02-24 00:48:53 -05:00
Anthropic doesn't publish release notes for Claude Desktop. Each release here includes AI-generated notes that analyze code changes between versions. I wrote up how that process works if you're curious: [Generating Real Release Notes from Minified Electron Apps ](https://nonconvexlabs.com/blog/generating-real-release-notes-from-minified-electron-apps ).
2026-02-24 00:44:48 -05:00
2026-02-24 00:48:53 -05:00
The analysis runs against Claude's API. Costs vary a lot depending on how big the update is. Recent releases have run between * * $3.36 and $76.16 per release**.
If this project is useful to you, consider [sponsoring on GitHub ](https://github.com/sponsors/aaddrick ) to help cover those costs.
2026-02-24 00:44:48 -05:00
2025-08-04 19:13:40 -04:00
## License
2024-12-26 11:08:01 -05:00
2025-08-04 19:13:40 -04:00
The build scripts in this repository are dual-licensed under:
- MIT License (see [LICENSE-MIT ](LICENSE-MIT ))
- Apache License 2.0 (see [LICENSE-APACHE ](LICENSE-APACHE ))
2024-12-26 11:08:01 -05:00
2025-08-04 19:13:40 -04:00
The Claude Desktop application itself is subject to [Anthropic's Consumer Terms ](https://www.anthropic.com/legal/consumer-terms ).
2024-12-26 11:08:01 -05:00
2025-08-04 19:13:40 -04:00
## Contributing
2024-12-26 11:08:01 -05:00
2025-08-09 21:58:44 -04:00
Contributions are welcome! By submitting a contribution, you agree to license it under the same dual-license terms as this project.