From 8c91e08e7ca360c2d78e8f77efa102d142d42b57 Mon Sep 17 00:00:00 2001 From: Ivan Malison Date: Wed, 24 Jun 2026 18:28:08 -0700 Subject: [PATCH] claude-remote-control: fix pure-eval; skip missing dirs at runtime The previous version filtered the directory list with builtins.pathExists. That breaks under the automatic system.autoUpgrade, which builds the flake from GitHub in *pure* evaluation mode: there pathExists returns false for every absolute path, so the filter collapsed to an empty list and generated zero sessions. Use a static directory list (pure-eval safe) and instead gate each unit on systemd's ConditionPathIsDirectory=, evaluated at runtime. Hosts that lack a given directory skip just that session cleanly (inactive, not failed, no restart loop), so the same module/list works across machines. Co-Authored-By: Claude Opus 4.8 (1M context) --- nixos/claude-remote-control.nix | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/nixos/claude-remote-control.nix b/nixos/claude-remote-control.nix index b1cbad28..a618fd9a 100644 --- a/nixos/claude-remote-control.nix +++ b/nixos/claude-remote-control.nix @@ -13,19 +13,19 @@ # `-L` socket) and Remote Control session name derived from the directory's # base name. Attach locally with the generated `claude-rc-attach-` # alias, e.g. `claude-rc-attach-dotfiles`. - candidateDirectories = [ + # The same list is used on every host that enables this module. A host that + # doesn't have a given directory simply skips that one session at runtime via + # `ConditionPathIsDirectory` (see below) — so we must NOT filter the list at + # eval time. In particular `builtins.pathExists` is useless here: the + # auto-upgrade builds this flake in *pure* evaluation mode, where pathExists + # returns false for every absolute path and would silently drop every session. + directories = [ "/srv/dotfiles" "/home/imalison/Projects/subtr-actor" "/home/imalison/Projects/rocket-sense" "/home/imalison/code/mova" ]; - # Only run a session for directories that actually exist on this host, so the - # same module can be enabled across machines where some projects live at - # different paths (or not at all). Relies on impure evaluation, which the - # `just switch` workflow already uses (`nixos-rebuild ... --impure`). - directories = builtins.filter builtins.pathExists candidateDirectories; - # claude shells out to these for its tools; give the service a clean PATH. servicePath = lib.makeBinPath (with pkgs; [ claude-code @@ -59,6 +59,10 @@ Unit = { Description = "Claude Code remote-control session (${dir})"; After = ["network.target"]; + # Skip this session cleanly (not "failed", no restart loop) on hosts + # where the directory doesn't exist. Evaluated at runtime, so it stays + # correct regardless of pure vs impure Nix evaluation. + ConditionPathIsDirectory = dir; }; Service = { # tmux new-session -d daemonizes the server and returns.