dot
vizie's NixOS desktop: Hyprland, CachyOS kernel and gaming tweaks
| 1 | # Anthropic's official Claude Desktop for Linux (beta), repackaged from the .deb in |
| 2 | # Anthropic's own apt repository: https://code.claude.com/docs/en/desktop-linux |
| 3 | # |
| 4 | # To update: pick the newest Filename/SHA256 pair from |
| 5 | # https://downloads.claude.ai/claude-desktop/apt/stable/dists/stable/main/binary-amd64/Packages |
| 6 | # and change version and sha256 below (the index's SHA256 is in hex, as here). |
| 7 | # |
| 8 | # Cowork also needs QEMU/KVM, the vhost_vsock module and OVMF firmware at the |
| 9 | # Debian path it looks for; modules/nixos/apps.nix provides those. |
| 10 | # |
| 11 | # The Code tab runs Claude Code from the Nix store (claude-code.nix) rather than |
| 12 | # a copy the app downloads, and Python tools use nixpkgs' uv rather than one it |
| 13 | # downloads. After a version change, update claude-code.nix too: the build says |
| 14 | # so if the app pins a different Claude Code. |
| 15 | { |
| 16 | lib, |
| 17 | stdenv, |
| 18 | callPackage, |
| 19 | fetchurl, |
| 20 | dpkg, |
| 21 | asar, |
| 22 | autoPatchelfHook, |
| 23 | makeWrapper, |
| 24 | wrapGAppsHook3, |
| 25 | alsa-lib, |
| 26 | at-spi2-atk, |
| 27 | at-spi2-core, |
| 28 | cairo, |
| 29 | cups, |
| 30 | dbus, |
| 31 | expat, |
| 32 | glib, |
| 33 | gtk3, |
| 34 | libdrm, |
| 35 | libgbm, |
| 36 | libglvnd, |
| 37 | libnotify, |
| 38 | libpulseaudio, |
| 39 | libsecret, |
| 40 | libuuid, |
| 41 | libxkbcommon, |
| 42 | libayatana-appindicator, |
| 43 | nspr, |
| 44 | nss, |
| 45 | pango, |
| 46 | pipewire, |
| 47 | systemd, |
| 48 | vulkan-loader, |
| 49 | libx11, |
| 50 | libxcomposite, |
| 51 | libxdamage, |
| 52 | libxext, |
| 53 | libxfixes, |
| 54 | libxrandr, |
| 55 | libxtst, |
| 56 | libxshmfence, |
| 57 | libxcb, |
| 58 | libseccomp, |
| 59 | libcap_ng, |
| 60 | xdg-utils, |
| 61 | qemu_kvm, |
| 62 | socat, |
| 63 | bubblewrap, |
| 64 | openssh, |
| 65 | uv, |
| 66 | }: |
| 67 | |
| 68 | let |
| 69 | claude-code = callPackage ./claude-code.nix { }; |
| 70 | in |
| 71 | stdenv.mkDerivation (finalAttrs: { |
| 72 | pname = "claude-desktop"; |
| 73 | version = "2.42304.0"; |
| 74 | |
| 75 | src = fetchurl { |
| 76 | url = "https://downloads.claude.ai/claude-desktop/apt/stable/pool/main/c/claude-desktop/claude-desktop__amd64.deb"; |
| 77 | sha256 = "74cd2ccc29d24165144e455cbc872c6cc2a24a263b83e73420e95f89166d4aa4"; |
| 78 | }; |
| 79 | |
| 80 | nativeBuildInputs = [ |
| 81 | dpkg |
| 82 | asar |
| 83 | autoPatchelfHook |
| 84 | makeWrapper |
| 85 | wrapGAppsHook3 |
| 86 | ]; |
| 87 | |
| 88 | buildInputs = [ |
| 89 | alsa-lib |
| 90 | at-spi2-atk |
| 91 | at-spi2-core |
| 92 | cairo |
| 93 | cups |
| 94 | dbus |
| 95 | expat |
| 96 | glib |
| 97 | gtk3 |
| 98 | libdrm |
| 99 | libgbm |
| 100 | libnotify |
| 101 | libpulseaudio |
| 102 | libsecret |
| 103 | libuuid |
| 104 | libxkbcommon |
| 105 | nspr |
| 106 | nss |
| 107 | pango |
| 108 | pipewire |
| 109 | systemd |
| 110 | libx11 |
| 111 | libxcomposite |
| 112 | libxdamage |
| 113 | libxext |
| 114 | libxfixes |
| 115 | libxrandr |
| 116 | libxtst |
| 117 | libxshmfence |
| 118 | libxcb |
| 119 | # The bundled virtiofsd (Cowork). |
| 120 | libseccomp |
| 121 | libcap_ng |
| 122 | ]; |
| 123 | |
| 124 | # Loaded with dlopen at run time, so autoPatchelf can't see them. |
| 125 | runtimeLibs = [ |
| 126 | libglvnd |
| 127 | libnotify |
| 128 | libpulseaudio |
| 129 | libayatana-appindicator |
| 130 | pipewire |
| 131 | systemd |
| 132 | vulkan-loader |
| 133 | ]; |
| 134 | |
| 135 | dontWrapGApps = true; |
| 136 | |
| 137 | unpackPhase = '' |
| 138 | runHook preUnpack |
| 139 | # Not dpkg-deb -x: the sandbox can't recreate chrome-sandbox's setuid bit. |
| 140 | dpkg-deb --fsys-tarfile $src | tar -x --no-same-permissions --no-same-owner |
| 141 | runHook postUnpack |
| 142 | ''; |
| 143 | |
| 144 | installPhase = '' |
| 145 | runHook preInstall |
| 146 | |
| 147 | mkdir -p $out/lib $out/bin |
| 148 | cp -r usr/lib/claude-desktop $out/lib/ |
| 149 | cp -r usr/share $out/ |
| 150 | rm -rf $out/share/lintian |
| 151 | |
| 152 | # The setuid sandbox helper can't be setuid in the Nix store; Chromium uses |
| 153 | # the user-namespace sandbox instead, which needs no helper. |
| 154 | rm $out/lib/claude-desktop/chrome-sandbox |
| 155 | |
| 156 | # The app has an override for running a Claude Code that's already on disk |
| 157 | # instead of downloading one; release builds compile out the part that |
| 158 | # reads it. This puts it back, pointing at the store path. The app then |
| 159 | # also leaves Claude Code updates alone: they come with this package. |
| 160 | res=$out/lib/claude-desktop/resources |
| 161 | asar extract $res/app.asar app |
| 162 | pin=$(grep -l '"baseUrl":"https://downloads.claude.ai/claude-code-releases"' app/.vite/build/*.js) |
| 163 | if ! grep -qF '{"version":"","manifest"' $pin; then |
| 164 | echo "claude-desktop: the app pins another Claude Code than ; update claude-code.nix" >&2 |
| 165 | exit 1 |
| 166 | fi |
| 167 | hook='process.env.CLAUDE_CODE_LOCAL_BINARY}async initLocalBinary(' |
| 168 | if ! file=$(grep -lF "$hook" app/.vite/build/*.js); then |
| 169 | echo "claude-desktop: the app's Claude Code override has changed; see the comment above" >&2 |
| 170 | exit 1 |
| 171 | fi |
| 172 | substituteInPlace $file --replace-fail "$hook" \ |
| 173 | 'this.localBinaryInitPromise=this.initLocalBinary("")}async initLocalBinary(' |
| 174 | rm -r $res/app.asar $res/app.asar.unpacked |
| 175 | asar pack app $res/app.asar --unpack '{*.node,github-mcp-server}' |
| 176 | |
| 177 | runHook postInstall |
| 178 | ''; |
| 179 | |
| 180 | postFixup = '' |
| 181 | makeWrapper $out/lib/claude-desktop/claude-desktop $out/bin/claude-desktop \ |
| 182 | "''${gappsWrapperArgs[@]}" \ |
| 183 | --prefix LD_LIBRARY_PATH : \ |
| 184 | --prefix PATH : |
| 185 | |
| 186 | |
| 187 | |
| 188 | |
| 189 | |
| 190 | |
| 191 | |
| 192 | |
| 193 | |
| 194 | ''; |
| 195 | |
| 196 | passthru = { inherit claude-code; }; |
| 197 | |
| 198 | meta = { |
| 199 | description = "Claude desktop app (official Linux beta build)"; |
| 200 | homepage = "https://claude.ai/download"; |
| 201 | license = lib.licenses.unfree; |
| 202 | mainProgram = "claude-desktop"; |
| 203 | platforms = [ "x86_64-linux" ]; |
| 204 | sourceProvenance = [ lib.sourceTypes.binaryNativeCode ]; |
| 205 | }; |
| 206 | }) |