diff --git a/nix/agent-modules/default.nix b/nix/agent-modules/default.nix index 5db3dbdc..6047ad5c 100644 --- a/nix/agent-modules/default.nix +++ b/nix/agent-modules/default.nix @@ -242,7 +242,7 @@ in ++ [ ( if config.services.hyperhive.agent.claudeCodePath == null then - pkgs.claude-code + import ../claude-code-no-alsa.nix lib pkgs.claude-code else # Host-pinned claude: a symlink farm around a path the # container was handed as text. It has to be a derivation — diff --git a/nix/claude-code-no-alsa.nix b/nix/claude-code-no-alsa.nix new file mode 100644 index 00000000..89484a11 --- /dev/null +++ b/nix/claude-code-no-alsa.nix @@ -0,0 +1,25 @@ +# `claude-code` without the `--prefix LD_LIBRARY_PATH` alsa-lib entry +# nixpkgs adds to its wrapper. The wrapper exports the variable into +# claude's own environment, so every shell claude spawns inherits an +# alsa-lib `lib` dir that shadows the libraries newer nixpkgs binaries +# (headless chromium) were built against. Agents have no audio device, +# so alsa-lib is not needed. Every other wrapper flag stays. +# +# nixpkgs gives no switch for it (`alsa-lib` only feeds that one +# `makeLibraryPath`), so the line is dropped from `installPhase`. A +# package whose `installPhase` has no such line comes back unchanged. +lib: claudeCode: +let + marker = "--prefix LD_LIBRARY_PATH"; + dropMarker = + phase: + lib.concatStringsSep "\n" ( + builtins.filter (l: !(lib.hasInfix marker l)) (lib.splitString "\n" phase) + ); +in +if lib.hasInfix marker (claudeCode.installPhase or "") then + claudeCode.overrideAttrs (old: { + installPhase = dropMarker old.installPhase; + }) +else + claudeCode diff --git a/nix/host-modules/hive-c0re/default.nix b/nix/host-modules/hive-c0re/default.nix index 0e87c4bf..056cdb92 100644 --- a/nix/host-modules/hive-c0re/default.nix +++ b/nix/host-modules/hive-c0re/default.nix @@ -109,7 +109,11 @@ let # anything that drops it. The failure mode is a garbage-collected # `claude` and a hive that can't take a turn, weeks after the commit # that caused it. - claude_code_path = controllerCfg.claudeCodePackage; + claude_code_path = + if controllerCfg.claudeCodePackage == null then + null + else + import ../../claude-code-no-alsa.nix lib controllerCfg.claudeCodePackage; dashboard_port = controllerCfg.dashboardPort; agent_cpu_quota = cfg.agentCpuQuota; agent_memory_max = cfg.agentMemoryMax;