Files
wehub-resource-sync 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
chore: import upstream snapshot with attribution
2026-07-13 12:29:21 +08:00

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.