be755c08c166

fix code-review HIGH: home commands are local-only, bump v3.1.2 — home detection (binary, ~/.config/home-manager, $HOME/$USER flake ref) all read the LOCAL host while exec routes over SSH for a remote machine, so 'nina home --on <remote>' would decide mode/flake-ref from the wrong box. Now home() refuses a non-local machine with output.homeLocalOnly. Also (MED) homeApplyDone prints 'done' instead of 'generation 0' when the post-switch gen re-read fails (switch still succeeded). VERSION/zon -> 3.1.2. Verified on mac: 'home apply --on remotebox' -> local-only refusal; local 'home apply' unaffected. build+tests green

time
2026-06-10 12:13 UTC · 4 months ago
machine
koh2
agent
claude-opus-4-8
session
flake + home manager support
parent
a96eade6fa9c
4 files VERSION+1 −1build.zig.zon+1 −1src/commands.zig+10 −0src/output.zig+17 −0
VERSION+1 −1
@@ -1 +1 @@1-3.1.11+3.1.2

view file

build.zig.zon+1 −1
@@ -9,7 +9,7 @@99     .name = .nina,1010     // This is a [Semantic Version](https://semver.org/).1111     // In a future version of Zig it will be used for package deduplication.12-    .version = "3.1.1",12+    .version = "3.1.2",1313     // Together with name, this represents a globally unique package1414     // identifier. This field is generated by the Zig toolchain when the1515     // package is first created, and then *never changes*. This allows

view file

src/commands.zig+10 −0
@@ -978,6 +978,16 @@978978     if (ctx.sub.len == 0 or std.mem.eql(u8, ctx.sub, "help"))979979         return output.subcommandHelp("home", &home_help, null);980980 981+    // Home Manager manages the local user's environment. Detection (which binary,982+    // ~/.config/home-manager, $HOME/$USER for the flake ref) all read the LOCAL983+    // host, while exec routes over SSH for a remote machine — so `home --on984+    // <remote>` would decide mode/flake-ref from the wrong box. Refuse it cleanly985+    // rather than acting on a mismatch.986+    if (!ctx.machine.local) {987+        output.homeLocalOnly(ctx.machine.name);988+        return;989+    }990+981991     const mode = exec.detectHomeManager(ctx.gpa, ctx.io, ctx.environ);982992     if (mode == .none) {983993         output.homeNotInstalled();

view file

src/output.zig+17 −0
@@ -995,11 +995,28 @@995995 996996 pub fn homeApplyDone(gen: u32, elapsed_ms: u64) void {997997     const secs = @as(f64, @floatFromInt(elapsed_ms)) / 1000.0;998+    // gen 0 means the post-switch generation re-read failed — the switch itself999+    // succeeded, so report success without a misleading "generation 0".1000+    if (gen == 0) {1001+        if (elapsed_ms >= 1000) {1002+            p("{s}done  {s}[{d:.1}s]{s}\n", .{ hdr(), c(DIM), secs, c(RESET) });1003+        } else {1004+            p("{s}done\n", .{hdr()});1005+        }1006+        return;1007+    }9981008     if (elapsed_ms >= 1000) {9991009         p("{s}generation {s}{d}{s}  {s}[{d:.1}s]{s}\n", .{ hdr(), c(BOLD), gen, c(RESET), c(DIM), secs, c(RESET) });10001010     } else {10011011         p("{s}generation {s}{d}{s}\n", .{ hdr(), c(BOLD), gen, c(RESET) });10021012     }1013+}1014+1015+// `home` was invoked against a remote machine. Detection + flake-ref are1016+// local-only, so we don't act on a remote — point the user at the local run.1017+pub fn homeLocalOnly(machine: []const u8) void {1018+    p("{s}home manager commands run on the local machine only\n", .{hdr()});1019+    p("   {s}-> '{s}' is remote; run nina home on that machine directly{s}\n", .{ c(DIM), machine, c(RESET) });10031020 }10041021 10051022 pub fn homeApplyDry(machine: []const u8) void {

view file