claude-nomad 0.53.2 → 0.54.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/nomad.mjs CHANGED
@@ -614,19 +614,19 @@ var init_utils_fs = __esm({
614
614
  });
615
615
 
616
616
  // src/commands.pull.wedge.ts
617
- import { execFileSync as execFileSync2 } from "node:child_process";
618
- import { existsSync as existsSync12 } from "node:fs";
619
- import { join as join14 } from "node:path";
617
+ import { execFileSync as execFileSync3 } from "node:child_process";
618
+ import { existsSync as existsSync13 } from "node:fs";
619
+ import { join as join15 } from "node:path";
620
620
  function detectWedge(repo) {
621
- const g = join14(repo, ".git");
622
- if (existsSync12(join14(g, "rebase-merge")) || existsSync12(join14(g, "rebase-apply"))) return "rebase";
623
- if (existsSync12(join14(g, "MERGE_HEAD"))) return "merge";
621
+ const g = join15(repo, ".git");
622
+ if (existsSync13(join15(g, "rebase-merge")) || existsSync13(join15(g, "rebase-apply"))) return "rebase";
623
+ if (existsSync13(join15(g, "MERGE_HEAD"))) return "merge";
624
624
  return null;
625
625
  }
626
626
  function unmergedIndexPresent(repo) {
627
627
  let raw;
628
628
  try {
629
- raw = execFileSync2("git", ["diff", "--diff-filter=U", "--name-only", "-z"], {
629
+ raw = execFileSync3("git", ["diff", "--diff-filter=U", "--name-only", "-z"], {
630
630
  cwd: repo,
631
631
  stdio: ["ignore", "pipe", "pipe"],
632
632
  maxBuffer: 64 * 1024 * 1024
@@ -660,7 +660,7 @@ function wedgeMarkerRunbookText(state) {
660
660
  function orphanedAutostashPresent(repo) {
661
661
  let raw;
662
662
  try {
663
- raw = execFileSync2("git", ["stash", "list"], {
663
+ raw = execFileSync3("git", ["stash", "list"], {
664
664
  cwd: repo,
665
665
  stdio: ["ignore", "pipe", "pipe"],
666
666
  maxBuffer: 64 * 1024 * 1024
@@ -677,15 +677,15 @@ var init_commands_pull_wedge = __esm({
677
677
  });
678
678
 
679
679
  // src/push-gitleaks.config.ts
680
- import { existsSync as existsSync13, mkdtempSync, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "node:fs";
680
+ import { existsSync as existsSync14, mkdtempSync, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "node:fs";
681
681
  import { tmpdir } from "node:os";
682
- import { join as join15 } from "node:path";
682
+ import { join as join16 } from "node:path";
683
683
  import { fileURLToPath } from "node:url";
684
684
  function resolveTomlPath(repo = repoHome()) {
685
- const repoToml = join15(repo, ".gitleaks.toml");
686
- if (existsSync13(repoToml)) return repoToml;
685
+ const repoToml = join16(repo, ".gitleaks.toml");
686
+ if (existsSync14(repoToml)) return repoToml;
687
687
  const bundled = fileURLToPath(new URL("../.gitleaks.toml", import.meta.url));
688
- return existsSync13(bundled) ? bundled : null;
688
+ return existsSync14(bundled) ? bundled : null;
689
689
  }
690
690
  function assertOverlayAllowlistsScoped(overlayBody) {
691
691
  if (OVERLAY_INLINE_ALLOWLIST_RE.test(overlayBody)) {
@@ -723,17 +723,17 @@ function buildOverlayTempConfig(overlayBody, bundled) {
723
723
  path = ${JSON.stringify(bundled)}
724
724
 
725
725
  ${overlayBody}`;
726
- const tempPath = mkdtempSync(join15(tmpdir(), "nomad-gitleaks-cfg-"));
727
- const configPath = join15(tempPath, "config.toml");
726
+ const tempPath = mkdtempSync(join16(tmpdir(), "nomad-gitleaks-cfg-"));
727
+ const configPath = join16(tempPath, "config.toml");
728
728
  writeFileSync3(configPath, tempBody, { mode: 384, flag: "wx" });
729
729
  return { configPath, tempPath };
730
730
  }
731
731
  function resolveTomlConfig() {
732
732
  const repo = repoHome();
733
- const overlayPath = join15(repo, ".gitleaks.overlay.toml");
734
- const repoToml = join15(repo, ".gitleaks.toml");
733
+ const overlayPath = join16(repo, ".gitleaks.overlay.toml");
734
+ const repoToml = join16(repo, ".gitleaks.toml");
735
735
  const bundled = resolveTomlPath(repo);
736
- if (!existsSync13(overlayPath)) {
736
+ if (!existsSync14(overlayPath)) {
737
737
  return { path: bundled, tempPath: null };
738
738
  }
739
739
  if (bundled === repoToml) {
@@ -779,10 +779,10 @@ var init_push_gitleaks_config = __esm({
779
779
  });
780
780
 
781
781
  // src/push-checks.ts
782
- import { execFileSync as execFileSync3 } from "node:child_process";
782
+ import { execFileSync as execFileSync4 } from "node:child_process";
783
783
  import { readdirSync as readdirSync4, rmSync as rmSync5 } from "node:fs";
784
784
  import { homedir as homedir2, platform } from "node:os";
785
- import { join as join16 } from "node:path";
785
+ import { join as join17 } from "node:path";
786
786
  function gitleaksInstallHint() {
787
787
  const head = "gitleaks not on PATH (required for nomad push). Install:";
788
788
  const plat = platform();
@@ -825,7 +825,7 @@ function findGitlinks(dir) {
825
825
  return;
826
826
  }
827
827
  for (const e of entries) {
828
- const p = join16(current, e.name);
828
+ const p = join17(current, e.name);
829
829
  if (e.name === ".git") {
830
830
  hits.push(p);
831
831
  continue;
@@ -841,7 +841,7 @@ function probeGitleaks() {
841
841
  const args = ["version"];
842
842
  if (toml !== null) args.push("--config", toml);
843
843
  try {
844
- return execFileSync3("gitleaks", args, { stdio: ["ignore", "pipe", "pipe"] }).toString().trim();
844
+ return execFileSync4("gitleaks", args, { stdio: ["ignore", "pipe", "pipe"] }).toString().trim();
845
845
  } catch (err) {
846
846
  const e = err;
847
847
  if (e.code === "ENOENT") throw new NomadFatal(gitleaksInstallHint());
@@ -861,7 +861,7 @@ function rebaseBeforePush(repo) {
861
861
  const wedge = classifyWedge(repo);
862
862
  if (wedge !== null) throw new NomadFatal(wedgePreflight(wedge));
863
863
  try {
864
- execFileSync3("git", ["pull", "--rebase", "--autostash"], {
864
+ execFileSync4("git", ["pull", "--rebase", "--autostash"], {
865
865
  cwd: repo,
866
866
  stdio: ["ignore", "pipe", "pipe"]
867
867
  });
@@ -883,10 +883,10 @@ var init_push_checks = __esm({
883
883
  });
884
884
 
885
885
  // src/push-gitleaks.scan.ts
886
- import { execFileSync as execFileSync6 } from "node:child_process";
886
+ import { execFileSync as execFileSync8 } from "node:child_process";
887
887
  import { mkdirSync as mkdirSync3, readFileSync as readFileSync5, rmSync as rmSync6 } from "node:fs";
888
888
  import { homedir as homedir3 } from "node:os";
889
- import { join as join20 } from "node:path";
889
+ import { join as join21 } from "node:path";
890
890
  function readGitleaksReport(reportPath) {
891
891
  try {
892
892
  const raw = readFileSync5(reportPath, "utf8");
@@ -898,9 +898,9 @@ function readGitleaksReport(reportPath) {
898
898
  }
899
899
  }
900
900
  function scanStagedTree(repoDir, forwardStreams = false) {
901
- const cacheDir = join20(homedir3(), ".cache", "claude-nomad");
901
+ const cacheDir = join21(homedir3(), ".cache", "claude-nomad");
902
902
  mkdirSync3(cacheDir, { recursive: true });
903
- const reportPath = join20(cacheDir, `gitleaks-${nowTimestamp()}-${process.pid}.json`);
903
+ const reportPath = join21(cacheDir, `gitleaks-${nowTimestamp()}-${process.pid}.json`);
904
904
  const { path: toml, tempPath } = resolveTomlConfig();
905
905
  const args = [
906
906
  "protect",
@@ -913,9 +913,9 @@ function scanStagedTree(repoDir, forwardStreams = false) {
913
913
  if (toml !== null) args.push("--config", toml);
914
914
  const opts = { cwd: repoDir, stdio: ["ignore", "pipe", "pipe"] };
915
915
  try {
916
- execFileSync6("git", ["init", "-q"], opts);
917
- execFileSync6("git", ["add", "-A"], opts);
918
- execFileSync6("gitleaks", args, opts);
916
+ execFileSync8("git", ["init", "-q"], opts);
917
+ execFileSync8("git", ["add", "-A"], opts);
918
+ execFileSync8("gitleaks", args, opts);
919
919
  return [];
920
920
  } catch (err) {
921
921
  const e = err;
@@ -932,9 +932,9 @@ function scanStagedTree(repoDir, forwardStreams = false) {
932
932
  }
933
933
  }
934
934
  function scanFile(filePath, forwardStreams = false) {
935
- const cacheDir = join20(homedir3(), ".cache", "claude-nomad");
935
+ const cacheDir = join21(homedir3(), ".cache", "claude-nomad");
936
936
  mkdirSync3(cacheDir, { recursive: true });
937
- const reportPath = join20(cacheDir, `gitleaks-file-${nowTimestamp()}-${process.pid}.json`);
937
+ const reportPath = join21(cacheDir, `gitleaks-file-${nowTimestamp()}-${process.pid}.json`);
938
938
  const { path: toml, tempPath } = resolveTomlConfig();
939
939
  const args = [
940
940
  "detect",
@@ -947,7 +947,7 @@ function scanFile(filePath, forwardStreams = false) {
947
947
  if (toml !== null) args.push("--config", toml);
948
948
  const opts = { stdio: ["ignore", "pipe", "pipe"] };
949
949
  try {
950
- execFileSync6("gitleaks", args, opts);
950
+ execFileSync8("gitleaks", args, opts);
951
951
  return [];
952
952
  } catch (err) {
953
953
  const e = err;
@@ -2063,8 +2063,8 @@ function cmdEject(opts = {}, roots = defaultEjectRoots()) {
2063
2063
  }
2064
2064
 
2065
2065
  // src/commands.doctor.ts
2066
- import { existsSync as existsSync29 } from "node:fs";
2067
- import { join as join35 } from "node:path";
2066
+ import { existsSync as existsSync30 } from "node:fs";
2067
+ import { join as join36 } from "node:path";
2068
2068
 
2069
2069
  // src/commands.doctor.checks.repo.ts
2070
2070
  init_color();
@@ -2391,6 +2391,18 @@ function reportUnmappedProjects(section2, map) {
2391
2391
  addChildItem(section2, dim(dir));
2392
2392
  }
2393
2393
  }
2394
+ function reportCurrentHostPathsMissing(section2, map) {
2395
+ for (const [name, hosts] of Object.entries(map.projects)) {
2396
+ const abspath = hosts[HOST];
2397
+ if (!abspath || abspath === "TBD") continue;
2398
+ if (!existsSync11(abspath)) {
2399
+ addItem(
2400
+ section2,
2401
+ `${yellow(warnGlyph)} path-map: ${name} local path missing on ${HOST}: ${blue(abspath)}`
2402
+ );
2403
+ }
2404
+ }
2405
+ }
2394
2406
  function reportPathCollisions(section2, map) {
2395
2407
  const seen = /* @__PURE__ */ new Map();
2396
2408
  let collisionCount = 0;
@@ -2429,6 +2441,7 @@ function reportPathMap(section2) {
2429
2441
  return;
2430
2442
  }
2431
2443
  reportMappedProjects(section2, map);
2444
+ reportCurrentHostPathsMissing(section2, map);
2432
2445
  reportUnmappedProjects(section2, map);
2433
2446
  reportPathCollisions(section2, map);
2434
2447
  }
@@ -2441,18 +2454,103 @@ function reportNeverSync(section2) {
2441
2454
  );
2442
2455
  }
2443
2456
 
2457
+ // src/commands.doctor.checks.skills.ts
2458
+ init_color();
2459
+ import { existsSync as existsSync12 } from "node:fs";
2460
+ import { join as join14 } from "node:path";
2461
+ init_config();
2462
+
2463
+ // src/extras-sync.diff.ts
2464
+ init_utils();
2465
+ import { execFileSync as execFileSync2 } from "node:child_process";
2466
+ function labelDiffLine(line) {
2467
+ const tab = line.indexOf(" ");
2468
+ if (tab === -1) return line;
2469
+ const status = line.slice(0, tab);
2470
+ const path = line.slice(tab + 1);
2471
+ if (status === "D") return `${path} (local only)`;
2472
+ if (status === "A") return `${path} (repo only)`;
2473
+ return path;
2474
+ }
2475
+ function parseDiffOutput(stdout) {
2476
+ return stdout.split("\n").filter((line) => line.length > 0).map(labelDiffLine);
2477
+ }
2478
+ function listDivergingFiles(a, b) {
2479
+ try {
2480
+ const stdout = execFileSync2("git", ["diff", "--no-index", "--name-status", a, b], {
2481
+ stdio: ["ignore", "pipe", "pipe"]
2482
+ }).toString();
2483
+ return parseDiffOutput(stdout);
2484
+ } catch (err) {
2485
+ const e = err;
2486
+ if (e.status === 1 && e.stdout !== void 0) {
2487
+ return parseDiffOutput(e.stdout.toString());
2488
+ }
2489
+ if (e.code === "ENOENT") {
2490
+ warn(`git not on PATH; divergence check skipped for ${a}`);
2491
+ return [];
2492
+ }
2493
+ warn(`divergence check failed for ${a}: ${e.message ?? String(err)}`);
2494
+ return [];
2495
+ }
2496
+ }
2497
+
2498
+ // src/commands.doctor.checks.skills.ts
2499
+ function stripSideIndicator(line) {
2500
+ if (line.endsWith(" (local only)")) return line.slice(0, -" (local only)".length);
2501
+ if (line.endsWith(" (repo only)")) return line.slice(0, -" (repo only)".length);
2502
+ return line;
2503
+ }
2504
+ function isGsdDiffLine(line, localBase, sharedBase) {
2505
+ const bare = stripSideIndicator(line);
2506
+ let relative6;
2507
+ if (bare.startsWith(localBase + "/")) {
2508
+ relative6 = bare.slice(localBase.length + 1);
2509
+ } else if (bare.startsWith(sharedBase + "/")) {
2510
+ relative6 = bare.slice(sharedBase.length + 1);
2511
+ } else {
2512
+ relative6 = bare;
2513
+ }
2514
+ return relative6.split("/")[0].startsWith(GSD_PREFIX);
2515
+ }
2516
+ function reportSkillsDivergence(section2) {
2517
+ const sharedSkills = join14(repoHome(), "shared", "skills");
2518
+ const localSkills = join14(claudeHome(), "skills");
2519
+ if (!existsSync12(sharedSkills)) {
2520
+ addItem(section2, `${dim(infoGlyph)} skills: no shared/skills/ to compare`);
2521
+ return;
2522
+ }
2523
+ if (!existsSync12(localSkills)) {
2524
+ addItem(section2, `${dim(infoGlyph)} skills: no local skills/ to compare`);
2525
+ return;
2526
+ }
2527
+ const diff = listDivergingFiles(localSkills, sharedSkills);
2528
+ const relevant = diff.filter((line) => !isGsdDiffLine(line, localSkills, sharedSkills));
2529
+ if (relevant.length === 0) {
2530
+ addItem(section2, `${green(okGlyph)} skills: in sync with shared/skills/`);
2531
+ return;
2532
+ }
2533
+ addItem(
2534
+ section2,
2535
+ `${yellow(warnGlyph)} skills: ${relevant.length} file(s) diverge from shared/skills/`
2536
+ );
2537
+ for (const f of relevant) {
2538
+ addChildItem(section2, f);
2539
+ }
2540
+ }
2541
+
2444
2542
  // src/commands.doctor.checks.git-state.ts
2445
2543
  init_color();
2446
2544
  init_config();
2447
- import { execFileSync as execFileSync4 } from "node:child_process";
2448
- import { existsSync as existsSync14 } from "node:fs";
2449
- import { join as join17, relative as relative2 } from "node:path";
2545
+ import { execFileSync as execFileSync5 } from "node:child_process";
2546
+ import { existsSync as existsSync15 } from "node:fs";
2547
+ import { join as join18, relative as relative2 } from "node:path";
2450
2548
  init_commands_pull_wedge();
2451
2549
  init_push_checks();
2452
2550
  init_utils();
2453
2551
  function reportGitleaksProbe(section2) {
2454
2552
  try {
2455
- execFileSync4("gitleaks", ["version"], { stdio: ["ignore", "pipe", "pipe"] });
2553
+ execFileSync5("gitleaks", ["version"], { stdio: ["ignore", "pipe", "pipe"] });
2456
2554
  return true;
2457
2555
  } catch (err) {
2458
2556
  if (err.code === "ENOENT") {
@@ -2469,8 +2567,8 @@ function reportGitleaksProbe(section2) {
2469
2567
  }
2470
2568
  function reportGitlinks(section2) {
2471
2569
  const repo = repoHome();
2472
- const sharedDir = join17(repo, "shared");
2473
- if (existsSync14(sharedDir)) {
2570
+ const sharedDir = join18(repo, "shared");
2571
+ if (existsSync15(sharedDir)) {
2474
2572
  const gitlinks = findGitlinks(sharedDir);
2475
2573
  for (const p of gitlinks) {
2476
2574
  const rel = relative2(repo, p);
@@ -2488,7 +2586,7 @@ function reportGitlinks(section2) {
2488
2586
  }
2489
2587
  function reportRemote(section2) {
2490
2588
  try {
2491
- const url = execFileSync4("git", ["remote", "get-url", "origin"], {
2589
+ const url = execFileSync5("git", ["remote", "get-url", "origin"], {
2492
2590
  cwd: repoHome(),
2493
2591
  stdio: ["ignore", "pipe", "pipe"]
2494
2592
  }).toString().trim();
@@ -2540,11 +2638,36 @@ function reportOrphanedAutostash(sec) {
2540
2638
  } catch {
2541
2639
  }
2542
2640
  }
2641
+ function reportGitIdentity(section2) {
2642
+ const repo = repoHome();
2643
+ const missing = [];
2644
+ for (const field of ["user.name", "user.email"]) {
2645
+ try {
2646
+ const val = execFileSync5("git", ["config", field], {
2647
+ cwd: repo,
2648
+ stdio: ["ignore", "pipe", "pipe"]
2649
+ }).toString().trim();
2650
+ if (!val) missing.push(field);
2651
+ } catch (err) {
2652
+ if (err.status === 1) missing.push(field);
2653
+ else return;
2654
+ }
2655
+ }
2656
+ if (missing.length > 0) {
2657
+ const hint = missing.map((f) => `git config ${f} "..."`).join(" / ");
2658
+ addItem(
2659
+ section2,
2660
+ `${yellow(warnGlyph)} git identity: ${missing.join(", ")} not set (run: ${hint})`
2661
+ );
2662
+ } else {
2663
+ addItem(section2, `${green(okGlyph)} git identity: user.name and user.email configured`);
2664
+ }
2665
+ }
2543
2666
 
2544
2667
  // src/commands.doctor.checks.backups.ts
2545
2668
  init_color();
2546
- import { existsSync as existsSync15, lstatSync as lstatSync7, readdirSync as readdirSync5 } from "node:fs";
2547
- import { join as join18 } from "node:path";
2669
+ import { existsSync as existsSync16, lstatSync as lstatSync7, readdirSync as readdirSync5 } from "node:fs";
2670
+ import { join as join19 } from "node:path";
2548
2671
  init_config();
2549
2672
  var TS_SHAPE2 = /^\d{8}-\d{6}(-\d+)?$/;
2550
2673
  function safeReaddir(dir) {
@@ -2560,7 +2683,7 @@ var BYTES_PER_MB = 1024 * 1024;
2560
2683
  function dirSizeBytes(dir) {
2561
2684
  let bytes = 0;
2562
2685
  for (const entry of safeReaddir(dir)) {
2563
- const full = join18(dir, entry);
2686
+ const full = join19(dir, entry);
2564
2687
  const st = lstatSync7(full, { throwIfNoEntry: false });
2565
2688
  if (!st) continue;
2566
2689
  if (st.isSymbolicLink()) continue;
@@ -2571,11 +2694,11 @@ function dirSizeBytes(dir) {
2571
2694
  }
2572
2695
  function totalSizeMb(backupBase2, dirs) {
2573
2696
  let bytes = 0;
2574
- for (const name of dirs) bytes += dirSizeBytes(join18(backupBase2, name));
2697
+ for (const name of dirs) bytes += dirSizeBytes(join19(backupBase2, name));
2575
2698
  return bytes / BYTES_PER_MB;
2576
2699
  }
2577
2700
  function reportBackupsCheck(section2, backupBase2 = backupBase()) {
2578
- if (!existsSync15(backupBase2)) return;
2701
+ if (!existsSync16(backupBase2)) return;
2579
2702
  const dirs = safeReaddir(backupBase2).filter((n) => TS_SHAPE2.test(n));
2580
2703
  const count = dirs.length;
2581
2704
  const sizeMb = totalSizeMb(backupBase2, dirs);
@@ -2587,16 +2710,83 @@ function reportBackupsCheck(section2, backupBase2 = backupBase()) {
2587
2710
  }
2588
2711
  }
2589
2712
 
2713
+ // src/commands.doctor.check-remote.ts
2714
+ init_color();
2715
+ import { execFileSync as execFileSync6 } from "node:child_process";
2716
+ init_config();
2717
+ init_utils_json();
2718
+ var GIT_REMOTE_TIMEOUT_MS = 3e3;
2719
+ function readRemotePathMap(sec, repo) {
2720
+ let rawJson;
2721
+ try {
2722
+ rawJson = execFileSync6("git", ["show", "origin/main:path-map.json"], {
2723
+ cwd: repo,
2724
+ stdio: ["ignore", "pipe", "pipe"],
2725
+ timeout: GIT_REMOTE_TIMEOUT_MS
2726
+ }).toString();
2727
+ } catch {
2728
+ addItem(
2729
+ sec,
2730
+ `${yellow(warnGlyph)} remote check skipped (could not read path-map.json from origin/main)`
2731
+ );
2732
+ return false;
2733
+ }
2734
+ let map;
2735
+ try {
2736
+ map = JSON.parse(rawJson);
2737
+ } catch {
2738
+ addItem(sec, `${yellow(warnGlyph)} remote: path-map.json at origin/main is malformed JSON`);
2739
+ return false;
2740
+ }
2741
+ const shapeError = validatePathMapShape(map);
2742
+ if (shapeError !== null) {
2743
+ addItem(
2744
+ sec,
2745
+ `${yellow(warnGlyph)} remote: path-map.json at origin/main has invalid shape: ${shapeError}`
2746
+ );
2747
+ return false;
2748
+ }
2749
+ return true;
2750
+ }
2751
+ function reportCheckRemote(section2) {
2752
+ const repo = repoHome();
2753
+ let names;
2754
+ try {
2755
+ const out = execFileSync6("git", ["ls-tree", "--name-only", "origin/main"], {
2756
+ cwd: repo,
2757
+ stdio: ["ignore", "pipe", "pipe"],
2758
+ timeout: GIT_REMOTE_TIMEOUT_MS
2759
+ }).toString().trim();
2760
+ names = out.split("\n").filter(Boolean);
2761
+ } catch {
2762
+ addItem(
2763
+ section2,
2764
+ `${yellow(warnGlyph)} remote check skipped (origin/main unavailable or git error)`
2765
+ );
2766
+ return;
2767
+ }
2768
+ if (!names.includes("shared")) {
2769
+ addItem(section2, `${yellow(warnGlyph)} remote: shared/ not found in origin/main`);
2770
+ return;
2771
+ }
2772
+ if (!names.includes("path-map.json")) {
2773
+ addItem(section2, `${yellow(warnGlyph)} remote: path-map.json not found in origin/main`);
2774
+ return;
2775
+ }
2776
+ if (!readRemotePathMap(section2, repo)) return;
2777
+ addItem(section2, `${green(okGlyph)} remote: origin/main has shared/ and a valid path-map.json`);
2778
+ }
2779
+
2590
2780
  // src/commands.doctor.check-schema.ts
2591
2781
  init_color();
2592
- import { existsSync as existsSync16 } from "node:fs";
2593
- import { join as join19 } from "node:path";
2782
+ import { existsSync as existsSync17 } from "node:fs";
2783
+ import { join as join20 } from "node:path";
2594
2784
  init_config();
2595
2785
 
2596
2786
  // src/http-fetch.ts
2597
- import { execFileSync as execFileSync5 } from "node:child_process";
2787
+ import { execFileSync as execFileSync7 } from "node:child_process";
2598
2788
  var FETCH_TIMEOUT_MS = 3e3;
2599
- function fetchUrl(url, run = execFileSync5) {
2789
+ function fetchUrl(url, run = execFileSync7) {
2600
2790
  try {
2601
2791
  return run("curl", ["-fsSL", "-m", "3", url], {
2602
2792
  stdio: ["ignore", "pipe", "pipe"],
@@ -2627,8 +2817,8 @@ function fetchSchemaKeys() {
2627
2817
  }
2628
2818
  }
2629
2819
  function reportCheckSchema(section2) {
2630
- const settingsPath = join19(claudeHome(), "settings.json");
2631
- if (!existsSync16(settingsPath)) {
2820
+ const settingsPath = join20(claudeHome(), "settings.json");
2821
+ if (!existsSync17(settingsPath)) {
2632
2822
  addItem(section2, `${dim(infoGlyph)} no ~/.claude/settings.json to check`);
2633
2823
  return;
2634
2824
  }
@@ -2657,19 +2847,19 @@ function reportCheckSchema(section2) {
2657
2847
  // src/commands.doctor.check-shared.ts
2658
2848
  init_color();
2659
2849
  import { randomBytes } from "node:crypto";
2660
- import { execFileSync as execFileSync7 } from "node:child_process";
2661
- import { existsSync as existsSync18, mkdirSync as mkdirSync5, readdirSync as readdirSync7, rmSync as rmSync8 } from "node:fs";
2850
+ import { execFileSync as execFileSync9 } from "node:child_process";
2851
+ import { existsSync as existsSync19, mkdirSync as mkdirSync5, readdirSync as readdirSync7, rmSync as rmSync8 } from "node:fs";
2662
2852
  import { homedir as homedir4 } from "node:os";
2663
- import { join as join23 } from "node:path";
2853
+ import { join as join24 } from "node:path";
2664
2854
 
2665
2855
  // src/commands.doctor.check-shared.scan.ts
2666
2856
  init_color();
2667
- import { join as join21 } from "node:path";
2857
+ import { join as join22 } from "node:path";
2668
2858
  init_config();
2669
2859
  init_push_gitleaks();
2670
2860
  function scrubPath(logical, sid, logicalToEncoded) {
2671
2861
  const encoded = logicalToEncoded.get(logical) ?? logical;
2672
- return join21(claudeHome(), "projects", encoded, `${sid}.jsonl`);
2862
+ return join22(claudeHome(), "projects", encoded, `${sid}.jsonl`);
2673
2863
  }
2674
2864
  function reportSessionFindings(section2, bySession) {
2675
2865
  for (const [sid, counts] of bySession) {
@@ -2757,8 +2947,8 @@ init_config();
2757
2947
 
2758
2948
  // src/remap.ts
2759
2949
  init_config_sharedDirs_guard();
2760
- import { cpSync as cpSync4, existsSync as existsSync17, mkdirSync as mkdirSync4, readdirSync as readdirSync6, renameSync as renameSync3, rmSync as rmSync7, statSync as statSync4 } from "node:fs";
2761
- import { join as join22, relative as relative3, sep as sep3 } from "node:path";
2950
+ import { cpSync as cpSync4, existsSync as existsSync18, mkdirSync as mkdirSync4, readdirSync as readdirSync6, renameSync as renameSync3, rmSync as rmSync7, statSync as statSync4 } from "node:fs";
2951
+ import { join as join23, relative as relative3, sep as sep3 } from "node:path";
2762
2952
 
2763
2953
  // src/extras-sync.guards.ts
2764
2954
  init_utils();
@@ -2819,15 +3009,15 @@ function remapPull(ts, opts = {}) {
2819
3009
  const wouldPull = [];
2820
3010
  const repo = repoHome();
2821
3011
  const claude = claudeHome();
2822
- const mapPath = join22(repo, "path-map.json");
2823
- const repoProjects = join22(repo, "shared", "projects");
2824
- if (!existsSync17(mapPath) || !existsSync17(repoProjects)) {
3012
+ const mapPath = join23(repo, "path-map.json");
3013
+ const repoProjects = join23(repo, "shared", "projects");
3014
+ if (!existsSync18(mapPath) || !existsSync18(repoProjects)) {
2825
3015
  const text = "no path-map or repo projects dir; skipping session remap";
2826
3016
  emitPreview(opts.onPreview, { kind: "note", text }, text);
2827
3017
  return { unmapped: 0, pulled, wouldPull };
2828
3018
  }
2829
3019
  const map = readPathMap(mapPath);
2830
- const localProjects = join22(claude, "projects");
3020
+ const localProjects = join23(claude, "projects");
2831
3021
  if (!dryRun) mkdirSync4(localProjects, { recursive: true });
2832
3022
  for (const [logical, hosts] of Object.entries(map.projects)) {
2833
3023
  assertSafeLogical(logical);
@@ -2837,9 +3027,9 @@ function remapPull(ts, opts = {}) {
2837
3027
  continue;
2838
3028
  }
2839
3029
  assertSafeLocalRoot(localPath, logical);
2840
- const src = join22(repoProjects, logical);
2841
- if (!existsSync17(src)) continue;
2842
- const dst = join22(localProjects, encodePath(localPath));
3030
+ const src = join23(repoProjects, logical);
3031
+ if (!existsSync18(src)) continue;
3032
+ const dst = join23(localProjects, encodePath(localPath));
2843
3033
  if (dryRun) {
2844
3034
  wouldPull.push(logical);
2845
3035
  emitPreview(
@@ -2886,16 +3076,16 @@ function remapPush(ts, opts = {}) {
2886
3076
  const wouldPush = [];
2887
3077
  const repo = repoHome();
2888
3078
  const claude = claudeHome();
2889
- const mapPath = join22(repo, "path-map.json");
2890
- if (!existsSync17(mapPath)) {
3079
+ const mapPath = join23(repo, "path-map.json");
3080
+ if (!existsSync18(mapPath)) {
2891
3081
  log("no path-map.json; skipping session export");
2892
3082
  return { unmapped: 0, collisions: 0, pushed, wouldPush };
2893
3083
  }
2894
3084
  const map = readPathMap(mapPath);
2895
- const localProjects = join22(claude, "projects");
2896
- const repoProjects = join22(repo, "shared", "projects");
3085
+ const localProjects = join23(claude, "projects");
3086
+ const repoProjects = join23(repo, "shared", "projects");
2897
3087
  const reverse = buildReverseMap(map);
2898
- if (!existsSync17(localProjects)) return { unmapped, collisions: 0, pushed, wouldPush };
3088
+ if (!existsSync18(localProjects)) return { unmapped, collisions: 0, pushed, wouldPush };
2899
3089
  if (!dryRun) mkdirSync4(repoProjects, { recursive: true });
2900
3090
  for (const dir of readdirSync6(localProjects)) {
2901
3091
  if (dir.endsWith(TMP_SUFFIX)) continue;
@@ -2904,13 +3094,13 @@ function remapPush(ts, opts = {}) {
2904
3094
  unmapped++;
2905
3095
  continue;
2906
3096
  }
2907
- const repoDst = join22(repoProjects, logical);
3097
+ const repoDst = join23(repoProjects, logical);
2908
3098
  if (dryRun) {
2909
3099
  wouldPush.push(logical);
2910
3100
  continue;
2911
3101
  }
2912
3102
  backupRepoWrite(repoDst, ts, repo);
2913
- copyDirJsonlOnly(join22(localProjects, dir), repoDst);
3103
+ copyDirJsonlOnly(join23(localProjects, dir), repoDst);
2914
3104
  pushed.push(logical);
2915
3105
  }
2916
3106
  return { unmapped, collisions: 0, pushed, wouldPush };
@@ -2923,8 +3113,8 @@ function buildScanTree(tmpRoot) {
2923
3113
  const logicalToEncoded = /* @__PURE__ */ new Map();
2924
3114
  let staged = 0;
2925
3115
  const repo = repoHome();
2926
- const mapPath = join23(repo, "path-map.json");
2927
- if (!existsSync18(mapPath)) return { logicalToEncoded, staged, malformed: false };
3116
+ const mapPath = join24(repo, "path-map.json");
3117
+ if (!existsSync19(mapPath)) return { logicalToEncoded, staged, malformed: false };
2928
3118
  let map;
2929
3119
  try {
2930
3120
  map = readJson(mapPath);
@@ -2941,12 +3131,12 @@ function buildScanTree(tmpRoot) {
2941
3131
  if (!p || p === "TBD") continue;
2942
3132
  reverse.set(encodePath(p), logical);
2943
3133
  }
2944
- const localProjects = join23(claudeHome(), "projects");
2945
- if (!existsSync18(localProjects)) return { logicalToEncoded, staged, malformed: false };
3134
+ const localProjects = join24(claudeHome(), "projects");
3135
+ if (!existsSync19(localProjects)) return { logicalToEncoded, staged, malformed: false };
2946
3136
  for (const dir of readdirSync7(localProjects)) {
2947
3137
  const logical = reverse.get(dir);
2948
3138
  if (!logical) continue;
2949
- copyDirJsonlOnly(join23(localProjects, dir), join23(tmpRoot, "shared", "projects", logical));
3139
+ copyDirJsonlOnly(join24(localProjects, dir), join24(tmpRoot, "shared", "projects", logical));
2950
3140
  logicalToEncoded.set(logical, dir);
2951
3141
  staged++;
2952
3142
  }
@@ -2954,7 +3144,7 @@ function buildScanTree(tmpRoot) {
2954
3144
  }
2955
3145
  function probeGitleaksForScan() {
2956
3146
  try {
2957
- execFileSync7("gitleaks", ["version"], { stdio: ["ignore", "pipe", "pipe"] });
3147
+ execFileSync9("gitleaks", ["version"], { stdio: ["ignore", "pipe", "pipe"] });
2958
3148
  return "ok";
2959
3149
  } catch (err) {
2960
3150
  if (err.code === "ENOENT") return "missing";
@@ -2977,11 +3167,11 @@ function ensureGitleaksReady(section2, gitleaksReady) {
2977
3167
  }
2978
3168
  function reportCheckShared(section2, gitleaksReady) {
2979
3169
  if (!ensureGitleaksReady(section2, gitleaksReady)) return;
2980
- const cacheDir = join23(homedir4(), ".cache", "claude-nomad");
3170
+ const cacheDir = join24(homedir4(), ".cache", "claude-nomad");
2981
3171
  mkdirSync5(cacheDir, { recursive: true });
2982
3172
  const stamp = `${nowTimestamp()}-${process.pid}-${randomBytes(4).toString("hex")}`;
2983
- const reportPath = join23(cacheDir, `check-shared-${stamp}.json`);
2984
- const tmpRoot = join23(cacheDir, `check-shared-tree-${stamp}`);
3173
+ const reportPath = join24(cacheDir, `check-shared-${stamp}.json`);
3174
+ const tmpRoot = join24(cacheDir, `check-shared-tree-${stamp}`);
2985
3175
  try {
2986
3176
  const { logicalToEncoded, staged, malformed } = buildScanTree(tmpRoot);
2987
3177
  if (malformed) {
@@ -3002,8 +3192,8 @@ function reportCheckShared(section2, gitleaksReady) {
3002
3192
 
3003
3193
  // src/commands.doctor.checks.hooks.scope.ts
3004
3194
  init_color();
3005
- import { existsSync as existsSync19, readFileSync as readFileSync6, readdirSync as readdirSync8, realpathSync as realpathSync2 } from "node:fs";
3006
- import { dirname as dirname3, extname, join as join24 } from "node:path";
3195
+ import { existsSync as existsSync20, readFileSync as readFileSync6, readdirSync as readdirSync8, realpathSync as realpathSync2 } from "node:fs";
3196
+ import { dirname as dirname3, extname, join as join25 } from "node:path";
3007
3197
  init_config();
3008
3198
  function typeFromPackageJson(pkgPath) {
3009
3199
  try {
@@ -3025,8 +3215,8 @@ function effectiveType(hookPath) {
3025
3215
  }
3026
3216
  let dir = dirname3(real);
3027
3217
  for (; ; ) {
3028
- const pkg = join24(dir, "package.json");
3029
- if (existsSync19(pkg)) return typeFromPackageJson(pkg);
3218
+ const pkg = join25(dir, "package.json");
3219
+ if (existsSync20(pkg)) return typeFromPackageJson(pkg);
3030
3220
  const parent = dirname3(dir);
3031
3221
  if (parent === dir) return "cjs";
3032
3222
  dir = parent;
@@ -3068,15 +3258,15 @@ function safeRead(path) {
3068
3258
  }
3069
3259
  }
3070
3260
  function reportHookScopeCheck(section2) {
3071
- const hooksDir = join24(claudeHome(), "hooks");
3072
- if (!existsSync19(hooksDir)) {
3261
+ const hooksDir = join25(claudeHome(), "hooks");
3262
+ if (!existsSync20(hooksDir)) {
3073
3263
  addItem(section2, `${dim(infoGlyph)} no ~/.claude/hooks; skipping module-scope check`);
3074
3264
  return;
3075
3265
  }
3076
3266
  let anyWarn = false;
3077
3267
  for (const name of safeReaddir2(hooksDir)) {
3078
3268
  if (extname(name) !== ".js") continue;
3079
- const abs = join24(hooksDir, name);
3269
+ const abs = join25(hooksDir, name);
3080
3270
  const eff = effectiveType(abs);
3081
3271
  if (eff === null) continue;
3082
3272
  const src = safeRead(abs);
@@ -3096,8 +3286,8 @@ function reportHookScopeCheck(section2) {
3096
3286
 
3097
3287
  // src/commands.doctor.checks.hooks.ts
3098
3288
  init_color();
3099
- import { existsSync as existsSync20 } from "node:fs";
3100
- import { join as join25 } from "node:path";
3289
+ import { existsSync as existsSync21 } from "node:fs";
3290
+ import { join as join26 } from "node:path";
3101
3291
  init_config();
3102
3292
  function expandHome(token) {
3103
3293
  const h2 = home();
@@ -3136,7 +3326,7 @@ function checkEventGroups(section2, event, groups) {
3136
3326
  for (const group of groups) {
3137
3327
  for (const cmd of commandsFromGroup(group)) {
3138
3328
  for (const resolved of claudePathsIn(cmd)) {
3139
- if (existsSync20(resolved)) continue;
3329
+ if (existsSync21(resolved)) continue;
3140
3330
  addItem(
3141
3331
  section2,
3142
3332
  `${red(failGlyph)} hooks/${event}: command target missing: ${resolved} (run nomad pull)`
@@ -3149,8 +3339,8 @@ function checkEventGroups(section2, event, groups) {
3149
3339
  return anyFail;
3150
3340
  }
3151
3341
  function reportHooksTargetCheck(section2) {
3152
- const settingsPath = join25(claudeHome(), "settings.json");
3153
- if (!existsSync20(settingsPath)) {
3342
+ const settingsPath = join26(claudeHome(), "settings.json");
3343
+ if (!existsSync21(settingsPath)) {
3154
3344
  addItem(section2, `${dim(infoGlyph)} no ~/.claude/settings.json; skipping hook target check`);
3155
3345
  return;
3156
3346
  }
@@ -3173,12 +3363,12 @@ function reportHooksTargetCheck(section2) {
3173
3363
 
3174
3364
  // src/commands.doctor.checks.hooks.preserve-symlinks.ts
3175
3365
  init_color();
3176
- import { existsSync as existsSync22, readFileSync as readFileSync7 } from "node:fs";
3177
- import { join as join27 } from "node:path";
3366
+ import { existsSync as existsSync23, readFileSync as readFileSync7 } from "node:fs";
3367
+ import { join as join28 } from "node:path";
3178
3368
 
3179
3369
  // src/commands.doctor.checks.hooks.preserve-symlinks.probe.ts
3180
- import { closeSync as closeSync3, existsSync as existsSync21, openSync as openSync3, readSync, realpathSync as realpathSync3 } from "node:fs";
3181
- import { dirname as dirname4, join as join26, resolve as resolve2 } from "node:path";
3370
+ import { closeSync as closeSync3, existsSync as existsSync22, openSync as openSync3, readSync, realpathSync as realpathSync3 } from "node:fs";
3371
+ import { dirname as dirname4, join as join27, resolve as resolve2 } from "node:path";
3182
3372
  function suppressedRanges(src) {
3183
3373
  const ranges = [];
3184
3374
  const re = /\/\*[\s\S]*?\*\/|\/\/[^\n]*|'[^']*'|"[^"]*"|`[^`]*`/g;
@@ -3210,12 +3400,12 @@ function topRelativeSpecifiers(src) {
3210
3400
  }
3211
3401
  function specifierIsMissing(specifier, baseDir) {
3212
3402
  const base = resolve2(baseDir, specifier);
3213
- if (existsSync21(base)) return false;
3403
+ if (existsSync22(base)) return false;
3214
3404
  for (const ext of [".js", ".cjs", ".mjs"]) {
3215
- if (existsSync21(base + ext)) return false;
3405
+ if (existsSync22(base + ext)) return false;
3216
3406
  }
3217
3407
  for (const idx of ["index.js", "index.cjs", "index.mjs"]) {
3218
- if (existsSync21(join26(base, idx))) return false;
3408
+ if (existsSync22(join27(base, idx))) return false;
3219
3409
  }
3220
3410
  return true;
3221
3411
  }
@@ -3270,8 +3460,8 @@ function commandTokens(command) {
3270
3460
  return tokens;
3271
3461
  }
3272
3462
  function readPathMapSafe() {
3273
- const mapPath = join27(repoHome(), "path-map.json");
3274
- if (!existsSync22(mapPath)) return { projects: {} };
3463
+ const mapPath = join28(repoHome(), "path-map.json");
3464
+ if (!existsSync23(mapPath)) return { projects: {} };
3275
3465
  try {
3276
3466
  return JSON.parse(readFileSync7(mapPath, "utf8"));
3277
3467
  } catch {
@@ -3344,8 +3534,8 @@ function checkEventForPreserveSymlinks(section2, event, groups, sharedLinkNames)
3344
3534
  return anyWarn;
3345
3535
  }
3346
3536
  function reportPreserveSymlinksCheck(section2) {
3347
- const settingsPath = join27(claudeHome(), "settings.json");
3348
- if (!existsSync22(settingsPath)) {
3537
+ const settingsPath = join28(claudeHome(), "settings.json");
3538
+ if (!existsSync23(settingsPath)) {
3349
3539
  addItem(
3350
3540
  section2,
3351
3541
  `${dim(infoGlyph)} no ~/.claude/settings.json; skipping preserve-symlinks-main check`
@@ -3378,8 +3568,8 @@ function reportPreserveSymlinksCheck(section2) {
3378
3568
 
3379
3569
  // src/commands.doctor.checks.settings-drift.ts
3380
3570
  init_color();
3381
- import { existsSync as existsSync23, readFileSync as readFileSync8 } from "node:fs";
3382
- import { join as join28 } from "node:path";
3571
+ import { existsSync as existsSync24, readFileSync as readFileSync8 } from "node:fs";
3572
+ import { join as join29 } from "node:path";
3383
3573
  init_config();
3384
3574
  init_utils_json();
3385
3575
  function diffMergedSettings(merged, settings) {
@@ -3397,7 +3587,7 @@ function tryReadJson(filePath) {
3397
3587
  }
3398
3588
  }
3399
3589
  function reportHooksBaseSelfCleanNote(section2) {
3400
- const basePath = join28(repoHome(), "shared", "settings.base.json");
3590
+ const basePath = join29(repoHome(), "shared", "settings.base.json");
3401
3591
  const base = tryReadJson(basePath);
3402
3592
  if (base === null) return;
3403
3593
  if (!baseHasGsdHookEntries(base)) return;
@@ -3410,14 +3600,14 @@ function reportSettingsDriftCheck(section2) {
3410
3600
  const claude = claudeHome();
3411
3601
  const repo = repoHome();
3412
3602
  const host = HOST;
3413
- const settingsPath = join28(claude, "settings.json");
3414
- const basePath = join28(repo, "shared", "settings.base.json");
3415
- const hostPath = join28(repo, "hosts", `${host}.json`);
3416
- if (!existsSync23(settingsPath)) {
3603
+ const settingsPath = join29(claude, "settings.json");
3604
+ const basePath = join29(repo, "shared", "settings.base.json");
3605
+ const hostPath = join29(repo, "hosts", `${host}.json`);
3606
+ if (!existsSync24(settingsPath)) {
3417
3607
  addItem(section2, `${dim(infoGlyph)} no ~/.claude/settings.json; skipping merge-drift check`);
3418
3608
  return;
3419
3609
  }
3420
- if (!existsSync23(basePath)) {
3610
+ if (!existsSync24(basePath)) {
3421
3611
  addItem(
3422
3612
  section2,
3423
3613
  `${dim(infoGlyph)} shared/settings.base.json missing; skipping merge-drift check`
@@ -3436,7 +3626,7 @@ function reportSettingsDriftCheck(section2) {
3436
3626
  if (settings === null) {
3437
3627
  return;
3438
3628
  }
3439
- const hostExists = existsSync23(hostPath);
3629
+ const hostExists = existsSync24(hostPath);
3440
3630
  const hostObj = hostExists ? tryReadJson(hostPath) : null;
3441
3631
  if (hostExists && hostObj === null) {
3442
3632
  addItem(
@@ -3594,14 +3784,14 @@ function reportNodeEngineCheck(section2) {
3594
3784
 
3595
3785
  // src/spinner.ts
3596
3786
  init_color();
3597
- import { existsSync as existsSync27 } from "node:fs";
3787
+ import { existsSync as existsSync28 } from "node:fs";
3598
3788
  import { fileURLToPath as fileURLToPath4 } from "node:url";
3599
3789
  import { Worker } from "node:worker_threads";
3600
3790
 
3601
3791
  // src/commands.push.recovery.ts
3602
3792
  init_config();
3603
3793
  import { readFileSync as readFileSync13, rmSync as rmSync10, writeFileSync as writeFileSync5 } from "node:fs";
3604
- import { join as join33 } from "node:path";
3794
+ import { join as join34 } from "node:path";
3605
3795
  import { createInterface as createInterface2 } from "node:readline/promises";
3606
3796
 
3607
3797
  // src/commands.push.recovery.actions.ts
@@ -3612,25 +3802,25 @@ import { isAbsolute as isAbsolute2, resolve as resolve3, sep as sep5 } from "nod
3612
3802
  // src/commands.push.recovery.redact.ts
3613
3803
  init_config();
3614
3804
  init_config_sharedDirs_guard();
3615
- import { cpSync as cpSync5, existsSync as existsSync26, mkdirSync as mkdirSync6, statSync as statSync7 } from "node:fs";
3616
- import { dirname as dirname6, join as join31, sep as sep4 } from "node:path";
3805
+ import { cpSync as cpSync5, existsSync as existsSync27, mkdirSync as mkdirSync6, statSync as statSync7 } from "node:fs";
3806
+ import { dirname as dirname6, join as join32, sep as sep4 } from "node:path";
3617
3807
 
3618
3808
  // src/commands.redact.ts
3619
3809
  init_config();
3620
- import { existsSync as existsSync25, statSync as statSync6 } from "node:fs";
3621
- import { dirname as dirname5, join as join30 } from "node:path";
3810
+ import { existsSync as existsSync26, statSync as statSync6 } from "node:fs";
3811
+ import { dirname as dirname5, join as join31 } from "node:path";
3622
3812
 
3623
3813
  // src/commands.redact.subtree.ts
3624
- import { existsSync as existsSync24, lstatSync as lstatSync8, readFileSync as readFileSync11, readdirSync as readdirSync9, statSync as statSync5, writeFileSync as writeFileSync4 } from "node:fs";
3625
- import { join as join29 } from "node:path";
3814
+ import { existsSync as existsSync25, lstatSync as lstatSync8, readFileSync as readFileSync11, readdirSync as readdirSync9, statSync as statSync5, writeFileSync as writeFileSync4 } from "node:fs";
3815
+ import { join as join30 } from "node:path";
3626
3816
  init_utils_fs();
3627
3817
  init_utils();
3628
3818
  function collectFiles(dir, out) {
3629
- if (!existsSync24(dir)) return;
3819
+ if (!existsSync25(dir)) return;
3630
3820
  const st = lstatSync8(dir);
3631
3821
  if (!st.isDirectory()) return;
3632
3822
  for (const entry of readdirSync9(dir)) {
3633
- const abs = join29(dir, entry);
3823
+ const abs = join30(dir, entry);
3634
3824
  const lst = lstatSync8(abs);
3635
3825
  if (lst.isSymbolicLink()) continue;
3636
3826
  if (lst.isDirectory()) {
@@ -3682,10 +3872,10 @@ function applySubtreeRedactions(mainPath, mainFindings, subtreeFiles, rule, ts,
3682
3872
 
3683
3873
  // src/commands.pushed-history.ts
3684
3874
  init_utils();
3685
- import { execFileSync as execFileSync8 } from "node:child_process";
3875
+ import { execFileSync as execFileSync10 } from "node:child_process";
3686
3876
  function pushedRef(repo) {
3687
3877
  try {
3688
- const ref = execFileSync8("git", ["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"], {
3878
+ const ref = execFileSync10("git", ["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"], {
3689
3879
  cwd: repo,
3690
3880
  stdio: ["ignore", "pipe", "ignore"]
3691
3881
  }).toString().trim();
@@ -3698,7 +3888,7 @@ function sessionInPushedHistory(id, repo) {
3698
3888
  const ref = pushedRef(repo);
3699
3889
  if (ref === null) return false;
3700
3890
  try {
3701
- const out = execFileSync8(
3891
+ const out = execFileSync10(
3702
3892
  "git",
3703
3893
  [
3704
3894
  "log",
@@ -3735,15 +3925,15 @@ init_utils_json();
3735
3925
  init_utils();
3736
3926
  function resolveLiveTranscript(id) {
3737
3927
  try {
3738
- const mapPath = join30(repoHome(), "path-map.json");
3739
- if (!existsSync25(mapPath)) return null;
3928
+ const mapPath = join31(repoHome(), "path-map.json");
3929
+ if (!existsSync26(mapPath)) return null;
3740
3930
  const projects = readJson(mapPath).projects;
3741
3931
  const claude = claudeHome();
3742
3932
  for (const hostMap of Object.values(projects)) {
3743
3933
  const abs = hostMap[HOST];
3744
3934
  if (abs === void 0) continue;
3745
- const live = join30(claude, "projects", encodePath(abs), `${id}.jsonl`);
3746
- if (existsSync25(live)) return live;
3935
+ const live = join31(claude, "projects", encodePath(abs), `${id}.jsonl`);
3936
+ if (existsSync26(live)) return live;
3747
3937
  }
3748
3938
  return null;
3749
3939
  } catch {
@@ -3763,17 +3953,17 @@ function cmdRedact(opts, nowMs = Date.now, scan = scanFile) {
3763
3953
  }
3764
3954
  const repo = repoHome();
3765
3955
  const backup = backupBase();
3766
- if (!existsSync25(repo)) die(`repo not cloned at ${repo}`);
3956
+ if (!existsSync26(repo)) die(`repo not cloned at ${repo}`);
3767
3957
  const handle = acquireLock("redact");
3768
3958
  if (handle === null) process.exit(0);
3769
3959
  try {
3770
3960
  const localPath = resolveLiveTranscript(id);
3771
- if (localPath === null || !existsSync25(localPath)) {
3961
+ if (localPath === null || !existsSync26(localPath)) {
3772
3962
  fail(`could not resolve local transcript for session ${id} on this host`);
3773
3963
  process.exitCode = 1;
3774
3964
  return;
3775
3965
  }
3776
- const sessionDir = join30(dirname5(localPath), id);
3966
+ const sessionDir = join31(dirname5(localPath), id);
3777
3967
  const subtreeFiles = listSubtreeFiles(sessionDir);
3778
3968
  const subtreeMtime = newestSubtreeMtimeMs(localPath, subtreeFiles, (p) => statSync6(p).mtimeMs);
3779
3969
  if (isRecentlyModified(subtreeMtime, nowMs())) {
@@ -3889,8 +4079,8 @@ function resolveStagedDir(localPath, map, claude, repo) {
3889
4079
  assertSafeLogical(logical);
3890
4080
  const abs = hostMap[HOST];
3891
4081
  if (abs === void 0) continue;
3892
- if (localPath.startsWith(join31(claude, "projects", encodePath(abs)) + sep4)) {
3893
- return join31(repo, "shared", "projects", logical);
4082
+ if (localPath.startsWith(join32(claude, "projects", encodePath(abs)) + sep4)) {
4083
+ return join32(repo, "shared", "projects", logical);
3894
4084
  }
3895
4085
  }
3896
4086
  return null;
@@ -3900,7 +4090,7 @@ function preflightRedactable(f, map, nowMs) {
3900
4090
  if (sid === null) return "a finding has no resolvable session id (not a session transcript)";
3901
4091
  const localPath = resolveLiveTranscript(sid);
3902
4092
  if (localPath === null) return `session ${sid}: local transcript not found`;
3903
- const sessionDir = join31(dirname6(localPath), sid);
4093
+ const sessionDir = join32(dirname6(localPath), sid);
3904
4094
  const subtreeFiles = listSubtreeFiles(sessionDir);
3905
4095
  const subtreeMtime = newestSubtreeMtimeMs(localPath, subtreeFiles, (p) => statSync7(p).mtimeMs);
3906
4096
  if (isRecentlyModified(subtreeMtime, nowMs())) {
@@ -3930,7 +4120,7 @@ function applyRedact(f, ts, map, nowMs, scan = scanFile) {
3930
4120
  `could not locate the local transcript for session ${sid}; choose Skip or Drop session.`
3931
4121
  );
3932
4122
  }
3933
- const sessionDir = join31(dirname6(localPath), sid);
4123
+ const sessionDir = join32(dirname6(localPath), sid);
3934
4124
  const subtreeFiles = listSubtreeFiles(sessionDir);
3935
4125
  const subtreeMtime = newestSubtreeMtimeMs(localPath, subtreeFiles, (p) => statSync7(p).mtimeMs);
3936
4126
  if (isRecentlyModified(subtreeMtime, nowMs())) {
@@ -3964,9 +4154,9 @@ function applyRedact(f, ts, map, nowMs, scan = scanFile) {
3964
4154
  );
3965
4155
  }
3966
4156
  mkdirSync6(stagedProjectDir, { recursive: true });
3967
- cpSync5(localPath, join31(stagedProjectDir, `${sid}.jsonl`), { force: true });
3968
- if (existsSync26(sessionDir)) {
3969
- cpSync5(sessionDir, join31(stagedProjectDir, sid), { force: true, recursive: true });
4157
+ cpSync5(localPath, join32(stagedProjectDir, `${sid}.jsonl`), { force: true });
4158
+ if (existsSync27(sessionDir)) {
4159
+ cpSync5(sessionDir, join32(stagedProjectDir, sid), { force: true, recursive: true });
3970
4160
  }
3971
4161
  return true;
3972
4162
  }
@@ -3974,14 +4164,14 @@ function applyRedact(f, ts, map, nowMs, scan = scanFile) {
3974
4164
  // src/commands.push.recovery.drop.ts
3975
4165
  init_config();
3976
4166
  import { rmSync as rmSync9 } from "node:fs";
3977
- import { join as join32 } from "node:path";
4167
+ import { join as join33 } from "node:path";
3978
4168
  function dropSessionFromStaged(sid, map) {
3979
4169
  const logicals = Object.keys(map.projects);
3980
4170
  if (logicals.length === 0) return false;
3981
4171
  const repo = repoHome();
3982
4172
  for (const logical of logicals) {
3983
- const jsonl = join32(repo, "shared", "projects", logical, `${sid}.jsonl`);
3984
- const dir = join32(repo, "shared", "projects", logical, sid);
4173
+ const jsonl = join33(repo, "shared", "projects", logical, `${sid}.jsonl`);
4174
+ const dir = join33(repo, "shared", "projects", logical, sid);
3985
4175
  rmSync9(jsonl, { force: true });
3986
4176
  rmSync9(dir, { recursive: true, force: true });
3987
4177
  }
@@ -4138,7 +4328,7 @@ function applyThenRescan(scanVerdict, repoHome2) {
4138
4328
  return next;
4139
4329
  }
4140
4330
  function allowThenRescan(append, scanVerdict, repoHome2) {
4141
- const ignPath = join33(repoHome2, ".gitleaksignore");
4331
+ const ignPath = join34(repoHome2, ".gitleaksignore");
4142
4332
  let before;
4143
4333
  try {
4144
4334
  before = readFileSync13(ignPath, "utf8");
@@ -4237,7 +4427,7 @@ function writeAnimatedDone(out, label, ms, useTTY) {
4237
4427
  `);
4238
4428
  }
4239
4429
  function resolveWorkerPath(deps = {}) {
4240
- const check = deps.existsSyncFn ?? existsSync27;
4430
+ const check = deps.existsSyncFn ?? existsSync28;
4241
4431
  const base = deps.baseUrl ?? import.meta.url;
4242
4432
  const mjs = fileURLToPath4(new URL("./nomad.worker.mjs", base));
4243
4433
  if (check(mjs)) return mjs;
@@ -4303,9 +4493,9 @@ function withSpinner(label, fn, deps) {
4303
4493
 
4304
4494
  // src/commands.doctor.gitleaks-version.ts
4305
4495
  init_color();
4306
- import { execFileSync as execFileSync9 } from "node:child_process";
4307
- import { existsSync as existsSync28 } from "node:fs";
4308
- import { join as join34 } from "node:path";
4496
+ import { execFileSync as execFileSync11 } from "node:child_process";
4497
+ import { existsSync as existsSync29 } from "node:fs";
4498
+ import { join as join35 } from "node:path";
4309
4499
  init_config();
4310
4500
  var SEMVER_MAJOR_MINOR = /^(\d+)\.(\d+)\.\d+$/;
4311
4501
  var GITLEAKS_TIMEOUT_MS = 5e3;
@@ -4314,7 +4504,7 @@ function majorMinorOf(value) {
4314
4504
  return m === null ? null : [m[1], m[2]];
4315
4505
  }
4316
4506
  function readGitleaksVersion(run, tomlExists) {
4317
- const tomlPath = join34(repoHome(), ".gitleaks.toml");
4507
+ const tomlPath = join35(repoHome(), ".gitleaks.toml");
4318
4508
  const args = ["version"];
4319
4509
  if (tomlExists(tomlPath)) args.push("--config", tomlPath);
4320
4510
  try {
@@ -4326,7 +4516,7 @@ function readGitleaksVersion(run, tomlExists) {
4326
4516
  return null;
4327
4517
  }
4328
4518
  }
4329
- function reportGitleaksVersionCheck(section2, run = execFileSync9, tomlExists = existsSync28) {
4519
+ function reportGitleaksVersionCheck(section2, run = execFileSync11, tomlExists = existsSync29) {
4330
4520
  const raw = readGitleaksVersion(run, tomlExists);
4331
4521
  if (raw === null) return;
4332
4522
  const local = majorMinorOf(raw);
@@ -4346,7 +4536,7 @@ function reportGitleaksVersionCheck(section2, run = execFileSync9, tomlExists =
4346
4536
 
4347
4537
  // src/commands.doctor.checks.deps.ts
4348
4538
  init_color();
4349
- import { execFileSync as execFileSync10 } from "node:child_process";
4539
+ import { execFileSync as execFileSync12 } from "node:child_process";
4350
4540
  var VERSION_TOKEN = /(\d{1,9}\.\d{1,9}\.\d{1,9})/;
4351
4541
  var PROBE_TIMEOUT_MS = 3e3;
4352
4542
  var FETCHER_BASE = "HTTP fetcher";
@@ -4383,7 +4573,7 @@ function reportFetcherRow(section2, run) {
4383
4573
  );
4384
4574
  }
4385
4575
  }
4386
- function reportOptionalDeps(section2, run = execFileSync10) {
4576
+ function reportOptionalDeps(section2, run = execFileSync12) {
4387
4577
  const gh = probeOptionalDep("gh", run);
4388
4578
  if (gh.status === "present") {
4389
4579
  addItem(section2, `${green(okGlyph)} gh: ${gh.version ?? "present"}`);
@@ -4398,11 +4588,11 @@ function reportOptionalDeps(section2, run = execFileSync10) {
4398
4588
 
4399
4589
  // src/commands.doctor.actions-drift.ts
4400
4590
  init_color();
4401
- import { execFileSync as execFileSync12 } from "node:child_process";
4591
+ import { execFileSync as execFileSync14 } from "node:child_process";
4402
4592
  init_config();
4403
4593
 
4404
4594
  // src/gh-actions.ts
4405
- import { execFileSync as execFileSync11 } from "node:child_process";
4595
+ import { execFileSync as execFileSync13 } from "node:child_process";
4406
4596
  var GH_TIMEOUT_MS = 5e3;
4407
4597
  function parseGitHubRemote(remoteUrl) {
4408
4598
  const normalized = remoteUrl.trim().replace(/\/$/, "");
@@ -4410,7 +4600,7 @@ function parseGitHubRemote(remoteUrl) {
4410
4600
  if (m === null) return null;
4411
4601
  return { owner: m[1], repo: m[2] };
4412
4602
  }
4413
- function ghAuthStatus(run = execFileSync11) {
4603
+ function ghAuthStatus(run = execFileSync13) {
4414
4604
  try {
4415
4605
  run("gh", ["auth", "status"], {
4416
4606
  stdio: ["ignore", "ignore", "ignore"],
@@ -4424,7 +4614,7 @@ function ghAuthStatus(run = execFileSync11) {
4424
4614
  return "gh-probe-error";
4425
4615
  }
4426
4616
  }
4427
- function isRepoPrivate(ref, run = execFileSync11) {
4617
+ function isRepoPrivate(ref, run = execFileSync13) {
4428
4618
  const out = run("gh", ["repo", "view", `${ref.owner}/${ref.repo}`, "--json", "isPrivate"], {
4429
4619
  stdio: ["ignore", "pipe", "ignore"],
4430
4620
  timeout: GH_TIMEOUT_MS
@@ -4432,7 +4622,7 @@ function isRepoPrivate(ref, run = execFileSync11) {
4432
4622
  const parsed = JSON.parse(out);
4433
4623
  return parsed.isPrivate === true;
4434
4624
  }
4435
- function isActionsEnabled(ref, run = execFileSync11) {
4625
+ function isActionsEnabled(ref, run = execFileSync13) {
4436
4626
  const out = run(
4437
4627
  "gh",
4438
4628
  ["api", `repos/${ref.owner}/${ref.repo}/actions/permissions`, "--jq", ".enabled"],
@@ -4440,7 +4630,7 @@ function isActionsEnabled(ref, run = execFileSync11) {
4440
4630
  ).toString().trim();
4441
4631
  return out === "true";
4442
4632
  }
4443
- function disableActions(ref, run = execFileSync11) {
4633
+ function disableActions(ref, run = execFileSync13) {
4444
4634
  run(
4445
4635
  "gh",
4446
4636
  [
@@ -4454,7 +4644,7 @@ function disableActions(ref, run = execFileSync11) {
4454
4644
  { stdio: ["ignore", "ignore", "pipe"], timeout: GH_TIMEOUT_MS }
4455
4645
  );
4456
4646
  }
4457
- function readOriginRemote(cwd, run = execFileSync11) {
4647
+ function readOriginRemote(cwd, run = execFileSync13) {
4458
4648
  return run("git", ["remote", "get-url", "origin"], {
4459
4649
  cwd,
4460
4650
  stdio: ["ignore", "pipe", "ignore"]
@@ -4462,7 +4652,7 @@ function readOriginRemote(cwd, run = execFileSync11) {
4462
4652
  }
4463
4653
 
4464
4654
  // src/commands.doctor.actions-drift.ts
4465
- function reportActionsDrift(section2, run = execFileSync12) {
4655
+ function reportActionsDrift(section2, run = execFileSync14) {
4466
4656
  let remote;
4467
4657
  try {
4468
4658
  remote = readOriginRemote(repoHome(), run);
@@ -4519,7 +4709,13 @@ function buildVerdictSection(sections) {
4519
4709
 
4520
4710
  // src/commands.doctor.compact.ts
4521
4711
  init_color();
4522
- var ALWAYS_FULL = /* @__PURE__ */ new Set(["Nomad Version", "Summary", "Shared scan", "Schema scan"]);
4712
+ var ALWAYS_FULL = /* @__PURE__ */ new Set([
4713
+ "Nomad Version",
4714
+ "Summary",
4715
+ "Shared scan",
4716
+ "Schema scan",
4717
+ "Remote check"
4718
+ ]);
4523
4719
  function isProblem(item2) {
4524
4720
  return item2.includes(failGlyph) || item2.includes(warnGlyph);
4525
4721
  }
@@ -4542,8 +4738,8 @@ function gatherDoctorSections(opts) {
4542
4738
  reportHostAndPaths(host);
4543
4739
  reportRepoState(host);
4544
4740
  const links = section("Shared links");
4545
- const mapPath = join35(repoHome(), "path-map.json");
4546
- const rawMap = existsSync29(mapPath) ? readJsonSafe(mapPath, mapPath, links) : null;
4741
+ const mapPath = join36(repoHome(), "path-map.json");
4742
+ const rawMap = existsSync30(mapPath) ? readJsonSafe(mapPath, mapPath, links) : null;
4547
4743
  const map = rawMap ?? { projects: {} };
4548
4744
  reportSharedLinks(links, map);
4549
4745
  reportDroppedNamesMigration(links);
@@ -4561,10 +4757,13 @@ function gatherDoctorSections(opts) {
4561
4757
  reportPathMap(pathMap);
4562
4758
  const neverSync = section("Never-sync");
4563
4759
  reportNeverSync(neverSync);
4760
+ const skills = section("Skills");
4761
+ reportSkillsDivergence(skills);
4564
4762
  const repository = section("Repository");
4565
4763
  const gitleaksReady = reportGitleaksProbe(repository);
4566
4764
  reportGitlinks(repository);
4567
4765
  reportRemote(repository);
4766
+ reportGitIdentity(repository);
4568
4767
  reportRebaseClean(repository);
4569
4768
  reportRebaseState(repository);
4570
4769
  reportOrphanedAutostash(repository);
@@ -4581,6 +4780,8 @@ function gatherDoctorSections(opts) {
4581
4780
  if (opts.checkShared === true) reportCheckShared(sharedScan, gitleaksReady);
4582
4781
  const schemaScan = section("Schema scan");
4583
4782
  if (opts.checkSchema === true) reportCheckSchema(schemaScan);
4783
+ const remoteCheck = section("Remote check");
4784
+ if (opts.checkRemote === true) reportCheckRemote(remoteCheck);
4584
4785
  const body = [
4585
4786
  nomadVersion,
4586
4787
  depVersions,
@@ -4590,10 +4791,12 @@ function gatherDoctorSections(opts) {
4590
4791
  settings,
4591
4792
  pathMap,
4592
4793
  neverSync,
4794
+ skills,
4593
4795
  repository,
4594
4796
  housekeeping,
4595
4797
  sharedScan,
4596
- schemaScan
4798
+ schemaScan,
4799
+ remoteCheck
4597
4800
  ];
4598
4801
  return [...body, buildVerdictSection(body)];
4599
4802
  }
@@ -4618,27 +4821,29 @@ function parseDoctorArgs(args) {
4618
4821
  }
4619
4822
  let checkShared = false;
4620
4823
  let checkSchema = false;
4824
+ let checkRemote = false;
4621
4825
  let verbose = false;
4622
4826
  for (const arg of args) {
4623
4827
  if (arg === "--check-shared") checkShared = true;
4624
4828
  else if (arg === "--check-schema") checkSchema = true;
4829
+ else if (arg === "--check-remote") checkRemote = true;
4625
4830
  else if (arg === "--verbose" || arg === "--all" || arg === "-v") verbose = true;
4626
4831
  else return { kind: "error" };
4627
4832
  }
4628
- return { kind: "run", checkShared, checkSchema, verbose };
4833
+ return { kind: "run", checkShared, checkSchema, checkRemote, verbose };
4629
4834
  }
4630
4835
 
4631
4836
  // src/commands.drop-session.ts
4632
4837
  init_config();
4633
- import { execFileSync as execFileSync14 } from "node:child_process";
4634
- import { existsSync as existsSync31, readdirSync as readdirSync10, statSync as statSync8 } from "node:fs";
4635
- import { join as join37, relative as relative4 } from "node:path";
4838
+ import { execFileSync as execFileSync16 } from "node:child_process";
4839
+ import { existsSync as existsSync32, readdirSync as readdirSync10, statSync as statSync8 } from "node:fs";
4840
+ import { join as join38, relative as relative4 } from "node:path";
4636
4841
 
4637
4842
  // src/commands.drop-session.git.ts
4638
- import { execFileSync as execFileSync13 } from "node:child_process";
4843
+ import { execFileSync as execFileSync15 } from "node:child_process";
4639
4844
  function expandStagedDir(dirRel, repo) {
4640
4845
  try {
4641
- const out = execFileSync13("git", ["ls-files", "-z", "--", dirRel], {
4846
+ const out = execFileSync15("git", ["ls-files", "-z", "--", dirRel], {
4642
4847
  cwd: repo,
4643
4848
  stdio: ["ignore", "pipe", "pipe"]
4644
4849
  });
@@ -4649,7 +4854,7 @@ function expandStagedDir(dirRel, repo) {
4649
4854
  }
4650
4855
  function isTrackedInHead(rel, repo) {
4651
4856
  try {
4652
- execFileSync13("git", ["cat-file", "-e", `HEAD:${rel}`], {
4857
+ execFileSync15("git", ["cat-file", "-e", `HEAD:${rel}`], {
4653
4858
  cwd: repo,
4654
4859
  stdio: ["ignore", "pipe", "pipe"]
4655
4860
  });
@@ -4660,7 +4865,7 @@ function isTrackedInHead(rel, repo) {
4660
4865
  }
4661
4866
  function isInIndex(rel, repo) {
4662
4867
  try {
4663
- const out = execFileSync13("git", ["ls-files", "--", rel], {
4868
+ const out = execFileSync15("git", ["ls-files", "--", rel], {
4664
4869
  cwd: repo,
4665
4870
  stdio: ["ignore", "pipe", "pipe"]
4666
4871
  });
@@ -4674,8 +4879,8 @@ function isInIndex(rel, repo) {
4674
4879
  init_config();
4675
4880
  init_utils();
4676
4881
  init_utils_json();
4677
- import { existsSync as existsSync30 } from "node:fs";
4678
- import { join as join36 } from "node:path";
4882
+ import { existsSync as existsSync31 } from "node:fs";
4883
+ import { join as join37 } from "node:path";
4679
4884
  var SHARED_PROJECT_LOGICAL = /^shared\/projects\/([^/]+)\//;
4680
4885
  function reportScrubHint(id, matches) {
4681
4886
  const live = resolveLiveTranscript2(id, matches);
@@ -4691,8 +4896,8 @@ function reportScrubHint(id, matches) {
4691
4896
  }
4692
4897
  function resolveLiveTranscript2(id, matches) {
4693
4898
  try {
4694
- const mapPath = join36(repoHome(), "path-map.json");
4695
- if (!existsSync30(mapPath)) return null;
4899
+ const mapPath = join37(repoHome(), "path-map.json");
4900
+ if (!existsSync31(mapPath)) return null;
4696
4901
  const projects = readJson(mapPath).projects;
4697
4902
  const claude = claudeHome();
4698
4903
  for (const rel of matches) {
@@ -4700,8 +4905,8 @@ function resolveLiveTranscript2(id, matches) {
4700
4905
  if (logical === void 0) continue;
4701
4906
  const abs = projects[logical]?.[HOST];
4702
4907
  if (abs === void 0) continue;
4703
- const live = join36(claude, "projects", encodePath(abs), `${id}.jsonl`);
4704
- if (existsSync30(live)) return live;
4908
+ const live = join37(claude, "projects", encodePath(abs), `${id}.jsonl`);
4909
+ if (existsSync31(live)) return live;
4705
4910
  }
4706
4911
  return null;
4707
4912
  } catch {
@@ -4717,12 +4922,12 @@ function cmdDropSession(id) {
4717
4922
  process.exit(1);
4718
4923
  }
4719
4924
  const repo = repoHome();
4720
- if (!existsSync31(repo)) die(`repo not cloned at ${repo}`);
4925
+ if (!existsSync32(repo)) die(`repo not cloned at ${repo}`);
4721
4926
  const handle = acquireLock("drop-session");
4722
4927
  if (handle === null) process.exit(0);
4723
4928
  try {
4724
- const repoProjects = join37(repo, "shared", "projects");
4725
- if (!existsSync31(repoProjects)) {
4929
+ const repoProjects = join38(repo, "shared", "projects");
4930
+ if (!existsSync32(repoProjects)) {
4726
4931
  throw new NomadFatal(`no staged session matches ${id}`);
4727
4932
  }
4728
4933
  const matches = collectMatches(repoProjects, id, repo);
@@ -4745,12 +4950,12 @@ function cmdDropSession(id) {
4745
4950
  function collectMatches(repoProjects, id, repo) {
4746
4951
  const matches = [];
4747
4952
  for (const logical of readdirSync10(repoProjects)) {
4748
- const candidate = join37(repoProjects, logical, `${id}.jsonl`);
4749
- if (existsSync31(candidate)) {
4953
+ const candidate = join38(repoProjects, logical, `${id}.jsonl`);
4954
+ if (existsSync32(candidate)) {
4750
4955
  matches.push(relative4(repo, candidate));
4751
4956
  }
4752
- const dir = join37(repoProjects, logical, id);
4753
- if (existsSync31(dir) && statSync8(dir).isDirectory()) {
4957
+ const dir = join38(repoProjects, logical, id);
4958
+ if (existsSync32(dir) && statSync8(dir).isDirectory()) {
4754
4959
  const dirRel = relative4(repo, dir);
4755
4960
  const staged = expandStagedDir(dirRel, repo);
4756
4961
  if (staged.length > 0) matches.push(...staged);
@@ -4766,12 +4971,12 @@ function unstageOne(rel, repo) {
4766
4971
  }
4767
4972
  try {
4768
4973
  if (isTrackedInHead(rel, repo)) {
4769
- execFileSync14("git", ["restore", "--staged", "--worktree", "--", rel], {
4974
+ execFileSync16("git", ["restore", "--staged", "--worktree", "--", rel], {
4770
4975
  cwd: repo,
4771
4976
  stdio: ["ignore", "pipe", "pipe"]
4772
4977
  });
4773
4978
  } else {
4774
- execFileSync14("git", ["rm", "--cached", "-f", "--", rel], {
4979
+ execFileSync16("git", ["rm", "--cached", "-f", "--", rel], {
4775
4980
  cwd: repo,
4776
4981
  stdio: ["ignore", "pipe", "pipe"]
4777
4982
  });
@@ -4785,8 +4990,8 @@ function unstageOne(rel, repo) {
4785
4990
  }
4786
4991
 
4787
4992
  // src/commands.pull.ts
4788
- import { existsSync as existsSync37, mkdirSync as mkdirSync9 } from "node:fs";
4789
- import { join as join44 } from "node:path";
4993
+ import { existsSync as existsSync38, mkdirSync as mkdirSync9 } from "node:fs";
4994
+ import { join as join45 } from "node:path";
4790
4995
 
4791
4996
  // src/commands.push.sections.ts
4792
4997
  init_color();
@@ -4881,55 +5086,20 @@ init_config();
4881
5086
 
4882
5087
  // src/extras-sync.ts
4883
5088
  init_config();
4884
- import { existsSync as existsSync34 } from "node:fs";
4885
- import { join as join41 } from "node:path";
4886
-
4887
- // src/extras-sync.diff.ts
4888
- init_utils();
4889
- import { execFileSync as execFileSync15 } from "node:child_process";
4890
- function labelDiffLine(line) {
4891
- const tab = line.indexOf(" ");
4892
- if (tab === -1) return line;
4893
- const status = line.slice(0, tab);
4894
- const path = line.slice(tab + 1);
4895
- if (status === "D") return `${path} (local only)`;
4896
- if (status === "A") return `${path} (repo only)`;
4897
- return path;
4898
- }
4899
- function parseDiffOutput(stdout) {
4900
- return stdout.split("\n").filter((line) => line.length > 0).map(labelDiffLine);
4901
- }
4902
- function listDivergingFiles(a, b) {
4903
- try {
4904
- const stdout = execFileSync15("git", ["diff", "--no-index", "--name-status", a, b], {
4905
- stdio: ["ignore", "pipe", "pipe"]
4906
- }).toString();
4907
- return parseDiffOutput(stdout);
4908
- } catch (err) {
4909
- const e = err;
4910
- if (e.status === 1 && e.stdout !== void 0) {
4911
- return parseDiffOutput(e.stdout.toString());
4912
- }
4913
- if (e.code === "ENOENT") {
4914
- warn(`git not on PATH; divergence check skipped for ${a}`);
4915
- return [];
4916
- }
4917
- warn(`divergence check failed for ${a}: ${e.message ?? String(err)}`);
4918
- return [];
4919
- }
4920
- }
5089
+ import { existsSync as existsSync35 } from "node:fs";
5090
+ import { join as join42 } from "node:path";
4921
5091
 
4922
5092
  // src/extras-sync.core.ts
4923
5093
  init_config();
4924
- import { cpSync as cpSync6, existsSync as existsSync32, lstatSync as lstatSync9, readdirSync as readdirSync11, rmSync as rmSync11 } from "node:fs";
4925
- import { basename, join as join38 } from "node:path";
5094
+ import { cpSync as cpSync6, existsSync as existsSync33, lstatSync as lstatSync9, readdirSync as readdirSync11, rmSync as rmSync11 } from "node:fs";
5095
+ import { basename, join as join39 } from "node:path";
4926
5096
  init_utils();
4927
5097
  init_utils_json();
4928
5098
  function loadValidatedExtras(opts) {
4929
5099
  const repo = repoHome();
4930
- const mapPath = join38(repo, "path-map.json");
4931
- const repoExtras = join38(repo, "shared", "extras");
4932
- if (!existsSync32(mapPath) || opts.requireRepoExtras === true && !existsSync32(repoExtras)) {
5100
+ const mapPath = join39(repo, "path-map.json");
5101
+ const repoExtras = join39(repo, "shared", "extras");
5102
+ if (!existsSync33(mapPath) || opts.requireRepoExtras === true && !existsSync33(repoExtras)) {
4933
5103
  if (opts.missingMsg !== void 0) log(opts.missingMsg);
4934
5104
  return null;
4935
5105
  }
@@ -4961,16 +5131,16 @@ function* eachExtrasTarget(v, counts) {
4961
5131
  }
4962
5132
  }
4963
5133
  function stripCollidingDstSymlinks(src, dst, isExcluded) {
4964
- if (!existsSync32(dst)) return;
5134
+ if (!existsSync33(dst)) return;
4965
5135
  for (const name of readdirSync11(src)) {
4966
5136
  if (isExcluded(name)) continue;
4967
- const dstPath = join38(dst, name);
5137
+ const dstPath = join39(dst, name);
4968
5138
  const dstStat = lstatSync9(dstPath, { throwIfNoEntry: false });
4969
5139
  if (dstStat === void 0) continue;
4970
5140
  if (dstStat.isSymbolicLink()) {
4971
5141
  rmSync11(dstPath, { recursive: true, force: true });
4972
- } else if (dstStat.isDirectory() && lstatSync9(join38(src, name)).isDirectory()) {
4973
- stripCollidingDstSymlinks(join38(src, name), dstPath, isExcluded);
5142
+ } else if (dstStat.isDirectory() && lstatSync9(join39(src, name)).isDirectory()) {
5143
+ stripCollidingDstSymlinks(join39(src, name), dstPath, isExcluded);
4974
5144
  }
4975
5145
  }
4976
5146
  }
@@ -5012,15 +5182,15 @@ function copyExtrasFiltered(src, dst, blockSet) {
5012
5182
  function prunePreservingDenied(src, dst, blockSet) {
5013
5183
  for (const name of readdirSync11(dst)) {
5014
5184
  if (isDeniedName(blockSet, name)) continue;
5015
- const dstPath = join38(dst, name);
5016
- const srcStat = lstatSync9(join38(src, name), { throwIfNoEntry: false });
5185
+ const dstPath = join39(dst, name);
5186
+ const srcStat = lstatSync9(join39(src, name), { throwIfNoEntry: false });
5017
5187
  if (srcStat === void 0) {
5018
5188
  rmSync11(dstPath, { recursive: true, force: true });
5019
5189
  continue;
5020
5190
  }
5021
5191
  const dstStat = lstatSync9(dstPath);
5022
5192
  if (srcStat.isDirectory() && dstStat.isDirectory()) {
5023
- prunePreservingDenied(join38(src, name), dstPath, blockSet);
5193
+ prunePreservingDenied(join39(src, name), dstPath, blockSet);
5024
5194
  } else if (srcStat.isDirectory() !== dstStat.isDirectory()) {
5025
5195
  rmSync11(dstPath, { recursive: true, force: true });
5026
5196
  }
@@ -5043,15 +5213,15 @@ function copyExtrasFilteredPreserving(src, dst, blockSet) {
5043
5213
  function prunePreservingBy(src, dst, isPreserved) {
5044
5214
  for (const name of readdirSync11(dst)) {
5045
5215
  if (isPreserved(name)) continue;
5046
- const dstPath = join38(dst, name);
5047
- const srcStat = lstatSync9(join38(src, name), { throwIfNoEntry: false });
5216
+ const dstPath = join39(dst, name);
5217
+ const srcStat = lstatSync9(join39(src, name), { throwIfNoEntry: false });
5048
5218
  if (srcStat === void 0) {
5049
5219
  rmSync11(dstPath, { recursive: true, force: true });
5050
5220
  continue;
5051
5221
  }
5052
5222
  const dstStat = lstatSync9(dstPath);
5053
5223
  if (srcStat.isDirectory() && dstStat.isDirectory()) {
5054
- prunePreservingBy(join38(src, name), dstPath, isPreserved);
5224
+ prunePreservingBy(join39(src, name), dstPath, isPreserved);
5055
5225
  } else if (srcStat.isDirectory() !== dstStat.isDirectory()) {
5056
5226
  rmSync11(dstPath, { recursive: true, force: true });
5057
5227
  }
@@ -5078,11 +5248,11 @@ init_utils_json();
5078
5248
 
5079
5249
  // src/extras-sync.remap.ts
5080
5250
  init_config();
5081
- import { existsSync as existsSync33, mkdirSync as mkdirSync7, readdirSync as readdirSync12, realpathSync as realpathSync4, rmSync as rmSync12 } from "node:fs";
5082
- import { dirname as dirname7, join as join40, sep as sep7 } from "node:path";
5251
+ import { existsSync as existsSync34, mkdirSync as mkdirSync7, readdirSync as readdirSync12, realpathSync as realpathSync4, rmSync as rmSync12 } from "node:fs";
5252
+ import { dirname as dirname7, join as join41, sep as sep7 } from "node:path";
5083
5253
 
5084
5254
  // src/extras-sync.planning-diff.ts
5085
- import { join as join39, normalize as normalize2, sep as sep6 } from "node:path";
5255
+ import { join as join40, normalize as normalize2, sep as sep6 } from "node:path";
5086
5256
  init_utils();
5087
5257
  function processRecord(fields, i, changed, deleted) {
5088
5258
  const status = fields[i];
@@ -5134,7 +5304,7 @@ function planningDeleteTargets(opts) {
5134
5304
  const { deleted } = parsePlanningDiff(raw);
5135
5305
  const logicalPrefix = "shared/extras/" + logical + "/";
5136
5306
  const prefix = logicalPrefix + ".planning/";
5137
- const planningRoot = join39(localRoot, ".planning");
5307
+ const planningRoot = join40(localRoot, ".planning");
5138
5308
  const planningRootBoundary = planningRoot + sep6;
5139
5309
  const targets = [];
5140
5310
  for (const repoPath of deleted) {
@@ -5142,7 +5312,7 @@ function planningDeleteTargets(opts) {
5142
5312
  continue;
5143
5313
  }
5144
5314
  const remainder = repoPath.slice(logicalPrefix.length);
5145
- const candidate = join39(localRoot, remainder);
5315
+ const candidate = join40(localRoot, remainder);
5146
5316
  const resolved = normalize2(candidate);
5147
5317
  if (!resolved.startsWith(planningRootBoundary)) {
5148
5318
  throw new NomadFatal(
@@ -5163,7 +5333,7 @@ function runExtrasOp(v, dryRun, paths, backup, copy) {
5163
5333
  const would = [];
5164
5334
  for (const t of eachExtrasTarget(v, counts)) {
5165
5335
  const { src, dst } = paths(t);
5166
- if (!existsSync33(src)) continue;
5336
+ if (!existsSync34(src)) continue;
5167
5337
  const item2 = `${t.logical}/${t.dirname}`;
5168
5338
  if (dryRun) {
5169
5339
  would.push(item2);
@@ -5198,7 +5368,7 @@ function isInsidePlanningRoot(parentReal, rootReal) {
5198
5368
  return parentReal === rootReal || parentReal.startsWith(rootReal + sep7);
5199
5369
  }
5200
5370
  function deletePlanningTarget(target, planningRoot, repoCounterpart) {
5201
- if (existsSync33(repoCounterpart)) return;
5371
+ if (existsSync34(repoCounterpart)) return;
5202
5372
  const parentReal = tryRealpath(dirname7(target));
5203
5373
  if (parentReal === void 0) return;
5204
5374
  const rootReal = tryRealpath(planningRoot);
@@ -5208,7 +5378,7 @@ function deletePlanningTarget(target, planningRoot, repoCounterpart) {
5208
5378
  pruneEmptyAncestors(target, planningRoot);
5209
5379
  }
5210
5380
  function propagatePlanningDeletes(v, ts, prePostHeads, repo) {
5211
- const repoExtras = join40(repo, "shared", "extras");
5381
+ const repoExtras = join41(repo, "shared", "extras");
5212
5382
  for (const t of eachExtrasTarget(v, { unmapped: 0, skipped: 0 })) {
5213
5383
  if (t.dirname !== ".planning") continue;
5214
5384
  let raw;
@@ -5234,11 +5404,11 @@ function propagatePlanningDeletes(v, ts, prePostHeads, repo) {
5234
5404
  }
5235
5405
  const targets = planningDeleteTargets({ raw, logical: t.logical, localRoot: t.localRoot });
5236
5406
  if (targets.length === 0) continue;
5237
- backupExtrasWrite(join40(t.localRoot, t.dirname), ts, t.localRoot);
5238
- const planningRoot = join40(t.localRoot, ".planning");
5407
+ backupExtrasWrite(join41(t.localRoot, t.dirname), ts, t.localRoot);
5408
+ const planningRoot = join41(t.localRoot, ".planning");
5239
5409
  for (const target of targets) {
5240
5410
  const relToLocal = target.slice(t.localRoot.length + sep7.length);
5241
- deletePlanningTarget(target, planningRoot, join40(repoExtras, t.logical, relToLocal));
5411
+ deletePlanningTarget(target, planningRoot, join41(repoExtras, t.logical, relToLocal));
5242
5412
  }
5243
5413
  }
5244
5414
  }
@@ -5247,14 +5417,14 @@ function remapExtrasPush(ts, opts = {}) {
5247
5417
  const v = loadValidatedExtras({ missingMsg: "no path-map.json; skipping extras push" });
5248
5418
  if (v === null) return { unmapped: 0, skipped: 0, pushed: [], wouldPush: [] };
5249
5419
  const repo = repoHome();
5250
- const repoExtras = join40(repo, "shared", "extras");
5420
+ const repoExtras = join41(repo, "shared", "extras");
5251
5421
  if (!dryRun) mkdirSync7(repoExtras, { recursive: true });
5252
5422
  const { unmapped, skipped, done, would } = runExtrasOp(
5253
5423
  v,
5254
5424
  dryRun,
5255
5425
  ({ localRoot, logical, dirname: dirname8 }) => ({
5256
- src: join40(localRoot, dirname8),
5257
- dst: join40(repoExtras, logical, dirname8)
5426
+ src: join41(localRoot, dirname8),
5427
+ dst: join41(repoExtras, logical, dirname8)
5258
5428
  }),
5259
5429
  (dst) => backupRepoWrite(dst, ts, repo),
5260
5430
  // Push copy routing per extra type:
@@ -5283,8 +5453,8 @@ function remapExtrasPull(ts, opts = {}) {
5283
5453
  v,
5284
5454
  dryRun,
5285
5455
  ({ localRoot, logical, dirname: dirname8 }) => ({
5286
- src: join40(repo, "shared", "extras", logical, dirname8),
5287
- dst: join40(localRoot, dirname8)
5456
+ src: join41(repo, "shared", "extras", logical, dirname8),
5457
+ dst: join41(localRoot, dirname8)
5288
5458
  }),
5289
5459
  // Snapshot the host-side dst BEFORE copyExtras clobbers it. Anchor on
5290
5460
  // localRoot so the backup tree mirrors the project layout.
@@ -5316,15 +5486,15 @@ function divergenceCheckExtras(ts) {
5316
5486
  const v = loadValidatedExtras({});
5317
5487
  if (v === null) return;
5318
5488
  const counts = { unmapped: 0, skipped: 0 };
5319
- const backupRoot = join41(backupBase(), ts, "extras");
5489
+ const backupRoot = join42(backupBase(), ts, "extras");
5320
5490
  const repo = repoHome();
5321
5491
  for (const { logical, localRoot, dirname: dirname8 } of eachExtrasTarget(v, counts)) {
5322
- const local = join41(localRoot, dirname8);
5323
- const repoEntry = join41(repo, "shared", "extras", logical, dirname8);
5324
- if (!existsSync34(local) || !existsSync34(repoEntry)) continue;
5492
+ const local = join42(localRoot, dirname8);
5493
+ const repoEntry = join42(repo, "shared", "extras", logical, dirname8);
5494
+ if (!existsSync35(local) || !existsSync35(repoEntry)) continue;
5325
5495
  const diff = listDivergingFiles(local, repoEntry);
5326
5496
  if (diff.length === 0) continue;
5327
- const projectBackupRoot = join41(backupRoot, encodePath(localRoot));
5497
+ const projectBackupRoot = join42(backupRoot, encodePath(localRoot));
5328
5498
  warn(
5329
5499
  `local ${dirname8} for ${logical} diverges from origin in ${diff.length} file(s); next remapExtrasPull will merge changes (.planning overlays, .claude/.CLAUDE.md mirror; backups at ${projectBackupRoot}/)`
5330
5500
  );
@@ -5334,8 +5504,8 @@ function divergenceCheckExtras(ts) {
5334
5504
 
5335
5505
  // src/skills-sync.ts
5336
5506
  init_config();
5337
- import { existsSync as existsSync35, lstatSync as lstatSync10, mkdirSync as mkdirSync8, readdirSync as readdirSync13, rmSync as rmSync13 } from "node:fs";
5338
- import { join as join42 } from "node:path";
5507
+ import { existsSync as existsSync36, lstatSync as lstatSync10, mkdirSync as mkdirSync8, readdirSync as readdirSync13, rmSync as rmSync13 } from "node:fs";
5508
+ import { join as join43 } from "node:path";
5339
5509
  init_utils_fs();
5340
5510
  function isGsdOwned(name) {
5341
5511
  return name.startsWith(GSD_PREFIX);
@@ -5355,9 +5525,9 @@ function copySkillsPull(src, dst) {
5355
5525
  copyExtrasFilteredPreservingBy(src, dst, isSkillExcluded);
5356
5526
  }
5357
5527
  function syncSkillsPull(ts) {
5358
- const sharedSkills = join42(repoHome(), "shared", "skills");
5359
- if (!existsSync35(sharedSkills)) return;
5360
- const localSkills = join42(claudeHome(), "skills");
5528
+ const sharedSkills = join43(repoHome(), "shared", "skills");
5529
+ if (!existsSync36(sharedSkills)) return;
5530
+ const localSkills = join43(claudeHome(), "skills");
5361
5531
  const dstStat = lstatSync10(localSkills, { throwIfNoEntry: false });
5362
5532
  if (dstStat?.isSymbolicLink() === true) {
5363
5533
  backupBeforeWrite(localSkills, ts);
@@ -5367,18 +5537,18 @@ function syncSkillsPull(ts) {
5367
5537
  copySkillsPull(sharedSkills, localSkills);
5368
5538
  }
5369
5539
  function syncSkillsPush() {
5370
- const localSkills = join42(claudeHome(), "skills");
5540
+ const localSkills = join43(claudeHome(), "skills");
5371
5541
  const stat = lstatSync10(localSkills, { throwIfNoEntry: false });
5372
5542
  if (stat === void 0) return;
5373
5543
  if (stat.isSymbolicLink()) return;
5374
- const sharedSkills = join42(repoHome(), "shared", "skills");
5544
+ const sharedSkills = join43(repoHome(), "shared", "skills");
5375
5545
  copySkillsPush(localSkills, sharedSkills);
5376
5546
  }
5377
5547
 
5378
5548
  // src/preview.ts
5379
5549
  init_config();
5380
- import { existsSync as existsSync36 } from "node:fs";
5381
- import { join as join43 } from "node:path";
5550
+ import { existsSync as existsSync37 } from "node:fs";
5551
+ import { join as join44 } from "node:path";
5382
5552
 
5383
5553
  // node_modules/diff/libesm/diff/base.js
5384
5554
  var Diff = class {
@@ -5664,7 +5834,7 @@ function diffJsonStrings(currentJsonText, newJsonText) {
5664
5834
  return lines.join("\n");
5665
5835
  }
5666
5836
  function readJsonOrNull(path) {
5667
- if (!existsSync36(path)) return null;
5837
+ if (!existsSync37(path)) return null;
5668
5838
  try {
5669
5839
  return readJson(path);
5670
5840
  } catch {
@@ -5678,12 +5848,12 @@ function previewSettings(basePath, hostPath, settingsPath) {
5678
5848
  }
5679
5849
  const notes = [];
5680
5850
  const hostOverrides = readJsonOrNull(hostPath);
5681
- if (hostOverrides === null && existsSync36(hostPath)) {
5851
+ if (hostOverrides === null && existsSync37(hostPath)) {
5682
5852
  notes.push(`malformed hosts/${HOST}.json; ignoring overrides`);
5683
5853
  }
5684
5854
  const merged = stripGsdHookEntries(deepMerge(base, hostOverrides ?? {}));
5685
5855
  const current = readJsonOrNull(settingsPath);
5686
- if (current === null && existsSync36(settingsPath)) {
5856
+ if (current === null && existsSync37(settingsPath)) {
5687
5857
  return { diff: "", notes: [...notes, "malformed; skipping diff"] };
5688
5858
  }
5689
5859
  const strippedCurrent = stripGsdHookEntries(current ?? {});
@@ -5724,9 +5894,9 @@ function computePreview(ts, map, verb = "pull") {
5724
5894
  onPreview: (e) => addItem(links, formatLinkRow(e))
5725
5895
  });
5726
5896
  const settingsResult = previewSettings(
5727
- join43(repo, "shared", "settings.base.json"),
5728
- join43(repo, "hosts", `${HOST}.json`),
5729
- join43(claude, "settings.json")
5897
+ join44(repo, "shared", "settings.base.json"),
5898
+ join44(repo, "hosts", `${HOST}.json`),
5899
+ join44(claude, "settings.json")
5730
5900
  );
5731
5901
  const settingsSection = buildSettingsSectionForPreview(settingsResult);
5732
5902
  const sessions = section("Sessions");
@@ -5748,9 +5918,9 @@ init_config();
5748
5918
  init_commands_pull_wedge();
5749
5919
  init_utils();
5750
5920
  init_utils_fs();
5751
- import { execFileSync as execFileSync16 } from "node:child_process";
5921
+ import { execFileSync as execFileSync17 } from "node:child_process";
5752
5922
  function gitCapture(args, cwd) {
5753
- return execFileSync16("git", args, {
5923
+ return execFileSync17("git", args, {
5754
5924
  cwd,
5755
5925
  stdio: ["ignore", "pipe", "pipe"],
5756
5926
  maxBuffer: 64 * 1024 * 1024
@@ -5927,8 +6097,8 @@ function cmdPull(opts = {}) {
5927
6097
  const forceRemote = opts.forceRemote === true;
5928
6098
  const repo = repoHome();
5929
6099
  const backup = backupBase();
5930
- if (!existsSync37(repo)) die(`repo not cloned at ${repo}`);
5931
- if (!existsSync37(join44(repo, "shared", "settings.base.json"))) {
6100
+ if (!existsSync38(repo)) die(`repo not cloned at ${repo}`);
6101
+ if (!existsSync38(join45(repo, "shared", "settings.base.json"))) {
5932
6102
  die("repo not initialized; run 'nomad init' to scaffold");
5933
6103
  }
5934
6104
  const handle = acquireLock("pull");
@@ -5937,7 +6107,7 @@ function cmdPull(opts = {}) {
5937
6107
  const ts = freshBackupTs(backup);
5938
6108
  handleWedge(repo, forceRemote);
5939
6109
  if (!dryRun) {
5940
- const backupRoot = join44(backup, ts);
6110
+ const backupRoot = join45(backup, ts);
5941
6111
  try {
5942
6112
  mkdirSync9(backupRoot, { recursive: true });
5943
6113
  } catch (err) {
@@ -5950,8 +6120,8 @@ function cmdPull(opts = {}) {
5950
6120
  const prePostHeads = capturePrePostHeads(repo, () => {
5951
6121
  gitOrFatal(["pull", "--rebase", "--autostash"], "git pull --rebase", repo);
5952
6122
  });
5953
- const mapPath = join44(repo, "path-map.json");
5954
- const map = existsSync37(mapPath) ? readPathMap(mapPath) : { projects: {} };
6123
+ const mapPath = join45(repo, "path-map.json");
6124
+ const map = existsSync38(mapPath) ? readPathMap(mapPath) : { projects: {} };
5955
6125
  divergenceCheckExtras(ts);
5956
6126
  if (dryRun) {
5957
6127
  computePreview(ts, map, "pull");
@@ -5973,8 +6143,8 @@ function cmdPull(opts = {}) {
5973
6143
 
5974
6144
  // src/commands.push.ts
5975
6145
  init_config();
5976
- import { existsSync as existsSync39 } from "node:fs";
5977
- import { join as join46, relative as relative5 } from "node:path";
6146
+ import { existsSync as existsSync40 } from "node:fs";
6147
+ import { join as join47, relative as relative5 } from "node:path";
5978
6148
 
5979
6149
  // src/commands.push.allowlist.ts
5980
6150
  init_config();
@@ -6067,7 +6237,7 @@ function enforceAllowList(statusPorcelain, map) {
6067
6237
 
6068
6238
  // src/push-global-config.ts
6069
6239
  init_config();
6070
- import { execFileSync as execFileSync17 } from "node:child_process";
6240
+ import { execFileSync as execFileSync18 } from "node:child_process";
6071
6241
  var STATUS_LABELS = {
6072
6242
  A: "add",
6073
6243
  M: "modify",
@@ -6107,7 +6277,7 @@ function isInScope(filePath, exactPrefixes, dirPrefixes) {
6107
6277
  }
6108
6278
  function collectGlobalConfigChanges(repoHome2, hostname2, opts) {
6109
6279
  const args = opts.staged ? ["diff", "--cached", "--name-status", "-z"] : ["diff", "HEAD", "--name-status", "-z"];
6110
- const raw = execFileSync17("git", args, {
6280
+ const raw = execFileSync18("git", args, {
6111
6281
  cwd: repoHome2,
6112
6282
  stdio: ["ignore", "pipe", "pipe"]
6113
6283
  }).toString();
@@ -6146,9 +6316,9 @@ init_color();
6146
6316
  init_config();
6147
6317
  init_config_sharedDirs_guard();
6148
6318
  import { randomBytes as randomBytes2 } from "node:crypto";
6149
- import { copyFileSync, existsSync as existsSync38, mkdirSync as mkdirSync10, readdirSync as readdirSync14, rmSync as rmSync14 } from "node:fs";
6319
+ import { copyFileSync, existsSync as existsSync39, mkdirSync as mkdirSync10, readdirSync as readdirSync14, rmSync as rmSync14 } from "node:fs";
6150
6320
  import { homedir as homedir5 } from "node:os";
6151
- import { join as join45 } from "node:path";
6321
+ import { join as join46 } from "node:path";
6152
6322
  init_push_leak_verdict();
6153
6323
  init_push_gitleaks();
6154
6324
  init_utils_fs();
@@ -6163,13 +6333,13 @@ function stageSessions(tmpRoot, map) {
6163
6333
  if (!p || p === "TBD") continue;
6164
6334
  reverse.set(encodePath(p), logical);
6165
6335
  }
6166
- const localProjects = join45(claudeHome(), "projects");
6167
- if (!existsSync38(localProjects)) return 0;
6336
+ const localProjects = join46(claudeHome(), "projects");
6337
+ if (!existsSync39(localProjects)) return 0;
6168
6338
  let staged = 0;
6169
6339
  for (const dir of readdirSync14(localProjects)) {
6170
6340
  const logical = reverse.get(dir);
6171
6341
  if (!logical) continue;
6172
- copyDirJsonlOnly(join45(localProjects, dir), join45(tmpRoot, "shared", "projects", logical));
6342
+ copyDirJsonlOnly(join46(localProjects, dir), join46(tmpRoot, "shared", "projects", logical));
6173
6343
  staged++;
6174
6344
  }
6175
6345
  return staged;
@@ -6185,9 +6355,9 @@ function stageExtras(tmpRoot, map) {
6185
6355
  if (!localRoot || localRoot === "TBD") continue;
6186
6356
  for (const dirname8 of dirnames) {
6187
6357
  if (!whitelist.includes(dirname8)) continue;
6188
- const src = join45(localRoot, dirname8);
6189
- if (!existsSync38(src)) continue;
6190
- const dst = join45(tmpRoot, "shared", "extras", logical, dirname8);
6358
+ const src = join46(localRoot, dirname8);
6359
+ if (!existsSync39(src)) continue;
6360
+ const dst = join46(tmpRoot, "shared", "extras", logical, dirname8);
6191
6361
  copyExtras(src, dst);
6192
6362
  staged++;
6193
6363
  }
@@ -6195,19 +6365,19 @@ function stageExtras(tmpRoot, map) {
6195
6365
  return staged;
6196
6366
  }
6197
6367
  function previewPushLeaks(map) {
6198
- const cacheDir = join45(homedir5(), ".cache", "claude-nomad");
6368
+ const cacheDir = join46(homedir5(), ".cache", "claude-nomad");
6199
6369
  mkdirSync10(cacheDir, { recursive: true });
6200
6370
  const stamp = `${nowTimestamp()}-${process.pid}-${randomBytes2(4).toString("hex")}`;
6201
- const tmpRoot = join45(cacheDir, `push-preview-tree-${stamp}`);
6371
+ const tmpRoot = join46(cacheDir, `push-preview-tree-${stamp}`);
6202
6372
  try {
6203
6373
  const sessionCount = stageSessions(tmpRoot, map);
6204
6374
  const extrasCount = stageExtras(tmpRoot, map);
6205
6375
  if (sessionCount + extrasCount === 0) {
6206
6376
  return { leak: false, verdictRow: NOTHING_TO_SCAN_ROW, recovery: null, findings: [] };
6207
6377
  }
6208
- const ignoreFile = join45(repoHome(), ".gitleaksignore");
6209
- if (existsSync38(ignoreFile)) {
6210
- copyFileSync(ignoreFile, join45(tmpRoot, ".gitleaksignore"));
6378
+ const ignoreFile = join46(repoHome(), ".gitleaksignore");
6379
+ if (existsSync39(ignoreFile)) {
6380
+ copyFileSync(ignoreFile, join46(tmpRoot, ".gitleaksignore"));
6211
6381
  }
6212
6382
  let findings;
6213
6383
  try {
@@ -6229,8 +6399,8 @@ init_utils();
6229
6399
  init_utils_fs();
6230
6400
  init_utils_json();
6231
6401
  function stripGsdHooksFromBase(repo, backup) {
6232
- const basePath = join46(repo, "shared", "settings.base.json");
6233
- if (!existsSync39(basePath)) return;
6402
+ const basePath = join47(repo, "shared", "settings.base.json");
6403
+ if (!existsSync40(basePath)) return;
6234
6404
  let base;
6235
6405
  try {
6236
6406
  base = readJson(basePath);
@@ -6244,14 +6414,14 @@ function stripGsdHooksFromBase(repo, backup) {
6244
6414
  writeJsonAtomic(basePath, stripped);
6245
6415
  }
6246
6416
  function reportSettingsAheadDrift(repo) {
6247
- const basePath = join46(repo, "shared", "settings.base.json");
6248
- if (!existsSync39(basePath)) return;
6249
- const settingsPath = join46(claudeHome(), "settings.json");
6250
- if (!existsSync39(settingsPath)) return;
6417
+ const basePath = join47(repo, "shared", "settings.base.json");
6418
+ if (!existsSync40(basePath)) return;
6419
+ const settingsPath = join47(claudeHome(), "settings.json");
6420
+ if (!existsSync40(settingsPath)) return;
6251
6421
  try {
6252
6422
  const base = readJson(basePath);
6253
- const hostPath = join46(repo, "hosts", `${HOST}.json`);
6254
- const overrides = existsSync39(hostPath) ? readJson(hostPath) : {};
6423
+ const hostPath = join47(repo, "hosts", `${HOST}.json`);
6424
+ const overrides = existsSync40(hostPath) ? readJson(hostPath) : {};
6255
6425
  const merged = deepMerge(base, overrides);
6256
6426
  const settings = readJson(settingsPath);
6257
6427
  const { ahead } = classifySettingsDrift(merged, settings);
@@ -6265,7 +6435,7 @@ function reportSettingsAheadDrift(repo) {
6265
6435
  }
6266
6436
  }
6267
6437
  function guardGitlinks(repo) {
6268
- const gitlinks = findGitlinks(join46(repo, "shared"));
6438
+ const gitlinks = findGitlinks(join47(repo, "shared"));
6269
6439
  if (gitlinks.length === 0) return;
6270
6440
  for (const p of gitlinks) {
6271
6441
  const rel = relative5(repo, p);
@@ -6331,7 +6501,7 @@ async function cmdPush(opts = {}) {
6331
6501
  guardResolutionModeConflicts(dryRun, redactAll, allowAll, allowRule);
6332
6502
  const repo = repoHome();
6333
6503
  const backup = backupBase();
6334
- if (!existsSync39(repo)) die(`repo not cloned at ${repo}`);
6504
+ if (!existsSync40(repo)) die(`repo not cloned at ${repo}`);
6335
6505
  const handle = acquireLock("push");
6336
6506
  if (handle === null) process.exit(0);
6337
6507
  try {
@@ -6354,8 +6524,8 @@ async function cmdPush(opts = {}) {
6354
6524
  renderNoScanTree(st);
6355
6525
  return;
6356
6526
  }
6357
- const mapPath = join46(repo, "path-map.json");
6358
- if (!existsSync39(mapPath)) {
6527
+ const mapPath = join47(repo, "path-map.json");
6528
+ if (!existsSync40(mapPath)) {
6359
6529
  if (dryRun) return runDryRunPreview(st, null, repo);
6360
6530
  die("path-map.json missing, cannot enforce push allow-list");
6361
6531
  }
@@ -6376,25 +6546,35 @@ async function cmdPush(opts = {}) {
6376
6546
  }
6377
6547
 
6378
6548
  // src/commands.update.ts
6379
- import { execFileSync as execFileSync18 } from "node:child_process";
6549
+ import { execFileSync as execFileSync19 } from "node:child_process";
6380
6550
  init_utils();
6381
- function readInstalledVersion(run = execFileSync18) {
6551
+ function readInstalledVersion(run = execFileSync19) {
6382
6552
  try {
6383
6553
  return run("nomad", ["--version"], { encoding: "utf8" }).toString().trim() || null;
6384
6554
  } catch {
6385
6555
  return null;
6386
6556
  }
6387
6557
  }
6388
- function cmdUpdate(run = execFileSync18) {
6389
- console.log("Updating claude-nomad CLI via npm...");
6558
+ function cmdUpdate(currentVersion, run = execFileSync19) {
6559
+ console.log(`Updating claude-nomad v${currentVersion}...`);
6390
6560
  try {
6391
- run("npm", ["update", "-g", "claude-nomad"], { stdio: "inherit" });
6561
+ run("npm", ["update", "-g", "claude-nomad"], {
6562
+ encoding: "utf8",
6563
+ stdio: ["ignore", "pipe", "pipe"],
6564
+ // Now that output is captured rather than inherited, execFileSync buffers
6565
+ // it; lift the default 1 MiB ceiling so a noisy-but-successful npm run
6566
+ // (deprecation/funding spam) cannot throw ENOBUFS.
6567
+ maxBuffer: 64 * 1024 * 1024
6568
+ });
6392
6569
  } catch (err) {
6393
6570
  const e = err;
6394
6571
  if (e.code === "ENOENT") {
6395
6572
  throw new NomadFatal("npm not found on PATH; install Node.js/npm and retry.");
6396
6573
  }
6397
- throw new NomadFatal(`npm update -g claude-nomad failed: ${e.message}`);
6574
+ const detail = String(e.stderr ?? "").trim();
6575
+ const suffix = detail ? `
6576
+ ${detail}` : "";
6577
+ throw new NomadFatal(`npm update -g claude-nomad failed: ${e.message}${suffix}`);
6398
6578
  }
6399
6579
  const version = readInstalledVersion(run);
6400
6580
  if (version) {
@@ -6409,18 +6589,18 @@ init_config();
6409
6589
 
6410
6590
  // src/diff.ts
6411
6591
  init_config();
6412
- import { existsSync as existsSync40 } from "node:fs";
6413
- import { join as join47 } from "node:path";
6592
+ import { existsSync as existsSync41 } from "node:fs";
6593
+ import { join as join48 } from "node:path";
6414
6594
  init_utils();
6415
6595
  init_utils_fs();
6416
6596
  init_utils_json();
6417
6597
  function cmdDiff() {
6418
6598
  try {
6419
6599
  const repo = repoHome();
6420
- if (!existsSync40(repo)) die(`repo not cloned at ${repo}`);
6600
+ if (!existsSync41(repo)) die(`repo not cloned at ${repo}`);
6421
6601
  const ts = freshBackupTs(backupBase());
6422
- const mapPath = join47(repo, "path-map.json");
6423
- const map = existsSync40(mapPath) ? readPathMap(mapPath) : { projects: {} };
6602
+ const mapPath = join48(repo, "path-map.json");
6603
+ const map = existsSync41(mapPath) ? readPathMap(mapPath) : { projects: {} };
6424
6604
  computePreview(ts, map, "diff");
6425
6605
  } catch (err) {
6426
6606
  if (err instanceof NomadFatal) {
@@ -6434,19 +6614,19 @@ function cmdDiff() {
6434
6614
 
6435
6615
  // src/init.ts
6436
6616
  init_config();
6437
- import { existsSync as existsSync42, mkdirSync as mkdirSync11, writeFileSync as writeFileSync6 } from "node:fs";
6438
- import { join as join49 } from "node:path";
6617
+ import { existsSync as existsSync43, mkdirSync as mkdirSync11, writeFileSync as writeFileSync6 } from "node:fs";
6618
+ import { join as join50 } from "node:path";
6439
6619
 
6440
6620
  // src/init.gh-onboard.ts
6441
6621
  init_config();
6442
- import { execFileSync as execFileSync19 } from "node:child_process";
6622
+ import { execFileSync as execFileSync20 } from "node:child_process";
6443
6623
  init_utils();
6444
6624
  var DEFAULT_REPO_NAME = "claude-nomad-config";
6445
6625
  function isValidRepoName(name) {
6446
6626
  return /^[A-Za-z0-9._-]{1,100}$/.test(name);
6447
6627
  }
6448
6628
  var GH_NETWORK_TIMEOUT_MS = 3e4;
6449
- function ensureOriginRepo(repoName, run = execFileSync19) {
6629
+ function ensureOriginRepo(repoName, run = execFileSync20) {
6450
6630
  if (!isValidRepoName(repoName)) {
6451
6631
  die(
6452
6632
  `invalid repo name: ${JSON.stringify(repoName)}. Use only letters, digits, hyphens, underscores, and dots (1-100 chars).`
@@ -6517,33 +6697,33 @@ init_config();
6517
6697
  init_utils();
6518
6698
  init_utils_fs();
6519
6699
  init_utils_json();
6520
- import { copyFileSync as copyFileSync2, cpSync as cpSync7, existsSync as existsSync41, rmSync as rmSync15, statSync as statSync9 } from "node:fs";
6521
- import { join as join48 } from "node:path";
6700
+ import { copyFileSync as copyFileSync2, cpSync as cpSync7, existsSync as existsSync42, rmSync as rmSync15, statSync as statSync9 } from "node:fs";
6701
+ import { join as join49 } from "node:path";
6522
6702
  function snapshotIntoShared(map) {
6523
6703
  const repo = repoHome();
6524
6704
  const claude = claudeHome();
6525
6705
  for (const name of allSharedLinks(map)) {
6526
- const src = join48(claude, name);
6527
- if (!existsSync41(src)) continue;
6528
- const dst = join48(repo, "shared", name);
6706
+ const src = join49(claude, name);
6707
+ if (!existsSync42(src)) continue;
6708
+ const dst = join49(repo, "shared", name);
6529
6709
  if (statSync9(src).isDirectory()) {
6530
- const gk = join48(dst, ".gitkeep");
6531
- if (existsSync41(gk)) rmSync15(gk);
6710
+ const gk = join49(dst, ".gitkeep");
6711
+ if (existsSync42(gk)) rmSync15(gk);
6532
6712
  cpSync7(src, dst, { recursive: true, force: false, errorOnExist: true });
6533
6713
  } else {
6534
6714
  copyFileSync2(src, dst);
6535
6715
  }
6536
6716
  log(`snapshotted shared/${name} from ${src}`);
6537
6717
  }
6538
- const userSettings = join48(claude, "settings.json");
6539
- if (existsSync41(userSettings)) {
6718
+ const userSettings = join49(claude, "settings.json");
6719
+ if (existsSync42(userSettings)) {
6540
6720
  let parsed;
6541
6721
  try {
6542
6722
  parsed = readJson(userSettings);
6543
6723
  } catch (err) {
6544
6724
  return die(`malformed ${userSettings}: ${err.message}`);
6545
6725
  }
6546
- const hostFile = join48(repo, "hosts", `${HOST}.json`);
6726
+ const hostFile = join49(repo, "hosts", `${HOST}.json`);
6547
6727
  writeJsonAtomic(hostFile, parsed);
6548
6728
  log(`snapshotted hosts/${HOST}.json from ${userSettings}`);
6549
6729
  }
@@ -6556,14 +6736,14 @@ var SHARED_CLAUDE_MD = "<!-- claude-nomad shared CLAUDE.md; symlinked into ~/.cl
6556
6736
  var SHARED_KEEP_DIRS = ["agents", "skills", "commands", "rules", "hooks"];
6557
6737
  function preflightConflict(repoHome2) {
6558
6738
  const candidates = [
6559
- join49(repoHome2, "shared", "settings.base.json"),
6560
- join49(repoHome2, "shared", "CLAUDE.md"),
6561
- join49(repoHome2, "path-map.json"),
6562
- join49(repoHome2, "hosts"),
6563
- join49(repoHome2, "shared")
6739
+ join50(repoHome2, "shared", "settings.base.json"),
6740
+ join50(repoHome2, "shared", "CLAUDE.md"),
6741
+ join50(repoHome2, "path-map.json"),
6742
+ join50(repoHome2, "hosts"),
6743
+ join50(repoHome2, "shared")
6564
6744
  ];
6565
6745
  for (const c of candidates) {
6566
- if (existsSync42(c)) return c;
6746
+ if (existsSync43(c)) return c;
6567
6747
  }
6568
6748
  return null;
6569
6749
  }
@@ -6578,25 +6758,25 @@ function cmdInit(opts = {}) {
6578
6758
  die(`already initialized; refusing to clobber ${conflict}`);
6579
6759
  }
6580
6760
  ensureOriginRepo(opts.repoName ?? DEFAULT_REPO_NAME, opts.run);
6581
- mkdirSync11(join49(repo, "shared"), { recursive: true });
6582
- mkdirSync11(join49(repo, "hosts"), { recursive: true });
6761
+ mkdirSync11(join50(repo, "shared"), { recursive: true });
6762
+ mkdirSync11(join50(repo, "hosts"), { recursive: true });
6583
6763
  for (const name of SHARED_KEEP_DIRS) {
6584
- mkdirSync11(join49(repo, "shared", name), { recursive: true });
6764
+ mkdirSync11(join50(repo, "shared", name), { recursive: true });
6585
6765
  }
6586
- const userClaudeMd = join49(claude, "CLAUDE.md");
6587
- if (!snapshot || !existsSync42(userClaudeMd)) {
6588
- writeFileSync6(join49(repo, "shared", "CLAUDE.md"), SHARED_CLAUDE_MD);
6766
+ const userClaudeMd = join50(claude, "CLAUDE.md");
6767
+ if (!snapshot || !existsSync43(userClaudeMd)) {
6768
+ writeFileSync6(join50(repo, "shared", "CLAUDE.md"), SHARED_CLAUDE_MD);
6589
6769
  item("created shared/CLAUDE.md");
6590
6770
  }
6591
6771
  for (const name of SHARED_KEEP_DIRS) {
6592
- writeFileSync6(join49(repo, "shared", name, ".gitkeep"), "");
6772
+ writeFileSync6(join50(repo, "shared", name, ".gitkeep"), "");
6593
6773
  item(`created shared/${name}/.gitkeep`);
6594
6774
  }
6595
- writeFileSync6(join49(repo, "hosts", ".gitkeep"), "");
6775
+ writeFileSync6(join50(repo, "hosts", ".gitkeep"), "");
6596
6776
  item("created hosts/.gitkeep");
6597
- writeJsonAtomic(join49(repo, "shared", "settings.base.json"), {});
6777
+ writeJsonAtomic(join50(repo, "shared", "settings.base.json"), {});
6598
6778
  item("created shared/settings.base.json");
6599
- writeJsonAtomic(join49(repo, "path-map.json"), { projects: {} });
6779
+ writeJsonAtomic(join50(repo, "path-map.json"), { projects: {} });
6600
6780
  item("created path-map.json");
6601
6781
  if (snapshot) {
6602
6782
  snapshotIntoShared({ projects: {} });
@@ -6918,7 +7098,7 @@ function parsePushArgs(argv) {
6918
7098
  // package.json
6919
7099
  var package_default = {
6920
7100
  name: "claude-nomad",
6921
- version: "0.53.2",
7101
+ version: "0.54.0",
6922
7102
  type: "module",
6923
7103
  description: "Sync Claude Code config (~/.claude/) across machines via a private Git repo, with path remapping and per-host settings overrides.",
6924
7104
  keywords: [
@@ -7064,6 +7244,8 @@ var DEFAULT_HELP = [
7064
7244
  cont("`nomad push` would stage (a temp copy, never the live dir)."),
7065
7245
  row(" --check-schema", "Flag settings.json keys absent from the live published"),
7066
7246
  cont("Claude Code settings schema (needs network; degrades offline)."),
7247
+ row(" --check-remote", "Verify origin/main has shared/ and a valid path-map.json"),
7248
+ cont("(reads locally-cached remote ref; skips with a warning if unavailable)."),
7067
7249
  row(" --resume-cmd <id>", "Print `cd <abspath> && claude --resume <id>` for a session id"),
7068
7250
  cont("from ~/.claude/projects/."),
7069
7251
  "",
@@ -7135,15 +7317,15 @@ var DEFAULT_HELP = [
7135
7317
  init_config();
7136
7318
  init_utils();
7137
7319
  init_utils_json();
7138
- import { existsSync as existsSync43, readFileSync as readFileSync14, readdirSync as readdirSync15 } from "node:fs";
7139
- import { join as join50 } from "node:path";
7320
+ import { existsSync as existsSync44, readFileSync as readFileSync14, readdirSync as readdirSync15 } from "node:fs";
7321
+ import { join as join51 } from "node:path";
7140
7322
  function resumeCmd(sessionId) {
7141
7323
  if (!/^[A-Za-z0-9_-]+$/.test(sessionId) || sessionId.length > 128) {
7142
7324
  fail(`invalid session id: ${sessionId}`);
7143
7325
  process.exit(1);
7144
7326
  }
7145
- const projectsRoot = join50(claudeHome(), "projects");
7146
- if (!existsSync43(projectsRoot)) {
7327
+ const projectsRoot = join51(claudeHome(), "projects");
7328
+ if (!existsSync44(projectsRoot)) {
7147
7329
  fail(`${projectsRoot} does not exist`);
7148
7330
  process.exit(1);
7149
7331
  }
@@ -7157,8 +7339,8 @@ function resumeCmd(sessionId) {
7157
7339
  fail(`no cwd field found in ${jsonlPath}`);
7158
7340
  process.exit(1);
7159
7341
  }
7160
- const mapPath = join50(repoHome(), "path-map.json");
7161
- if (!existsSync43(mapPath)) {
7342
+ const mapPath = join51(repoHome(), "path-map.json");
7343
+ if (!existsSync44(mapPath)) {
7162
7344
  fail("path-map.json missing");
7163
7345
  process.exit(1);
7164
7346
  }
@@ -7181,8 +7363,8 @@ function resumeCmd(sessionId) {
7181
7363
  }
7182
7364
  function findTranscriptPath(projectsRoot, sessionId) {
7183
7365
  for (const dir of readdirSync15(projectsRoot)) {
7184
- const candidate = join50(projectsRoot, dir, `${sessionId}.jsonl`);
7185
- if (existsSync43(candidate)) return candidate;
7366
+ const candidate = join51(projectsRoot, dir, `${sessionId}.jsonl`);
7367
+ if (existsSync44(candidate)) return candidate;
7186
7368
  }
7187
7369
  return null;
7188
7370
  }
@@ -7284,7 +7466,7 @@ try {
7284
7466
  console.error("usage: nomad update");
7285
7467
  process.exit(1);
7286
7468
  }
7287
- cmdUpdate();
7469
+ cmdUpdate(package_default.version);
7288
7470
  break;
7289
7471
  }
7290
7472
  case "adopt": {
@@ -7323,7 +7505,7 @@ try {
7323
7505
  const parsed = parseDoctorArgs(process.argv.slice(3));
7324
7506
  if (parsed.kind === "error") {
7325
7507
  console.error(
7326
- "usage: nomad doctor [--check-shared] [--check-schema] [--verbose|--all|-v] | --resume-cmd <session-id>"
7508
+ "usage: nomad doctor [--check-shared] [--check-schema] [--check-remote] [--verbose|--all|-v] | --resume-cmd <session-id>"
7327
7509
  );
7328
7510
  process.exit(1);
7329
7511
  } else if (parsed.kind === "resume") {
@@ -7332,6 +7514,7 @@ try {
7332
7514
  cmdDoctor({
7333
7515
  checkShared: parsed.checkShared,
7334
7516
  checkSchema: parsed.checkSchema,
7517
+ checkRemote: parsed.checkRemote,
7335
7518
  verbose: parsed.verbose
7336
7519
  });
7337
7520
  }