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
135 lines
7.5 KiB
Markdown
135 lines
7.5 KiB
Markdown
[< Back to README](../README.md)
|
|
|
|
# Building from Source
|
|
|
|
`build.sh` downloads Anthropic's official Claude Desktop Linux `.deb`, optionally patches its `app.asar`, and repackages the official application tree as a `.deb`, `.rpm`, or AppImage.
|
|
|
|
```bash
|
|
git clone https://github.com/aaddrick/claude-desktop-debian.git
|
|
cd claude-desktop-debian
|
|
|
|
# Build with the auto-detected format for your distro
|
|
./build.sh
|
|
|
|
# Or pick a format explicitly
|
|
./build.sh --build deb
|
|
./build.sh --build rpm
|
|
./build.sh --build appimage
|
|
```
|
|
|
|
The default format is detected from the host distribution:
|
|
|
|
| Distribution family | Default format |
|
|
|---------------------|----------------|
|
|
| Debian, Ubuntu, Mint (`/etc/debian_version`) | `deb` |
|
|
| Fedora, RHEL, CentOS | `rpm` |
|
|
| NixOS | `nix` (currently a stub — see [Nix](#nix) below) |
|
|
| Anything else (including Arch) | `appimage` |
|
|
|
|
## Prerequisites
|
|
|
|
The official `.deb` is unpacked with `ar` + `tar` instead of `dpkg-deb`, so rpm-family and Arch hosts can build too. Per format:
|
|
|
|
| Needed for | Commands |
|
|
|------------|----------|
|
|
| Every format | `wget`, `ar` (binutils), `tar`, `xz`, `zstd` |
|
|
| `--build deb` | `dpkg-deb` (dpkg-dev) |
|
|
| `--build rpm` | `rpmbuild` (rpm-build) |
|
|
| `--build appimage` | `appimagetool` — downloaded into `build/` automatically when not on PATH |
|
|
| The asar patch stage | Node.js v20+ — a local v20.18.1 is downloaded into `build/` when the system Node is missing or too old; `@electron/asar` is npm-installed into `build/` |
|
|
|
|
On Debian- and RPM-family hosts, `build.sh` offers to install the missing system packages via `apt`/`dnf` (`check_dependencies` in `scripts/setup/dependencies.sh`). On other distros it lists what to install manually.
|
|
|
|
## Build flags
|
|
|
|
From `parse_arguments` in `scripts/setup/detect-host.sh`:
|
|
|
|
```
|
|
./build.sh [--build deb|rpm|appimage|nix] [--clean yes|no]
|
|
[--deb /path/to/claude-desktop.deb] [--arch amd64|arm64]
|
|
[--release-tag TAG] [--source-dir /path] [--test-flags]
|
|
```
|
|
|
|
| Flag | Default | Effect |
|
|
|------|---------|--------|
|
|
| `-b`, `--build` | auto-detected | Output format: `deb`, `rpm`, `appimage`, or `nix`. |
|
|
| `-c`, `--clean` | `yes` | Remove intermediate files in `build/` after packaging. `--clean no` keeps them for inspection. |
|
|
| `-d`, `--deb` | download | Use a locally downloaded official `.deb` instead of fetching the pinned one. The SHA256 pin check is skipped for local files. |
|
|
| `-a`, `--arch` | `uname -m` | Override the target architecture (`amd64` or `arm64`) for cross-building — repackaging the official `.deb` is arch-independent, so an amd64 host can produce an arm64 package. |
|
|
| `-r`, `--release-tag` | unset | Release tag (e.g. `v3.0.0+claude1.18286.0`); the wrapper version is extracted and appended to the package version (`1.18286.0-3.0.0`). Used by CI. |
|
|
| `-s`, `--source-dir` | repo root | Path to the repo root for scripts and assets, for out-of-tree invocations. |
|
|
| `--test-flags` | off | Parse flags, print the results, and exit without building. |
|
|
|
|
## How the official .deb is resolved
|
|
|
|
The build never scrapes a download page — it pulls a pinned artifact from Anthropic's official APT pool:
|
|
|
|
- `scripts/setup/official-deb.sh` pins `OFFICIAL_DEB_VERSION` (currently `1.18286.0`) plus a per-architecture pool path and SHA256 against `https://downloads.claude.ai/claude-desktop/apt/stable`.
|
|
- The download is verified against the pinned SHA256 before extraction.
|
|
- `ar` + `tar` extract `data.tar.*` and `control.tar.*` (zst/xz/gz all handled); the app tree must land at `usr/lib/claude-desktop` or the build aborts with an upstream-layout error.
|
|
- The package version is read from the extracted control file; a mismatch against the pin is a warning, not a failure.
|
|
- `Depends:` and `Recommends:` are read from the official control file and re-emitted verbatim into our packages — the contract differs per arch (arm64 recommends a different qemu stack than amd64), and re-emitting tracks upstream automatically.
|
|
|
|
The pins are bumped automatically: the `check-claude-version` workflow polls the official APT `Packages` index, rewrites the `OFFICIAL_DEB_*` pins in `scripts/setup/official-deb.sh`, updates the `CLAUDE_DESKTOP_VERSION` repo variable, and pushes a `v{REPO_VERSION}+claude{VERSION}` tag that triggers the release build.
|
|
|
|
To build a version before the automation catches it, download the `.deb` from the official pool yourself and pass `--deb /path/to/claude-desktop_VERSION_ARCH.deb`.
|
|
|
|
## The patch stage (patch-zero contract)
|
|
|
|
`active_patches` in `scripts/patches/app-asar.sh` lists every asar patch still active. The default verdict for any patch is delete: when the array is empty, the official `app.asar` ships **byte-identical** — it is never extracted or repacked. Two patches currently survive:
|
|
|
|
- `patch_quick_window` (`scripts/patches/quick-window.sh`) — KDE-gated blur/focus workaround so the main window reappears after a Quick Entry submit (Electron stale-focus bug on Plasma).
|
|
- `patch_org_plugins_path` (`scripts/patches/org-plugins.sh`) — adds a `case "linux"` to the upstream org-plugins platform switch, which only handles darwin/win32; without it MDM org plugins are silently dead on Linux (filed upstream).
|
|
|
|
Two build-time tripwires grep the pristine `app.asar` on every build and fail loudly if upstream flips behavior we deleted patches for: `apt_channel_pending` (AU-1 — the marker that keeps the official autoupdater dormant while the APT channel is pending) and `menuBarEnabled:!0` (MB-1 — the settings default that keeps the menu bar on).
|
|
|
|
When patches do run, the repack preserves upstream's `app.asar.unpacked` set exactly and aborts if the sets diverge.
|
|
|
|
## Installing the built package
|
|
|
|
### For .deb packages (Debian/Ubuntu)
|
|
|
|
```bash
|
|
sudo apt install ./claude-desktop-unofficial_VERSION_ARCHITECTURE.deb
|
|
# Or: sudo dpkg -i ./claude-desktop-unofficial_VERSION_ARCHITECTURE.deb
|
|
|
|
# If you encounter dependency issues:
|
|
sudo apt --fix-broken install
|
|
```
|
|
|
|
### For .rpm packages (Fedora/RHEL)
|
|
|
|
```bash
|
|
sudo dnf install ./claude-desktop-unofficial-VERSION-1.ARCH.rpm
|
|
# Or: sudo rpm -i ./claude-desktop-unofficial-VERSION-1.ARCH.rpm
|
|
```
|
|
|
|
### For AppImages
|
|
|
|
```bash
|
|
# Make executable
|
|
chmod +x ./claude-desktop-unofficial-*.AppImage
|
|
|
|
# Run directly
|
|
./claude-desktop-unofficial-*.AppImage
|
|
|
|
# Or integrate with your system using Gear Lever
|
|
```
|
|
|
|
**Note:** AppImage login requires proper desktop integration. Use [Gear Lever](https://flathub.org/apps/it.mijorus.gearlever) or manually install the generated `.desktop` file to `~/.local/share/applications/`.
|
|
|
|
**Automatic updates:** AppImages downloaded from GitHub releases include embedded update information and work with Gear Lever for automatic updates. Locally-built AppImages can be configured manually in Gear Lever.
|
|
|
|
## Nix
|
|
|
|
The derivation (`nix/claude-desktop.nix`) repackages the official `.deb`: `fetchurl` from the official APT pool, `autoPatchelfHook` over the bare co-located tree, no nixpkgs Electron. The FHS output (`nix/fhs.nix`, the flake default) additionally provides MCP runtime dependencies and OVMF firmware at Cowork's hardcoded probe paths.
|
|
|
|
```bash
|
|
nix build .#claude-desktop
|
|
nix build .#claude-desktop-fhs
|
|
```
|
|
|
|
Build-verified on x86_64; runtime on real NixOS and the aarch64 leg are open validation items (owner @typedrat). Design contract, SRI auto-bump anchors, and a no-NixOS testing recipe: [`docs/learnings/nix.md`](learnings/nix.md).
|
|
|
|
Two facts about the `--build nix` path that hold on this branch: `build.sh --build nix` requires `--deb` (it never downloads inside the sandbox), and it stops after the patch stage — the Nix derivation is expected to handle installation itself.
|