OOKNET                             [ /  search the index  ]  
──────────────────────────────────────────────────────────────────────────────────────
══════════════════════════════════════════════════════════════════════════════════════
OOKNET   [ /  search  ]  
────────────────────────────────────────────────
════════════════════════════════════════════════
 
 
main @ 313 LINES
 
[ HISTORY ]  [ UP ]
 

# adapted from github:aaddrick/claude-desktop-debian (nix/claude-desktop.nix)
# build scripts are pulled via fetchFromGitHub rather than vendoring the repo
# to bump: update repoSrc rev/hash + version + the windows exe srcs below
{
  lib,
  stdenvNoCC,
  fetchurl,
  fetchFromGitHub,
  electron,
  p7zip,
  icoutils,
  imagemagick,
  nodejs,
  asar,
  makeDesktopItem,
  python3,
  bash,
  getent,
  node-pty,
}: let
  pname = "claude-desktop";
  version = "1.12603.1";

  # upstream repo providing build.sh + scripts/ (the actual packaging logic)
  repoSrc = fetchFromGitHub {
    owner = "aaddrick";
    repo = "claude-desktop-debian";
    rev = "d2ce0466315033938ea6c2066d424239feffabf0"; # v2.0.20+claude1.12603.1
    hash = "sha256-vMMjROGD/huIbrvTV3okyMPseleQ3dsFOabJo9TtfoI=";
  };

  srcs = {
    x86_64-linux = fetchurl {
      url = "https://downloads.claude.ai/releases/win32/x64/1.12603.1/Claude-3df4f
d263723119bc45f0af2d784afd5055e2ba9.exe";
      hash = "sha256-Fym+uhmkDkkA8+32jk3B7BxFJ8TbM1sTOADJlkUMl6g=";
    };
    aarch64-linux = fetchurl {
      url = "https://downloads.claude.ai/releases/win32/arm64/1.12603.1/Claude-3df
4fd263723119bc45f0af2d784afd5055e2ba9.exe";
      hash = "sha256-jthQmwDvYBV89iR9xdrUccCQOTaEEgyfjxFoVIZEcKw=";
    };
  };

  src = srcs.${stdenvNoCC.hostPlatform.system} or (throw "Unsupported system: ${st
denvNoCC.hostPlatform.system}");

  # The unwrapped electron derivation - contains the real ELF binary
  # and Chromium resources (.pak files, locales/, etc.).
  electronUnwrapped = electron.passthru.unwrapped or electron;
  electronDir = "${electronUnwrapped}/libexec/electron";

  desktopItem = makeDesktopItem {
    name = "claude-desktop";
    exec = "claude-desktop %u";
    icon = "claude-desktop";
    type = "Application";
    terminal = false;
    desktopName = "Claude";
    genericName = "Claude Desktop";
    startupWMClass = "Claude";
    categories = ["Office" "Utility"];
    mimeTypes = ["x-scheme-handler/claude"];
  };
