RayCharlizard 37379b45ac fix: resolve working directory from primary mount on HostBackend (#392)
* fix: resolve working directory from primary mount on HostBackend

The Electron app sends `cwd=/sessions/{name}` (a session-root guest
path) for every Cowork session. `resolveWorkDir()` attempts to
translate this via `translateGuestPath()`, but that function's regex
requires `/sessions/{name}/mnt/{mount}/...` — the session root has no
`/mnt/` component, so translation always fails and CWD falls back to
`os.homedir()`.

BwrapBackend avoids this because it overrides `spawn()` and derives CWD
from the primary user mount (first non-dotfile, non-uploads key in
`mountMap`). HostBackend goes through `resolveWorkDir()` which lacked
this fallback.

Add the same primary-mount derivation to `resolveWorkDir()`: when the
CWD is a session-root guest path that `translateGuestPath()` cannot
resolve, find the primary user mount from `mountMap` and use its host
path. Falls back to homedir only when no user mount exists.

Verified with a Node.js test harness simulating the exact spawn
parameters from live session logs — the fix produces the correct
project directory while all edge cases (no user mount, empty mountMap,
host paths, sharedCwdPath precedence) behave correctly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test: cover resolveWorkDir primary-mount fallback; extract findPrimaryMount

Adds BATS coverage for the session-root cwd fix and extracts the
primary-mount derivation into a shared findPrimaryMount() helper so
HostBackend's resolveWorkDir() and BwrapBackend.spawn() share one
canonical implementation instead of two copies that can drift.

Tests:
- resolveWorkDir: session-root cwd uses primary user mount
- resolveWorkDir: session-root cwd skips dotfile and uploads mounts
- resolveWorkDir: session-root cwd with no user mount falls back to home
- findPrimaryMount: returns null for null/undefined/empty mountMap
- findPrimaryMount: returns first non-dotfile non-uploads key
- findPrimaryMount: returns null when all mounts are dotfiles or uploads
- findPrimaryMount: insertion order determines primary when multiple exist

The inline test copy of resolveWorkDir is updated to match the new
production logic.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-18 18:51:10 -05:00
2025-04-03 10:41:13 -04:00
2026-04-13 03:17:43 +00:00

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 bwrap installed and functional
host (fallback) 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.

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

Claude Desktop running on Linux

Global hotkey popup

Installation

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).

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 --exe flag 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
    • --doctor diagnostic 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
  • daa25209 for detailed root cause analysis of the cowork platform gate crash and patch script
  • noctuum
    • CLAUDE_MENU_BAR env 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 --doctor support 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 isPackaged regression
  • 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-cache symlink ELOOP bug
    • Fixing auto-memory path translation on HostBackend
  • reinthal for fixing the NixOS build breakage caused by the nixpkgs nodePackages removal
  • gianluca-peri
    • Reporting the GNOME quit accessibility issue
    • Confirming tray behavior with AppIndicator

Sponsorship

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.

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 to help cover those costs.

License

The build scripts in this repository are dual-licensed under:

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.

Description
No description provided
Readme 10 GiB
Languages
TypeScript 46.6%
Shell 40.5%
JavaScript 11.4%
Nix 0.9%
Python 0.6%