Files
claude-desktop-package/CLAUDE.md
2026-07-02 06:14:08 +00:00

4.0 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Purpose

This repo repackages Claude Desktop into RPMs for Fedora 43 & 44 / x86_64. It does not contain the app source — it downloads the upstream .deb from Anthropic's apt repository, repackages the prebuilt Electron bundle as an RPM (no recompile), signs it, and publishes to a self-hosted dnf repo at rpm.lair.cafe. Modelled on the sibling repo lair/mistralrs-package.

Why this exists

Claude Desktop's in-app updater uses Electron's native autoUpdater, which is macOS/Windows only — it is inert on Linux. Anthropic's only Linux update channel is an apt repo (Debian/Ubuntu). This repo is the dnf-equivalent so Fedora hosts stay current via dnf upgrade.

Architecture

Pipeline flow

  1. poll-upstream (.gitea/workflows/poll-upstream.yml) — cron every 6h. Reads the upstream apt Packages index for the latest version. If the corresponding RPMs don't exist (and aren't indexed) on rpm.lair.cafe for fc43 & fc44, and no build is in-flight, dispatches build-release.
  2. build-release (.gitea/workflows/build-release.yml) — two-stage pipeline, matrix over Fedora 43 & 44:
    • package (runs-on: rpm) — resolves the .deb URL + SHA256 from the apt Packages index, downloads and verifies it, then rpmbuild -bb rpm/claude-desktop.spec with --define claude_desktop_version and --define "dist .fcNN".
    • publish (runs-on: rpm) — OpenPGP-signs the RPMs (rpm --addsign), rsyncs to rpm.lair.cafe, runs createrepo_c --update, regenerates packages.json. createrepo/packages.json are wrapped in flock /var/www/rpm/.publish.lock to serialise against other package repos publishing into the same tree.

Upstream source of truth

https://downloads.claude.ai/claude-desktop/apt/stable/dists/stable/main/binary-amd64/Packages — each stanza carries Version, Filename, and SHA256. The .deb download URL is ${APT_BASE}/${Filename}.

Key files

  • rpm/claude-desktop.spec — RPM spec. Prebuilt Electron bundle; extracts the .deb with ar + tar in %prep (no dpkg dependency). Explicitly chmod 4755 the setuid-root chrome-sandbox in %install (GNU tar drops setuid bits when not run as root); drops the Debian AppArmor/apt maintainer scripts (Fedora uses SELinux + dnf).
  • rpm/rpmmacros%_openpgp_sign_id @GPG_NAME@; @GPG_NAME@ is sed-replaced with RPM_SIGNING_KEY_ID at publish time.
  • script/generate-packages-json.py — regenerates the whole tree's packages.json from repodata (verbatim copy of the sibling repo's script; keep in sync).

Commands

Build an RPM locally from the upstream .deb:

rpmdev-setuptree
VERSION=1.17377.2
curl -fsSL -o ~/rpmbuild/SOURCES/claude-desktop_${VERSION}_amd64.deb \
  "https://downloads.claude.ai/claude-desktop/apt/stable/pool/main/c/claude-desktop/claude-desktop_${VERSION}_amd64.deb"
rpmbuild -bb rpm/claude-desktop.spec \
  --define "claude_desktop_version ${VERSION}" \
  --undefine dist --define "dist .fc44"

Infrastructure

  • CI runs on Gitea Actions (self-hosted), not GitHub Actions.
  • RPM repo hosted at rpm.lair.cafe on host oolon.kosherinata.internal.
  • Stable repos: rpm.lair.cafe/fedora/{43,44}/x86_64/ (shared with other lair packages).
  • Publish uses rsync over SSH as the gitea_ci user.
  • Required Actions secrets: DISPATCH_TOKEN, RPM_SIGNING_KEY, RPM_SIGNING_KEY_ID, RSYNC_SSH_KEY (org-level on lair if configured; otherwise set per-repo).

Consuming the repo

On a Fedora host, drop a .repo file pointing at https://rpm.lair.cafe/fedora/$releasever/x86_64/ (see lair/mistralrs-package for the existing client .repo convention), then dnf install claude-desktop. Subsequent dnf upgrade picks up new versions automatically.

Runtime notes

  • If Chromium's sandbox misbehaves on a host with restricted user namespaces: claude-desktop --no-sandbox, or sysctl kernel.unprivileged_userns_clone=1.