in
  stdenvNoCC.mkDerivation {
    inherit pname version src;

    nativeBuildInputs = [
      p7zip
      nodejs
      asar
      icoutils
      imagemagick
      bash
      python3
      getent
    ];

    # The exe is not a standard archive - use manual unpack
    dontUnpack = true;

    buildPhase = ''
      runHook preBuild

      export HOME=$TMPDIR

      # Writable copy of upstream so we can fix its #649 add-dir patch.
      # v2.0.20's patch asserts the minified --add-dir dispatch snippet
      # appears exactly once and patches only the first hit, but claude
      # 1.12603.1 carries it twice and the assertion fatals. The two hits
      # are byte-identical (upstream counts an escaped literal), so the
      # filtered replacement it computes is correct for both - rewrite the
      # patch to neutralise the count guard and replace all occurrences.
      cp -r --no-preserve=mode,ownership ${repoSrc} ./upstream
      substituteInPlace ./upstream/scripts/patches/config.sh \
        --replace-fail 'allMatches && allMatches.length > 1' 'false' \
        --replace-fail 'code = code.replace(match[0], filtered);' 'code = code.spl
it(match[0]).join(filtered);'

      # Copy exe to a writable location for build.sh
      cp $src Claude-Setup.exe

      # Run build.sh in nix mode - it handles extraction, patching, icon
      # extraction, and asar repacking. --source-dir points at our patched
      # copy so build.sh finds scripts/.
      bash ./upstream/build.sh \
        --exe "$(pwd)/Claude-Setup.exe" \
        --source-dir "$(pwd)/upstream" \
        --node-pty-dir "${node-pty}/lib/node_modules/node-pty" \
        --build nix \
        --clean no

      runHook postBuild
    '';

    installPhase = ''
            runHook preInstall

            #=====================================================================
=====
            # Create a custom Electron tree with app resources co-located.
            #
            # On NixOS, the stock electron-unwrapped lives in a read-only store
            # path.  Chromium computes process.resourcesPath from /proc/self/exe,
            # so it always points to electron-unwrapped's resources/ dir - which
            # doesn't contain the app's locale JSONs, tray icons, etc.  When
            # ELECTRON_FORCE_IS_PACKAGED=true, the app reads en-US.json from
            # resourcesPath at module load time (before frame-fix-wrapper.js can
            # correct the path), causing an ENOENT crash.
            #
            # Solution: copy the Electron ELF binary into our own tree so that
            # /proc/self/exe resolves here, then merge both Electron's and the
            # app's resources into resources/.  Everything else (shared libs,
            # .pak files, locales/) is symlinked to avoid duplication.
            #=====================================================================
=====
            electron_tree=$out/lib/claude-desktop/electron

            mkdir -p $electron_tree/resources

            # Copy the ELF binary - MUST be a real copy (not symlink) so that
            # /proc/self/exe resolves to our tree
            cp ${electronDir}/electron $electron_tree/electron
            chmod +x $electron_tree/electron

            # Symlink everything else from electron-unwrapped
            for item in ${electronDir}/*; do
              name=$(basename "$item")
              [[ "$name" = "electron" ]] && continue
              [[ "$name" = "resources" ]] && continue
              ln -s "$item" "$electron_tree/$name"
            done

            # Populate resources/ - start with Electron's own (default_app.asar)
            for item in ${electronDir}/resources/*; do
              ln -s "$item" "$electron_tree/resources/$(basename "$item")"
            done

            # Install app.asar and unpacked resources into the merged tree
            cp build/electron-app/app.asar $electron_tree/resources/
            cp -r build/electron-app/app.asar.unpacked $electron_tree/resources/

            # Install tray icons into resources
            for tray_icon in build/electron-app/nix-resources/Tray*; do
              [[ -f "$tray_icon" ]] && cp "$tray_icon" $electron_tree/resources/
            done

            # Install SSH helpers into resources
            if [[ -d build/electron-app/nix-resources/claude-ssh ]]; then
              cp -r build/electron-app/nix-resources/claude-ssh \
                $electron_tree/resources/
            fi

            # Install cowork resources (smol-bin, plugin shim)
            for cowork_res in build/electron-app/nix-resources/smol-bin.*.vhdx \
                              build/electron-app/nix-resources/cowork-plugin-shim.
sh; do
              if [[ -f "$cowork_res" ]]; then
                cp "$cowork_res" $electron_tree/resources/
                echo "Installed cowork resource: $(basename "$cowork_res")"
              fi
            done

            # Install ion-dist static assets (app:// protocol handler root for
            # Third-Party Inference setup - see issue #488)
            if [[ -d build/electron-app/nix-resources/ion-dist ]]; then
              cp -r build/electron-app/nix-resources/ion-dist \
                $electron_tree/resources/
              echo "Installed cowork resource: ion-dist"
            fi

            # Install locale JSON files into resources
            for locale_json in build/claude-extract/lib/net45/resources/*-*.json; 
do
              [[ -f "$locale_json" ]] \
                && cp "$locale_json" $electron_tree/resources/
            done

            # Create the electron wrapper - replicates the env setup from the
            # stock electron wrapper (GIO, GTK, GDK_PIXBUF, XDG_DATA_DIRS) but
            # execs our custom binary.  We extract everything except the final
            # exec line from the stock wrapper, then append our own exec.
            head -n -1 ${electron}/bin/electron > $electron_tree/electron-wrapper
            echo "exec \"$electron_tree/electron\" \"\$@\"" >> $electron_tree/elec
tron-wrapper
            chmod +x $electron_tree/electron-wrapper

            # Update CHROME_DEVEL_SANDBOX to point to our tree's chrome-sandbox
            substituteInPlace $electron_tree/electron-wrapper \
              --replace-quiet "${electron}/libexec/electron/chrome-sandbox" \
                "$electron_tree/chrome-sandbox"

            #=====================================================================
=====
            # Standard install (icons, desktop file, launcher)
            #=====================================================================
=====

            # Convenience symlink for resources dir (used by launcher, FHS, etc.)
            ln -s $electron_tree/resources $out/lib/claude-desktop/resources

            # Install icons
            for size in 16 24 32 48 64 256; do
              icon_dir=$out/share/icons/hicolor/"$size"x"$size"/apps
              mkdir -p "$icon_dir"
              icon=$(find build/ -name "claude_*''${size}x''${size}x32.png" 2>/dev
/null | head -1)
              if [[ -n "$icon" ]]; then
                install -Dm644 "$icon" "$icon_dir/claude-desktop.png"
              fi
            done

            # Install shared launcher library + doctor (launcher-common.sh
            # sources doctor.sh at runtime, so both must live in the same dir)
            install -Dm755 ${repoSrc}/scripts/launcher-common.sh \
              $out/lib/claude-desktop/launcher-common.sh
            install -Dm755 ${repoSrc}/scripts/doctor.sh \
              $out/lib/claude-desktop/doctor.sh

            # Install .desktop file
            mkdir -p $out/share/applications
            install -Dm644 ${desktopItem}/share/applications/* $out/share/applicat
ions/

            # Create launcher script
            mkdir -p $out/bin
            cat > $out/bin/claude-desktop <<'LAUNCHER'
      #!/usr/bin/env bash
      # Claude Desktop launcher for NixOS

      electron_exec="ELECTRON_PLACEHOLDER"
      app_path="RESOURCES_PLACEHOLDER/app.asar"

      source "LAUNCHER_LIB_PLACEHOLDER"

      # Handle --doctor flag before anything else
      if [[ "''${1:-}" == '--doctor' ]]; then
      	run_doctor "$electron_exec"
      	exit $?
      fi

      # Setup logging and environment
      setup_logging || exit 1
      setup_electron_env
      cleanup_orphaned_cowork_daemon
      cleanup_stale_desktop_helpers
      cleanup_stale_lock
      cleanup_stale_cowork_socket

      # Log startup info
      log_message '--- Claude Desktop Launcher Start (NixOS) ---'
      log_message "Timestamp: $(date)"
      log_message "Arguments: $@"
      log_session_env

      # Check for display
      if ! check_display; then
      	log_message 'No display detected (TTY session)'
      	echo 'Error: Claude Desktop requires a graphical desktop environment.' >&2
      	echo 'Please run from within an X11 or Wayland session, not from a TTY.' >&
2
      	exit 1
      fi

      # Detect display backend (handles CLAUDE_USE_WAYLAND)
      detect_display_backend

      # Build Electron arguments
      build_electron_args 'nix'

      # Intentionally NOT appended: app.asar sits in Electron's default
      # resources/ dir next to the binary, so Electron auto-loads it. Passing
      # the path again makes Electron treat it as a file-to-open, which the
      # app forwards to its file-drop handler, producing a spurious
      # "Attach app.asar?" prompt on launch and on every taskbar reopen
      # (the second-instance argv path). Omitting it is the root-cause fix.
      # See issue #696.
      log_message "App (auto-loaded by Electron): $app_path"

      # Execute Electron and keep the launcher alive so explicit quit can
      # clean up Desktop-owned helpers that outlive the Electron main process.
      log_message "Executing: $electron_exec ''${electron_args[*]} $*"
      run_electron_and_cleanup "$electron_exec" "''${electron_args[@]}" "$@"
      exit $?
      LAUNCHER
            # Substitute placeholders - electron_exec points to our custom
            # wrapper (which sets GTK/GIO env then execs our merged binary)
            substituteInPlace $out/bin/claude-desktop \
              --replace-fail "ELECTRON_PLACEHOLDER" "$electron_tree/electron-wrapp
er" \
              --replace-fail "RESOURCES_PLACEHOLDER" "$electron_tree/resources" \
              --replace-fail "LAUNCHER_LIB_PLACEHOLDER" "$out/lib/claude-desktop/l
auncher-common.sh"
            chmod +x $out/bin/claude-desktop

            runHook postInstall
    '';

    meta = with lib; {
      description = "Claude Desktop for Linux";
      homepage = "https://github.com/aaddrick/claude-desktop-debian";
      license = licenses.unfree;
      platforms = ["x86_64-linux" "aarch64-linux"];
      sourceProvenance = with sourceTypes; [binaryNativeCode];
      mainProgram = "claude-desktop";
    };
  }

# adapted from github:aaddrick/claude-deskto
p-debian (nix/claude-desktop.nix)
# build scripts are pulled via fetchFromGitH
ub rather than vendoring the repo
# to bump: update repoSrc rev/hash + version
 + the windows exe srcs below
{
  lib,
  stdenvNoCC,
  fetchurl,
  fetchFromGitHub,
  electron,
  p7zip,
  icoutils,
  imagemagick,
  nodejs,
  asar,
  makeDesktopItem,
  python3,
  bash,
  getent,
  node-pty,
}: let
  pname = "claude-desktop";
  version = "1.12603.1";

  # upstream repo providing build.sh + scrip
ts/ (the actual packaging logic)
  repoSrc = fetchFromGitHub {
    owner = "aaddrick";
    repo = "claude-desktop-debian";
    rev = "d2ce0466315033938ea6c2066d424239f
effabf0"; # v2.0.20+claude1.12603.1
    hash = "sha256-vMMjROGD/huIbrvTV3okyMPse
leQ3dsFOabJo9TtfoI=";
  };

  srcs = {
    x86_64-linux = fetchurl {
      url = "https://downloads.claude.ai/rel
eases/win32/x64/1.12603.1/Claude-3df4fd26372
3119bc45f0af2d784afd5055e2ba9.exe";
      hash = "sha256-Fym+uhmkDkkA8+32jk3B7Bx
FJ8TbM1sTOADJlkUMl6g=";
    };
    aarch64-linux = fetchurl {
      url = "https://downloads.claude.ai/rel
eases/win32/arm64/1.12603.1/Claude-3df4fd263
723119bc45f0af2d784afd5055e2ba9.exe";
      hash = "sha256-jthQmwDvYBV89iR9xdrUccC
QOTaEEgyfjxFoVIZEcKw=";
    };
  };

  src = srcs.${stdenvNoCC.hostPlatform.syste
m} or (throw "Unsupported system: ${stdenvNo
CC.hostPlatform.system}");

  # The unwrapped electron derivation - cont
ains the real ELF binary
  # and Chromium resources (.pak files, loca
les/, etc.).
  electronUnwrapped = electron.passthru.unwr
apped or electron;
  electronDir = "${electronUnwrapped}/libexe
c/electron";

  desktopItem = makeDesktopItem {
    name = "claude-desktop";
    exec = "claude-desktop %u";
    icon = "claude-desktop";
    type = "Application";
    terminal = false;
    desktopName = "Claude";
    genericName = "Claude Desktop";
    startupWMClass = "Claude";
    categories = ["Office" "Utility"];
    mimeTypes = ["x-scheme-handler/claude"];
  };
in
  stdenvNoCC.mkDerivation {
    inherit pname version src;

    nativeBuildInputs = [
      p7zip
      nodejs
      asar
      icoutils
      imagemagick
      bash
      python3
      getent
    ];

    # The exe is not a standard archive - us
e manual unpack
    dontUnpack = true;

    buildPhase = ''
      runHook preBuild

      export HOME=$TMPDIR

      # Writable copy of upstream so we can 
fix its #649 add-dir patch.
      # v2.0.20's patch asserts the minified
 --add-dir dispatch snippet
      # appears exactly once and patches onl
y the first hit, but claude
      # 1.12603.1 carries it twice and the a
ssertion fatals. The two hits
      # are byte-identical (upstream counts 
an escaped literal), so the
      # filtered replacement it computes is 
correct for both - rewrite the
      # patch to neutralise the count guard 
and replace all occurrences.
      cp -r --no-preserve=mode,ownership ${r
epoSrc} ./upstream
      substituteInPlace ./upstream/scripts/p
atches/config.sh \
        --replace-fail 'allMatches && allMat
ches.length > 1' 'false' \
        --replace-fail 'code = code.replace(
match[0], filtered);' 'code = code.split(mat
ch[0]).join(filtered);'

      # Copy exe to a writable location for 
build.sh
      cp $src Claude-Setup.exe

      # Run build.sh in nix mode - it handle
s extraction, patching, icon
      # extraction, and asar repacking. --so
urce-dir points at our patched
      # copy so build.sh finds scripts/.
      bash ./upstream/build.sh \
        --exe "$(pwd)/Claude-Setup.exe" \
        --source-dir "$(pwd)/upstream" \
        --node-pty-dir "${node-pty}/lib/node
_modules/node-pty" \
        --build nix \
        --clean no

      runHook postBuild
    '';

    installPhase = ''
            runHook preInstall

            #===============================
===========================================
            # Create a custom Electron tree 
with app resources co-located.
            #
            # On NixOS, the stock electron-u
nwrapped lives in a read-only store
            # path.  Chromium computes proce
ss.resourcesPath from /proc/self/exe,
            # so it always points to electro
n-unwrapped's resources/ dir - which
            # doesn't contain the app's loca
le JSONs, tray icons, etc.  When
            # ELECTRON_FORCE_IS_PACKAGED=tru
e, the app reads en-US.json from
            # resourcesPath at module load t
ime (before frame-fix-wrapper.js can
            # correct the path), causing an 
ENOENT crash.
            #
            # Solution: copy the Electron EL
F binary into our own tree so that
            # /proc/self/exe resolves here, 
then merge both Electron's and the
            # app's resources into resources
/.  Everything else (shared libs,
            # .pak files, locales/) is symli
nked to avoid duplication.
            #===============================
===========================================
            electron_tree=$out/lib/claude-de
sktop/electron

            mkdir -p $electron_tree/resource
s

            # Copy the ELF binary - MUST be 
a real copy (not symlink) so that
            # /proc/self/exe resolves to our
 tree
            cp ${electronDir}/electron $elec
tron_tree/electron
            chmod +x $electron_tree/electron

            # Symlink everything else from e
lectron-unwrapped
            for item in ${electronDir}/*; do
              name=$(basename "$item")
              [[ "$name" = "electron" ]] && 
continue
              [[ "$name" = "resources" ]] &&
 continue
              ln -s "$item" "$electron_tree/
$name"
            done

            # Populate resources/ - start wi
th Electron's own (default_app.asar)
            for item in ${electronDir}/resou
rces/*; do
              ln -s "$item" "$electron_tree/
resources/$(basename "$item")"
            done

            # Install app.asar and unpacked 
resources into the merged tree
            cp build/electron-app/app.asar $
electron_tree/resources/
            cp -r build/electron-app/app.asa
r.unpacked $electron_tree/resources/

            # Install tray icons into resour
ces
            for tray_icon in build/electron-
app/nix-resources/Tray*; do
              [[ -f "$tray_icon" ]] && cp "$
tray_icon" $electron_tree/resources/
            done

            # Install SSH helpers into resou
rces
            if [[ -d build/electron-app/nix-
resources/claude-ssh ]]; then
              cp -r build/electron-app/nix-r
esources/claude-ssh \
                $electron_tree/resources/
            fi

            # Install cowork resources (smol
-bin, plugin shim)
            for cowork_res in build/electron
-app/nix-resources/smol-bin.*.vhdx \
                              build/electron
-app/nix-resources/cowork-plugin-shim.sh; do
              if [[ -f "$cowork_res" ]]; the
n
                cp "$cowork_res" $electron_t
ree/resources/
                echo "Installed cowork resou
rce: $(basename "$cowork_res")"
              fi
            done

            # Install ion-dist static assets
 (app:// protocol handler root for
            # Third-Party Inference setup - 
see issue #488)
            if [[ -d build/electron-app/nix-
resources/ion-dist ]]; then
              cp -r build/electron-app/nix-r
esources/ion-dist \
                $electron_tree/resources/
              echo "Installed cowork resourc
e: ion-dist"
            fi

            # Install locale JSON files into
 resources
            for locale_json in build/claude-
extract/lib/net45/resources/*-*.json; do
              [[ -f "$locale_json" ]] \
                && cp "$locale_json" $electr
on_tree/resources/
            done

            # Create the electron wrapper - 
replicates the env setup from the
            # stock electron wrapper (GIO, G
TK, GDK_PIXBUF, XDG_DATA_DIRS) but
            # execs our custom binary.  We e
xtract everything except the final
            # exec line from the stock wrapp
er, then append our own exec.
            head -n -1 ${electron}/bin/elect
ron > $electron_tree/electron-wrapper
            echo "exec \"$electron_tree/elec
tron\" \"\$@\"" >> $electron_tree/electron-w
rapper
            chmod +x $electron_tree/electron
-wrapper

            # Update CHROME_DEVEL_SANDBOX to
 point to our tree's chrome-sandbox
            substituteInPlace $electron_tree
/electron-wrapper \
              --replace-quiet "${electron}/l
ibexec/electron/chrome-sandbox" \
                "$electron_tree/chrome-sandb
ox"

            #===============================
===========================================
            # Standard install (icons, deskt
op file, launcher)
            #===============================
===========================================

            # Convenience symlink for resour
ces dir (used by launcher, FHS, etc.)
            ln -s $electron_tree/resources $
out/lib/claude-desktop/resources

            # Install icons
            for size in 16 24 32 48 64 256; 
do
              icon_dir=$out/share/icons/hico
lor/"$size"x"$size"/apps
              mkdir -p "$icon_dir"
              icon=$(find build/ -name "clau
de_*''${size}x''${size}x32.png" 2>/dev/null 
| head -1)
              if [[ -n "$icon" ]]; then
                install -Dm644 "$icon" "$ico
n_dir/claude-desktop.png"
              fi
            done

            # Install shared launcher librar
y + doctor (launcher-common.sh
            # sources doctor.sh at runtime, 
so both must live in the same dir)
            install -Dm755 ${repoSrc}/script
s/launcher-common.sh \
              $out/lib/claude-desktop/launch
er-common.sh
            install -Dm755 ${repoSrc}/script
s/doctor.sh \
              $out/lib/claude-desktop/doctor
.sh

            # Install .desktop file
            mkdir -p $out/share/applications
            install -Dm644 ${desktopItem}/sh
are/applications/* $out/share/applications/

            # Create launcher script
            mkdir -p $out/bin
            cat > $out/bin/claude-desktop <<
'LAUNCHER'
      #!/usr/bin/env bash
      # Claude Desktop launcher for NixOS

      electron_exec="ELECTRON_PLACEHOLDER"
      app_path="RESOURCES_PLACEHOLDER/app.as
ar"

      source "LAUNCHER_LIB_PLACEHOLDER"

      # Handle --doctor flag before anything
 else
      if [[ "''${1:-}" == '--doctor' ]]; the
n
      	run_doctor "$electron_exec"
      	exit $?
      fi

      # Setup logging and environment
      setup_logging || exit 1
      setup_electron_env
      cleanup_orphaned_cowork_daemon
      cleanup_stale_desktop_helpers
      cleanup_stale_lock
      cleanup_stale_cowork_socket

      # Log startup info
      log_message '--- Claude Desktop Launch
er Start (NixOS) ---'
      log_message "Timestamp: $(date)"
      log_message "Arguments: $@"
      log_session_env

      # Check for display
      if ! check_display; then
      	log_message 'No display detected (TTY
 session)'
      	echo 'Error: Claude Desktop requires 
a graphical desktop environment.' >&2
      	echo 'Please run from within an X11 o
r Wayland session, not from a TTY.' >&2
      	exit 1
      fi

      # Detect display backend (handles CLAU
DE_USE_WAYLAND)
      detect_display_backend

      # Build Electron arguments
      build_electron_args 'nix'

      # Intentionally NOT appended: app.asar
 sits in Electron's default
      # resources/ dir next to the binary, s
o Electron auto-loads it. Passing
      # the path again makes Electron treat 
it as a file-to-open, which the
      # app forwards to its file-drop handle
r, producing a spurious
      # "Attach app.asar?" prompt on launch 
and on every taskbar reopen
      # (the second-instance argv path). Omi
tting it is the root-cause fix.
      # See issue #696.
      log_message "App (auto-loaded by Elect
ron): $app_path"

      # Execute Electron and keep the launch
er alive so explicit quit can
      # clean up Desktop-owned helpers that 
outlive the Electron main process.
      log_message "Executing: $electron_exec
 ''${electron_args[*]} $*"
      run_electron_and_cleanup "$electron_ex
ec" "''${electron_args[@]}" "$@"
      exit $?
      LAUNCHER
            # Substitute placeholders - elec
tron_exec points to our custom
            # wrapper (which sets GTK/GIO en
v then execs our merged binary)
            substituteInPlace $out/bin/claud
e-desktop \
              --replace-fail "ELECTRON_PLACE
HOLDER" "$electron_tree/electron-wrapper" \
              --replace-fail "RESOURCES_PLAC
EHOLDER" "$electron_tree/resources" \
              --replace-fail "LAUNCHER_LIB_P
LACEHOLDER" "$out/lib/claude-desktop/launche
r-common.sh"
            chmod +x $out/bin/claude-desktop

            runHook postInstall
    '';

    meta = with lib; {
      description = "Claude Desktop for Linu
x";
      homepage = "https://github.com/aaddric
k/claude-desktop-debian";
      license = licenses.unfree;
      platforms = ["x86_64-linux" "aarch64-l
inux"];
      sourceProvenance = with sourceTypes; [
binaryNativeCode];
      mainProgram = "claude-desktop";
    };
  }
 
──────────────────────────────────────────────────────────────────────────────────────
OOKNET
────────────────────────────────────────────────
OOKNET