@sealant/mend 0.34.5 → 0.35.1

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.
Files changed (79) hide show
  1. package/dist/{chunk-5DORQXQT.js → chunk-SMH65F6Z.js} +25 -1
  2. package/dist/{dashboard-KZ4XGZ6W.js → dashboard-MGR4YUFD.js} +1 -1
  3. package/dist/main.js +418 -316
  4. package/man/mend-accounts.1 +1 -1
  5. package/man/mend-adopt.1 +1 -1
  6. package/man/mend-attach.1 +1 -1
  7. package/man/mend-codex.1 +1 -1
  8. package/man/mend-completions.1 +1 -1
  9. package/man/mend-connect.1 +8 -4
  10. package/man/mend-continue.1 +1 -1
  11. package/man/mend-doctor.1 +1 -1
  12. package/man/mend-dotfiles-repo.1 +1 -1
  13. package/man/mend-dotfiles-sync.1 +1 -1
  14. package/man/mend-dotfiles.1 +1 -1
  15. package/man/mend-env-cluster.1 +1 -1
  16. package/man/mend-env-load.1 +1 -1
  17. package/man/mend-env-show.1 +1 -1
  18. package/man/mend-folder-create.1 +1 -1
  19. package/man/mend-folder-list.1 +1 -1
  20. package/man/mend-folder-push.1 +1 -1
  21. package/man/mend-folder-rm.1 +1 -1
  22. package/man/mend-git-author.1 +1 -1
  23. package/man/mend-help.1 +1 -1
  24. package/man/mend-invite.1 +1 -1
  25. package/man/mend-keys-init.1 +1 -1
  26. package/man/mend-keys-mode.1 +1 -1
  27. package/man/mend-keys-share.1 +1 -1
  28. package/man/mend-keys-show.1 +1 -1
  29. package/man/mend-land.1 +1 -1
  30. package/man/mend-login.1 +1 -1
  31. package/man/mend-logout.1 +1 -1
  32. package/man/mend-man.1 +1 -1
  33. package/man/mend-members.1 +1 -1
  34. package/man/mend-operator-exposure.1 +1 -1
  35. package/man/mend-operator-gate.1 +1 -1
  36. package/man/mend-operator-grant-owner.1 +1 -1
  37. package/man/mend-operator-org-create.1 +1 -1
  38. package/man/mend-operator-org-invite-owner.1 +1 -1
  39. package/man/mend-operator-org-list.1 +1 -1
  40. package/man/mend-operator-org-rename.1 +1 -1
  41. package/man/mend-operator-reset-link.1 +1 -1
  42. package/man/mend-pair.1 +1 -1
  43. package/man/mend-projects.1 +1 -1
  44. package/man/mend-pull.1 +1 -1
  45. package/man/mend-refresh.1 +1 -1
  46. package/man/mend-rejoin.1 +1 -1
  47. package/man/mend-resume.1 +1 -1
  48. package/man/mend-run.1 +1 -1
  49. package/man/mend-server-logs.1 +1 -1
  50. package/man/mend-server-restart.1 +1 -1
  51. package/man/mend-server-setup.1 +1 -1
  52. package/man/mend-server-start.1 +1 -1
  53. package/man/mend-server-status.1 +1 -1
  54. package/man/mend-server-stop.1 +1 -1
  55. package/man/mend-server-upgrade.1 +1 -1
  56. package/man/mend-server.1 +1 -1
  57. package/man/mend-service-add.1 +1 -1
  58. package/man/mend-service-connect.1 +1 -1
  59. package/man/mend-service-init.1 +1 -1
  60. package/man/mend-service-list.1 +1 -1
  61. package/man/mend-service-logs.1 +1 -1
  62. package/man/mend-service-restart.1 +1 -1
  63. package/man/mend-service-run.1 +1 -1
  64. package/man/mend-service-stop.1 +1 -1
  65. package/man/mend-session-share.1 +1 -1
  66. package/man/mend-sessions.1 +1 -1
  67. package/man/mend-shell.1 +1 -1
  68. package/man/mend-skills-push.1 +1 -1
  69. package/man/mend-skills.1 +1 -1
  70. package/man/mend-snake.1 +1 -1
  71. package/man/mend-ssh-setup.1 +1 -1
  72. package/man/mend-ssh.1 +1 -1
  73. package/man/mend-stop.1 +1 -1
  74. package/man/mend-ui.1 +1 -1
  75. package/man/mend-uninstall.1 +1 -1
  76. package/man/mend-version.1 +1 -1
  77. package/man/mend-worktrees.1 +1 -1
  78. package/man/mend.1 +1 -1
  79. package/package.json +5 -4
package/dist/main.js CHANGED
@@ -34,15 +34,15 @@ import {
34
34
  sessionDisplayName,
35
35
  spoken,
36
36
  trackBracketedPaste
37
- } from "./chunk-5DORQXQT.js";
37
+ } from "./chunk-SMH65F6Z.js";
38
38
 
39
39
  // src/main.ts
40
- import { spawn as spawn3, spawnSync as spawnSync5 } from "node:child_process";
41
- import * as fs15 from "node:fs";
40
+ import { spawn as spawn3, spawnSync as spawnSync6 } from "node:child_process";
41
+ import * as fs17 from "node:fs";
42
42
  import { createRequire } from "node:module";
43
43
  import * as net4 from "node:net";
44
- import * as os10 from "node:os";
45
- import * as path16 from "node:path";
44
+ import * as os11 from "node:os";
45
+ import * as path18 from "node:path";
46
46
 
47
47
  // src/agent-share.ts
48
48
  import * as net from "node:net";
@@ -223,6 +223,15 @@ import * as fs from "node:fs";
223
223
  import * as os from "node:os";
224
224
  import * as path from "node:path";
225
225
  var claudeGrantDir = (home) => path.join(home, "claude-grant");
226
+ var forgetGrant = (configDir, platform = process.platform) => {
227
+ fs.rmSync(configDir, { recursive: true, force: true });
228
+ if (platform !== "darwin") return;
229
+ spawnSync(
230
+ "security",
231
+ ["delete-generic-password", "-a", os.userInfo().username, "-s", keychainService(configDir)],
232
+ { stdio: "ignore", timeout: 6e4 }
233
+ );
234
+ };
226
235
  var personalClaudeDir = (environment = process.env) => {
227
236
  const configured = environment["CLAUDE_CONFIG_DIR"];
228
237
  return configured === void 0 || configured === "" ? path.join(os.homedir(), ".claude") : configured;
@@ -342,15 +351,94 @@ var readClipboardImage = async (platform = process.platform, env = process.env)
342
351
  return null;
343
352
  };
344
353
 
345
- // src/doctor-bundle-collectors.ts
354
+ // src/codex-grant.ts
355
+ import { spawnSync as spawnSync2 } from "node:child_process";
346
356
  import * as fs3 from "node:fs";
347
357
  import * as os2 from "node:os";
348
358
  import * as path3 from "node:path";
349
359
 
350
- // src/server-runtime.ts
351
- import { spawn } from "node:child_process";
360
+ // src/login-dir.ts
352
361
  import * as fs2 from "node:fs";
353
362
  import * as path2 from "node:path";
363
+ var throwawayLoginDir = (parent, prefix) => {
364
+ fs2.mkdirSync(parent, { recursive: true, mode: 448 });
365
+ const dir = fs2.mkdtempSync(path2.join(parent, prefix));
366
+ fs2.chmodSync(dir, 448);
367
+ return dir;
368
+ };
369
+
370
+ // src/codex-grant.ts
371
+ var codexCli = (environment = process.env) => ({
372
+ bin: environment["MEND_CODEX_BIN"] ?? "codex",
373
+ env: environment
374
+ });
375
+ var personalCodexHome = (environment = process.env) => {
376
+ const configured = environment["CODEX_HOME"];
377
+ return configured === void 0 || configured === "" ? path3.join(os2.homedir(), ".codex") : configured;
378
+ };
379
+ var runCodexDeviceLogin = (cli, codexHome) => {
380
+ const result = spawnSync2(cli.bin, ["login", "--device-auth"], {
381
+ stdio: "inherit",
382
+ env: { ...cli.env, CODEX_HOME: codexHome }
383
+ });
384
+ return result.error === void 0 && result.status === 0;
385
+ };
386
+ var refreshTokenOf = (authJson) => {
387
+ try {
388
+ const parsed = JSON.parse(authJson);
389
+ if (typeof parsed !== "object" || parsed === null) return null;
390
+ const tokens = parsed.tokens;
391
+ if (typeof tokens !== "object" || tokens === null) return null;
392
+ const refreshToken = tokens.refresh_token;
393
+ return typeof refreshToken === "string" && refreshToken !== "" ? refreshToken : null;
394
+ } catch {
395
+ return null;
396
+ }
397
+ };
398
+ var sameCodexLogin = (a, b) => {
399
+ const first = refreshTokenOf(a);
400
+ return first !== null && first === refreshTokenOf(b);
401
+ };
402
+ var codexGrant = (input) => {
403
+ const home = throwawayLoginDir(input.parent, "codex-login-");
404
+ try {
405
+ input.say(" Mend needs its own Codex login; it is sent to your server and not kept here");
406
+ input.say(" your own Codex login stays as it is");
407
+ if (!runCodexDeviceLogin(input.cli, home)) {
408
+ return { kind: "failed", reason: "codex: the login did not complete" };
409
+ }
410
+ const file = path3.join(home, "auth.json");
411
+ if (!fs3.existsSync(file)) {
412
+ return { kind: "failed", reason: `codex: logged in, but no auth.json appeared in ${home}` };
413
+ }
414
+ const secret = fs3.readFileSync(file, "utf8").trim();
415
+ if (refreshTokenOf(secret) === null) {
416
+ return {
417
+ kind: "failed",
418
+ reason: "codex: the login wrote no ChatGPT session (an API key login has nothing to refresh)"
419
+ };
420
+ }
421
+ if (input.personalAuthJson !== null && sameCodexLogin(secret, input.personalAuthJson)) {
422
+ return {
423
+ kind: "failed",
424
+ reason: "codex: that is the same login this machine's Codex holds, so both sides would race on refresh \u2014 connect it deliberately with --use-my-login"
425
+ };
426
+ }
427
+ return { kind: "grant", secret };
428
+ } finally {
429
+ fs3.rmSync(home, { recursive: true, force: true });
430
+ }
431
+ };
432
+
433
+ // src/doctor-bundle-collectors.ts
434
+ import * as fs5 from "node:fs";
435
+ import * as os3 from "node:os";
436
+ import * as path5 from "node:path";
437
+
438
+ // src/server-runtime.ts
439
+ import { spawn } from "node:child_process";
440
+ import * as fs4 from "node:fs";
441
+ import * as path4 from "node:path";
354
442
  var serverProcessDeadlines = {
355
443
  ordinary: 3e4,
356
444
  pull: 10 * 6e4,
@@ -396,7 +484,7 @@ var runServerProcess = (command, args, parentEnvironment, options = {}) => {
396
484
  return new Promise((resolve7) => {
397
485
  let fd;
398
486
  try {
399
- if (options.stdoutFile !== void 0) fd = fs2.openSync(options.stdoutFile, "wx", 384);
487
+ if (options.stdoutFile !== void 0) fd = fs4.openSync(options.stdoutFile, "wx", 384);
400
488
  const child = spawn(command, [...args], {
401
489
  env,
402
490
  detached: process.platform !== "win32",
@@ -447,12 +535,12 @@ var runServerProcess = (command, args, parentEnvironment, options = {}) => {
447
535
  child.once("close", (status) => {
448
536
  globalThis.clearTimeout(timer);
449
537
  try {
450
- if (fd !== void 0) fs2.fsyncSync(fd);
538
+ if (fd !== void 0) fs4.fsyncSync(fd);
451
539
  } catch {
452
540
  failure2 ??= "Could not durably write process output.";
453
541
  } finally {
454
542
  try {
455
- if (fd !== void 0) fs2.closeSync(fd);
543
+ if (fd !== void 0) fs4.closeSync(fd);
456
544
  } catch {
457
545
  failure2 ??= "Could not close process output file.";
458
546
  }
@@ -466,7 +554,7 @@ var runServerProcess = (command, args, parentEnvironment, options = {}) => {
466
554
  });
467
555
  } catch (cause) {
468
556
  try {
469
- if (fd !== void 0) fs2.closeSync(fd);
557
+ if (fd !== void 0) fs4.closeSync(fd);
470
558
  } catch {
471
559
  }
472
560
  resolve7({
@@ -487,9 +575,9 @@ var serverComposeArgs = (installation, command) => [
487
575
  "--project-directory",
488
576
  installation.directory,
489
577
  "--env-file",
490
- path2.join(installation.directory, "server.env"),
578
+ path4.join(installation.directory, "server.env"),
491
579
  "-f",
492
- path2.join(installation.directory, "compose.yaml"),
580
+ path4.join(installation.directory, "compose.yaml"),
493
581
  ...command
494
582
  ];
495
583
 
@@ -535,11 +623,11 @@ var mapLimit = async (items, limit, work) => {
535
623
  return results;
536
624
  };
537
625
  var pathOf = (command, env = process.env) => {
538
- for (const directory of (env["PATH"] ?? "").split(path3.delimiter)) {
626
+ for (const directory of (env["PATH"] ?? "").split(path5.delimiter)) {
539
627
  if (directory === "") continue;
540
- const candidate = path3.join(directory, command);
628
+ const candidate = path5.join(directory, command);
541
629
  try {
542
- fs3.accessSync(candidate, fs3.constants.X_OK);
630
+ fs5.accessSync(candidate, fs5.constants.X_OK);
543
631
  return candidate;
544
632
  } catch {
545
633
  }
@@ -557,9 +645,9 @@ var cliCollector = (deps) => ({
557
645
  node: process.versions.node,
558
646
  platform: process.platform,
559
647
  arch: process.arch,
560
- osType: os2.type(),
561
- osRelease: os2.release(),
562
- hostname: os2.hostname(),
648
+ osType: os3.type(),
649
+ osRelease: os3.release(),
650
+ hostname: os3.hostname(),
563
651
  term: deps.env["TERM"] ?? null,
564
652
  shell: deps.env["SHELL"] ?? null,
565
653
  lang: deps.env["LANG"] ?? null,
@@ -1029,8 +1117,8 @@ var bundleCollectors = (deps) => {
1029
1117
  };
1030
1118
 
1031
1119
  // src/doctor-bundle.ts
1032
- import * as fs4 from "node:fs";
1033
- import * as path4 from "node:path";
1120
+ import * as fs6 from "node:fs";
1121
+ import * as path6 from "node:path";
1034
1122
  import { gzipSync } from "node:zlib";
1035
1123
 
1036
1124
  // src/help.ts
@@ -1079,19 +1167,20 @@ var COMMANDS = [
1079
1167
  summary: "send this machine's provider credential to the platform",
1080
1168
  synopsis: ["<claude|codex|github> [--use-my-login] [--from-stdin] [--remove]"],
1081
1169
  description: [
1082
- "Sessions run on the platform, so the platform needs your provider login. This reads the file the provider's own CLI wrote when you logged in (codex) or asks gh for its token (github) and stores it under your own user. Nothing is shared with other users.",
1083
- "Claude is different: Mend gets a login of its own. Claude rotates its refresh token, so two copies of one login fight and the one that refreshes second is signed out, and Mend refreshes on a schedule. So this logs in once against a directory Mend keeps, and your own Claude login stays as it is. Run it again whenever Mend says the grant expired."
1170
+ "Sessions run on the platform, so the platform needs your provider login. It is stored under your own user and used only for your work. Nothing is shared with other users.",
1171
+ "Claude and Codex get a login of Mend's own. Both rotate their refresh token, so two copies of one login fight and the one that refreshes second is signed out, and Mend's server refreshes on a schedule. So this logs in through the provider's own flow and your own login stays as it is: Claude in the browser, Codex with a device code, both sent and not kept here. Run it again whenever Mend says a login needs reconnecting. GitHub sends gh's token."
1084
1172
  ],
1085
1173
  options: [
1086
1174
  {
1087
1175
  flag: "--use-my-login",
1088
- text: "claude: send the login this machine already uses; both sides then share one grant"
1176
+ text: "claude, codex: send the login this machine already uses; both sides then share it"
1089
1177
  },
1090
1178
  { flag: "--from-stdin", text: "paste a credential instead of reading the provider's file" },
1091
1179
  { flag: "--remove", text: "disconnect the provider" }
1092
1180
  ],
1093
1181
  examples: [
1094
1182
  { command: "mend connect claude", text: "a Claude login of Mend's own, through the browser" },
1183
+ { command: "mend connect codex", text: "a Codex login of Mend's own, with a device code" },
1095
1184
  { command: "mend connect github --remove", text: "" }
1096
1185
  ],
1097
1186
  see: ["accounts"]
@@ -2470,9 +2559,9 @@ var collectBundle = async (collectors) => {
2470
2559
  };
2471
2560
  var bundleFileName = (now) => `mend-bundle-${now.toISOString().replace(/\.\d{3}Z$/, "Z").replace(/:/g, "-")}.tgz`;
2472
2561
  var writeBundle = (files, outPath, now) => {
2473
- const directory = path4.dirname(outPath);
2474
- fs4.mkdirSync(directory, { recursive: true, mode: 448 });
2475
- const root = path4.basename(outPath).replace(/\.(?:tgz|tar\.gz)$/, "");
2562
+ const directory = path6.dirname(outPath);
2563
+ fs6.mkdirSync(directory, { recursive: true, mode: 448 });
2564
+ const root = path6.basename(outPath).replace(/\.(?:tgz|tar\.gz)$/, "");
2476
2565
  const entries = files.map((file) => ({
2477
2566
  path: file.path,
2478
2567
  content: Buffer.from(file.content, "utf8")
@@ -2481,8 +2570,8 @@ var writeBundle = (files, outPath, now) => {
2481
2570
  entries.map((entry) => ({ path: `${root}/${entry.path}`, content: entry.content })),
2482
2571
  now
2483
2572
  );
2484
- fs4.writeFileSync(outPath, bytes, { mode: 384 });
2485
- fs4.chmodSync(outPath, 384);
2573
+ fs6.writeFileSync(outPath, bytes, { mode: 384 });
2574
+ fs6.chmodSync(outPath, 384);
2486
2575
  return {
2487
2576
  path: outPath,
2488
2577
  bytes: bytes.length,
@@ -2543,7 +2632,7 @@ var doctorBundleCommand = async (args, deps) => {
2543
2632
  return;
2544
2633
  }
2545
2634
  const now = deps.now();
2546
- const outPath = path4.resolve(parsed.args.out ?? path4.join(deps.defaultDir, bundleFileName(now)));
2635
+ const outPath = path6.resolve(parsed.args.out ?? path6.join(deps.defaultDir, bundleFileName(now)));
2547
2636
  deps.warn("collecting \xB7 this can take a minute");
2548
2637
  const files = await collectBundle(deps.collectors(parsed.args.tail));
2549
2638
  const written = writeBundle(files, outPath, now);
@@ -2551,14 +2640,14 @@ var doctorBundleCommand = async (args, deps) => {
2551
2640
  };
2552
2641
 
2553
2642
  // src/doctor.ts
2554
- import * as fs6 from "node:fs";
2555
- import * as path6 from "node:path";
2643
+ import * as fs8 from "node:fs";
2644
+ import * as path8 from "node:path";
2556
2645
 
2557
2646
  // src/docker-shutdown.ts
2558
- import { spawnSync as spawnSync2 } from "node:child_process";
2559
- import * as fs5 from "node:fs";
2560
- import * as os3 from "node:os";
2561
- import * as path5 from "node:path";
2647
+ import { spawnSync as spawnSync3 } from "node:child_process";
2648
+ import * as fs7 from "node:fs";
2649
+ import * as os4 from "node:os";
2650
+ import * as path7 from "node:path";
2562
2651
  var DOCKER_CAPTURE_STOP_GRACE_SECONDS = 3600;
2563
2652
  var DOCKERD_DEFAULT_SHUTDOWN_TIMEOUT_SECONDS = 15;
2564
2653
  var flagValue = (argv, name) => {
@@ -2583,12 +2672,12 @@ var daemonKindOf = (info) => {
2583
2672
  var defaultConfigPath = (facts, daemon) => {
2584
2673
  switch (daemon) {
2585
2674
  case "desktop":
2586
- return path5.join(facts.home, ".docker", "daemon.json");
2675
+ return path7.join(facts.home, ".docker", "daemon.json");
2587
2676
  case "orbstack":
2588
- return path5.join(facts.home, ".orbstack", "config", "docker.json");
2677
+ return path7.join(facts.home, ".orbstack", "config", "docker.json");
2589
2678
  case "rootless":
2590
- return path5.join(
2591
- facts.xdgConfigHome ?? path5.join(facts.home, ".config"),
2679
+ return path7.join(
2680
+ facts.xdgConfigHome ?? path7.join(facts.home, ".config"),
2592
2681
  "docker",
2593
2682
  "daemon.json"
2594
2683
  );
@@ -2717,7 +2806,7 @@ var parseDockerInfo = (stdout) => {
2717
2806
  };
2718
2807
  var readHostFile = (file) => {
2719
2808
  try {
2720
- return { kind: "read", text: fs5.readFileSync(file, "utf8") };
2809
+ return { kind: "read", text: fs7.readFileSync(file, "utf8") };
2721
2810
  } catch (cause) {
2722
2811
  return cause instanceof Error && "code" in cause && cause.code === "ENOENT" ? { kind: "absent" } : { kind: "unreadable" };
2723
2812
  }
@@ -2725,21 +2814,21 @@ var readHostFile = (file) => {
2725
2814
  var hostProcView = {
2726
2815
  list: (dir) => {
2727
2816
  try {
2728
- return fs5.readdirSync(dir);
2817
+ return fs7.readdirSync(dir);
2729
2818
  } catch {
2730
2819
  return null;
2731
2820
  }
2732
2821
  },
2733
2822
  read: (file) => {
2734
2823
  try {
2735
- return fs5.readFileSync(file, "utf8");
2824
+ return fs7.readFileSync(file, "utf8");
2736
2825
  } catch {
2737
2826
  return null;
2738
2827
  }
2739
2828
  },
2740
2829
  link: (file) => {
2741
2830
  try {
2742
- return fs5.readlinkSync(file);
2831
+ return fs7.readlinkSync(file);
2743
2832
  } catch {
2744
2833
  return null;
2745
2834
  }
@@ -2779,7 +2868,7 @@ var observeDockerd = (proc, host) => {
2779
2868
  const cmdline = proc.read(`/proc/${entry}/cmdline`);
2780
2869
  if (cmdline === null) continue;
2781
2870
  const argv = cmdline.split("\0").filter((arg) => arg !== "");
2782
- if (path5.basename(argv[0] ?? "") === "dockerd") daemons.push({ pid: entry, argv });
2871
+ if (path7.basename(argv[0] ?? "") === "dockerd") daemons.push({ pid: entry, argv });
2783
2872
  }
2784
2873
  if (daemons.length === 0) return { kind: "none" };
2785
2874
  const socket = unixSocketOf(host);
@@ -2839,7 +2928,7 @@ var observeDockerd = (proc, host) => {
2839
2928
  var hostDockerEndpoint = () => {
2840
2929
  const fromEnv = process.env["DOCKER_HOST"];
2841
2930
  if (fromEnv !== void 0 && fromEnv.trim() !== "") return fromEnv.trim();
2842
- const context = spawnSync2(
2931
+ const context = spawnSync3(
2843
2932
  "docker",
2844
2933
  ["context", "inspect", "--format", "{{.Endpoints.docker.Host}}"],
2845
2934
  {
@@ -2865,11 +2954,11 @@ var hostDockerDaemonFacts = (infoStdout) => ({
2865
2954
  info: infoStdout === null ? null : parseDockerInfo(infoStdout),
2866
2955
  ...dockerdFactsOf(observeDockerd(hostProcView, hostDockerEndpoint())),
2867
2956
  readFile: readHostFile,
2868
- home: os3.homedir(),
2957
+ home: os4.homedir(),
2869
2958
  xdgConfigHome: process.env["XDG_CONFIG_HOME"] ?? null
2870
2959
  });
2871
2960
  var observeHostShutdownTimeout = () => {
2872
- const info = spawnSync2("docker", ["info", "--format", "{{json .}}"], {
2961
+ const info = spawnSync3("docker", ["info", "--format", "{{json .}}"], {
2873
2962
  encoding: "utf8",
2874
2963
  timeout: 3e3,
2875
2964
  stdio: ["ignore", "pipe", "ignore"]
@@ -3028,7 +3117,8 @@ var runChecks = async (config, probes) => {
3028
3117
  } : {
3029
3118
  label: provider,
3030
3119
  state: "todo",
3031
- detail: account.status,
3120
+ // A refused refresh ends the login (docs/adr/0008): say what happened, not the enum.
3121
+ detail: account.status === "invalid" ? "reconnect needed \xB7 the provider refused the login" : account.status,
3032
3122
  fix: `mend connect ${provider}`
3033
3123
  }
3034
3124
  );
@@ -3098,10 +3188,10 @@ var runChecks = async (config, probes) => {
3098
3188
  return checks;
3099
3189
  };
3100
3190
  var onPath = (command) => {
3101
- for (const directory of (process.env["PATH"] ?? "").split(path6.delimiter)) {
3191
+ for (const directory of (process.env["PATH"] ?? "").split(path8.delimiter)) {
3102
3192
  if (directory === "") continue;
3103
3193
  try {
3104
- fs6.accessSync(path6.join(directory, command), fs6.constants.X_OK);
3194
+ fs8.accessSync(path8.join(directory, command), fs8.constants.X_OK);
3105
3195
  return true;
3106
3196
  } catch {
3107
3197
  }
@@ -3126,8 +3216,8 @@ var doctorCommand = async (config, localCredential2, claudeGrant2) => {
3126
3216
  };
3127
3217
 
3128
3218
  // src/dotfiles.ts
3129
- import * as fs7 from "node:fs";
3130
- import * as path7 from "node:path";
3219
+ import * as fs9 from "node:fs";
3220
+ import * as path9 from "node:path";
3131
3221
  var DOTFILE_CANDIDATES = [
3132
3222
  {
3133
3223
  group: "shell",
@@ -3170,7 +3260,7 @@ var DOTFILE_CANDIDATES = [
3170
3260
  var MAX_FILE_BYTES = 1024 * 1024;
3171
3261
  var statFile = (home, relative4) => {
3172
3262
  try {
3173
- const stat = fs7.statSync(path7.join(home, relative4));
3263
+ const stat = fs9.statSync(path9.join(home, relative4));
3174
3264
  return stat.isFile() ? stat : null;
3175
3265
  } catch {
3176
3266
  return null;
@@ -3183,9 +3273,9 @@ var scanDotfileCandidates = (home) => DOTFILE_CANDIDATES.flatMap(
3183
3273
  })
3184
3274
  );
3185
3275
  var homeRelativePath = (home, requested) => {
3186
- const relative4 = path7.relative(home, path7.resolve(home, requested));
3187
- const outside = relative4 === "" || relative4 === ".." || relative4.startsWith(`..${path7.sep}`) || path7.isAbsolute(relative4);
3188
- return outside ? null : relative4.split(path7.sep).join("/");
3276
+ const relative4 = path9.relative(home, path9.resolve(home, requested));
3277
+ const outside = relative4 === "" || relative4 === ".." || relative4.startsWith(`..${path9.sep}`) || path9.isAbsolute(relative4);
3278
+ return outside ? null : relative4.split(path9.sep).join("/");
3189
3279
  };
3190
3280
  var readSyncFiles = (home, paths_) => {
3191
3281
  const files = [];
@@ -3205,7 +3295,7 @@ var readSyncFiles = (home, paths_) => {
3205
3295
  }
3206
3296
  files.push({
3207
3297
  path: relative4,
3208
- contentsBase64: fs7.readFileSync(path7.join(home, relative4)).toString("base64"),
3298
+ contentsBase64: fs9.readFileSync(path9.join(home, relative4)).toString("base64"),
3209
3299
  // eslint-disable-next-line no-bitwise -- permission bits are the point
3210
3300
  mode: (stat.mode & 511).toString(8)
3211
3301
  });
@@ -3303,11 +3393,18 @@ var parseGitAuthorArgs = (args) => {
3303
3393
  };
3304
3394
  var gitAuthorLine = (author) => `${author.name} <${author.email}> \xB7 ${author.source === "setting" ? "your setting" : "your account's name and email"}`;
3305
3395
 
3396
+ // src/http-client.ts
3397
+ import { Agent, setGlobalDispatcher } from "undici";
3398
+ var cliDispatcher = (connect2) => new Agent({ allowH2: false, ...connect2 === void 0 ? {} : { connect: connect2 } });
3399
+ var useHttp1 = () => {
3400
+ setGlobalDispatcher(cliDispatcher());
3401
+ };
3402
+
3306
3403
  // src/landing.ts
3307
- import { spawnSync as spawnSync3 } from "node:child_process";
3308
- import * as fs8 from "node:fs";
3309
- import * as os4 from "node:os";
3310
- import * as path8 from "node:path";
3404
+ import { spawnSync as spawnSync4 } from "node:child_process";
3405
+ import * as fs10 from "node:fs";
3406
+ import * as os5 from "node:os";
3407
+ import * as path10 from "node:path";
3311
3408
  var paint = (code) => (text) => process.stdout.isTTY === true ? `[${code}m${text}[0m` : text;
3312
3409
  var dim = paint("2");
3313
3410
  var green = paint("32");
@@ -3522,7 +3619,7 @@ var landCommand = async (api2, args) => {
3522
3619
  if (!landingSucceeded(report)) process.exitCode = 1;
3523
3620
  };
3524
3621
  var git = (cwd, args) => {
3525
- const result = spawnSync3("git", args, { cwd, encoding: "utf8" });
3622
+ const result = spawnSync4("git", args, { cwd, encoding: "utf8" });
3526
3623
  return {
3527
3624
  status: result.status ?? 1,
3528
3625
  stdout: result.stdout ?? "",
@@ -3545,9 +3642,9 @@ var gitRemotes = (cwd) => {
3545
3642
  var remoteForOrigin = (remotes, originUrl, cwd) => {
3546
3643
  if (originUrl === null) return null;
3547
3644
  const origin = normalizeRemoteUrl(originUrl);
3548
- const originPath = origin === null ? path8.resolve(originUrl.replace(/^file:\/\//, "")) : null;
3645
+ const originPath = origin === null ? path10.resolve(originUrl.replace(/^file:\/\//, "")) : null;
3549
3646
  return remotes.find(
3550
- (remote) => origin === null ? path8.resolve(cwd, remote.url.replace(/^file:\/\//, "")) === originPath : normalizeRemoteUrl(remote.url) === origin
3647
+ (remote) => origin === null ? path10.resolve(cwd, remote.url.replace(/^file:\/\//, "")) === originPath : normalizeRemoteUrl(remote.url) === origin
3551
3648
  ) ?? null;
3552
3649
  };
3553
3650
  var LOG_LINES = 10;
@@ -3570,10 +3667,10 @@ var fetchBundle = (cwd, bundle) => {
3570
3667
  const before = git(cwd, ["rev-parse", "--verify", "--quiet", `${ref}^{commit}`]);
3571
3668
  const previous = before.status === 0 ? before.stdout.trim() : null;
3572
3669
  if (previous !== bundle.tip) {
3573
- const dir = fs8.mkdtempSync(path8.join(os4.tmpdir(), "mend-pull-"));
3670
+ const dir = fs10.mkdtempSync(path10.join(os5.tmpdir(), "mend-pull-"));
3574
3671
  try {
3575
- const file = path8.join(dir, "change.bundle");
3576
- fs8.writeFileSync(file, bundle.bytes, { mode: 384 });
3672
+ const file = path10.join(dir, "change.bundle");
3673
+ fs10.writeFileSync(file, bundle.bytes, { mode: 384 });
3577
3674
  const fetched = git(cwd, [
3578
3675
  "fetch",
3579
3676
  "--no-tags",
@@ -3583,7 +3680,7 @@ var fetchBundle = (cwd, bundle) => {
3583
3680
  ]);
3584
3681
  if (fetched.status !== 0) return refusedWith(gitWords(fetched));
3585
3682
  } finally {
3586
- fs8.rmSync(dir, { recursive: true, force: true });
3683
+ fs10.rmSync(dir, { recursive: true, force: true });
3587
3684
  }
3588
3685
  }
3589
3686
  const after = git(cwd, ["rev-parse", "--verify", "--quiet", `${ref}^{commit}`]).stdout.trim();
@@ -3774,7 +3871,7 @@ var followStart = async (options) => {
3774
3871
 
3775
3872
  // src/login.ts
3776
3873
  import { spawn as spawn2 } from "node:child_process";
3777
- import * as os5 from "node:os";
3874
+ import * as os6 from "node:os";
3778
3875
 
3779
3876
  // src/pair.ts
3780
3877
  var paint2 = (code) => (text) => process.stdout.isTTY === true ? `\x1B[${code}m${text}\x1B[0m` : text;
@@ -3966,7 +4063,7 @@ var resolveServerUrl = async (args, deps) => {
3966
4063
  };
3967
4064
  var loginCommand = async (args, deps) => {
3968
4065
  const base = await resolveServerUrl(args, deps);
3969
- const started = await post(`${base}/api/cli/auth`, { name: os5.hostname() });
4066
+ const started = await post(`${base}/api/cli/auth`, { name: os6.hostname() });
3970
4067
  if (started.status === 429) {
3971
4068
  return fail3(
3972
4069
  `the server asked for a pause \u2014 try again in ${retryAfterSecondsOf(started.json)}s`
@@ -4017,8 +4114,8 @@ var loginCommand = async (args, deps) => {
4017
4114
  };
4018
4115
 
4019
4116
  // src/organization.ts
4020
- import * as fs9 from "node:fs";
4021
- import * as path9 from "node:path";
4117
+ import * as fs11 from "node:fs";
4118
+ import * as path11 from "node:path";
4022
4119
  var paint4 = (code) => (text) => process.stdout.isTTY === true ? `[${code}m${text}[0m` : text;
4023
4120
  var dim4 = paint4("2");
4024
4121
  var green4 = paint4("32");
@@ -4082,7 +4179,7 @@ var scanFolder = (dir) => {
4082
4179
  const files = [];
4083
4180
  const skipped = [];
4084
4181
  const walk = (relative4) => {
4085
- const entries = fs9.readdirSync(path9.join(dir, relative4), { withFileTypes: true }).toSorted((a, b) => a.name.localeCompare(b.name));
4182
+ const entries = fs11.readdirSync(path11.join(dir, relative4), { withFileTypes: true }).toSorted((a, b) => a.name.localeCompare(b.name));
4086
4183
  for (const entry of entries) {
4087
4184
  const child = relative4 === "" ? entry.name : `${relative4}/${entry.name}`;
4088
4185
  if (entry.isSymbolicLink()) {
@@ -4091,7 +4188,7 @@ var scanFolder = (dir) => {
4091
4188
  if (SKIPPED_DIRECTORIES.has(entry.name)) skipped.push({ path: child, reason: "skipped" });
4092
4189
  else walk(child);
4093
4190
  } else if (entry.isFile()) {
4094
- const size = fs9.statSync(path9.join(dir, child)).size;
4191
+ const size = fs11.statSync(path11.join(dir, child)).size;
4095
4192
  if (size > FOLDER_FILE_BYTES) skipped.push({ path: child, reason: "over 1 MiB" });
4096
4193
  else files.push({ path: child, size });
4097
4194
  }
@@ -4144,7 +4241,7 @@ var folderCommand = async (api2, args) => {
4144
4241
  }
4145
4242
  case "push": {
4146
4243
  if (dir === void 0) return fail4("usage: mend folder push <name> <dir> [--replace]");
4147
- if (!fs9.existsSync(dir) || !fs9.statSync(dir).isDirectory()) {
4244
+ if (!fs11.existsSync(dir) || !fs11.statSync(dir).isDirectory()) {
4148
4245
  return fail4(`${dir} is not a directory`);
4149
4246
  }
4150
4247
  const folder = await folderNamed(api2, name);
@@ -4159,7 +4256,7 @@ var folderCommand = async (api2, args) => {
4159
4256
  files: batch.map((file) => ({
4160
4257
  path: file.path,
4161
4258
  // Read one batch at a time, so a large tree never sits in memory at once.
4162
- contentsBase64: fs9.readFileSync(path9.join(dir, file.path)).toString("base64")
4259
+ contentsBase64: fs11.readFileSync(path11.join(dir, file.path)).toString("base64")
4163
4260
  })),
4164
4261
  // --replace empties the folder with the first batch; the rest add to it.
4165
4262
  merge: !(replace && index === 0)
@@ -4343,8 +4440,8 @@ var operatorCommand = async (api2, tryApi, baseUrl, args) => {
4343
4440
  import { createHmac, randomBytes } from "node:crypto";
4344
4441
  import { readFile } from "node:fs/promises";
4345
4442
  import * as net2 from "node:net";
4346
- import * as os7 from "node:os";
4347
- import * as path11 from "node:path";
4443
+ import * as os8 from "node:os";
4444
+ import * as path13 from "node:path";
4348
4445
 
4349
4446
  // src/server-docker-volumes.ts
4350
4447
  import { createHash as createHash2 } from "node:crypto";
@@ -4562,9 +4659,9 @@ var verifyServerDockerVolumes = (runtime, input) => ownership(runtime, input, "v
4562
4659
 
4563
4660
  // src/server-store.ts
4564
4661
  import { randomUUID } from "node:crypto";
4565
- import * as fs10 from "node:fs";
4566
- import * as os6 from "node:os";
4567
- import * as path10 from "node:path";
4662
+ import * as fs12 from "node:fs";
4663
+ import * as os7 from "node:os";
4664
+ import * as path12 from "node:path";
4568
4665
  var ServerStoreError = class extends Error {
4569
4666
  _tag = "ServerStoreError";
4570
4667
  };
@@ -4585,28 +4682,28 @@ var attempt = (operation) => {
4585
4682
  var hasCode = (cause, code) => cause instanceof Error && "code" in cause && cause.code === code;
4586
4683
  var readOptional = (file) => {
4587
4684
  try {
4588
- return fs10.readFileSync(file, "utf8");
4685
+ return fs12.readFileSync(file, "utf8");
4589
4686
  } catch (cause) {
4590
4687
  if (hasCode(cause, "ENOENT")) return null;
4591
4688
  throw cause;
4592
4689
  }
4593
4690
  };
4594
4691
  var syncDirectory = (directory) => {
4595
- const fd = fs10.openSync(directory, "r");
4692
+ const fd = fs12.openSync(directory, "r");
4596
4693
  try {
4597
- fs10.fsyncSync(fd);
4694
+ fs12.fsyncSync(fd);
4598
4695
  } finally {
4599
- fs10.closeSync(fd);
4696
+ fs12.closeSync(fd);
4600
4697
  }
4601
4698
  };
4602
4699
  var writeDurable = (file, content, mode = 384) => {
4603
- const fd = fs10.openSync(file, "wx", mode);
4700
+ const fd = fs12.openSync(file, "wx", mode);
4604
4701
  try {
4605
- fs10.writeFileSync(fd, content, "utf8");
4606
- fs10.fchmodSync(fd, mode);
4607
- fs10.fsyncSync(fd);
4702
+ fs12.writeFileSync(fd, content, "utf8");
4703
+ fs12.fchmodSync(fd, mode);
4704
+ fs12.fsyncSync(fd);
4608
4705
  } finally {
4609
- fs10.closeSync(fd);
4706
+ fs12.closeSync(fd);
4610
4707
  }
4611
4708
  };
4612
4709
  var fileKeys = ["identity", "config", "env", "compose", "postgresInit"];
@@ -4626,11 +4723,11 @@ var parseLockOwner = (raw) => {
4626
4723
  };
4627
4724
  var describeOwner = (lockDir) => {
4628
4725
  try {
4629
- const raw = JSON.parse(fs10.readFileSync(path10.join(lockDir, "owner.json"), "utf8"));
4726
+ const raw = JSON.parse(fs12.readFileSync(path12.join(lockDir, "owner.json"), "utf8"));
4630
4727
  const owner = parseLockOwner(raw);
4631
4728
  if (owner === null) return "owner metadata is invalid";
4632
4729
  const label = `PID ${owner.pid} on ${owner.hostname}`;
4633
- if (owner.hostname !== os6.hostname()) return label;
4730
+ if (owner.hostname !== os7.hostname()) return label;
4634
4731
  try {
4635
4732
  process.kill(owner.pid, 0);
4636
4733
  return `${label} is still live`;
@@ -4646,28 +4743,28 @@ var lockGuidance = (lockDir) => new ServerStoreError(
4646
4743
  );
4647
4744
  var acquireLock = (configDir, create) => {
4648
4745
  if (create) {
4649
- fs10.mkdirSync(configDir, { recursive: true, mode: 448 });
4650
- fs10.chmodSync(configDir, 448);
4651
- } else if (!fs10.existsSync(configDir)) {
4746
+ fs12.mkdirSync(configDir, { recursive: true, mode: 448 });
4747
+ fs12.chmodSync(configDir, 448);
4748
+ } else if (!fs12.existsSync(configDir)) {
4652
4749
  throw new ServerStoreError(
4653
4750
  "No Mend server is configured. Run mend server setup explicitly to install one."
4654
4751
  );
4655
4752
  }
4656
- const lockDir = path10.join(configDir, "server.lock");
4753
+ const lockDir = path12.join(configDir, "server.lock");
4657
4754
  try {
4658
- fs10.mkdirSync(lockDir, { mode: 448 });
4755
+ fs12.mkdirSync(lockDir, { mode: 448 });
4659
4756
  } catch (cause) {
4660
4757
  if (hasCode(cause, "EEXIST")) throw lockGuidance(lockDir);
4661
4758
  throw cause;
4662
4759
  }
4663
- const owned = fs10.statSync(lockDir);
4664
- const ownerFile = path10.join(lockDir, "owner.json");
4665
- const owner = `${JSON.stringify({ pid: process.pid, hostname: os6.hostname(), token: randomUUID() })}
4760
+ const owned = fs12.statSync(lockDir);
4761
+ const ownerFile = path12.join(lockDir, "owner.json");
4762
+ const owner = `${JSON.stringify({ pid: process.pid, hostname: os7.hostname(), token: randomUUID() })}
4666
4763
  `;
4667
4764
  let open = true;
4668
4765
  const assertOwned = () => {
4669
- const current = fs10.statSync(lockDir);
4670
- if (!open || current.dev !== owned.dev || current.ino !== owned.ino || fs10.readFileSync(ownerFile, "utf8") !== owner) {
4766
+ const current = fs12.statSync(lockDir);
4767
+ if (!open || current.dev !== owned.dev || current.ino !== owned.ino || fs12.readFileSync(ownerFile, "utf8") !== owner) {
4671
4768
  throw new ServerStoreError(
4672
4769
  "Server lock ownership was lost. Stop and check for another server command before retrying."
4673
4770
  );
@@ -4683,8 +4780,8 @@ var acquireLock = (configDir, create) => {
4683
4780
  release: () => {
4684
4781
  const result = attempt(() => {
4685
4782
  assertOwned();
4686
- fs10.unlinkSync(ownerFile);
4687
- fs10.rmdirSync(lockDir);
4783
+ fs12.unlinkSync(ownerFile);
4784
+ fs12.rmdirSync(lockDir);
4688
4785
  });
4689
4786
  open = false;
4690
4787
  return result;
@@ -4693,7 +4790,7 @@ var acquireLock = (configDir, create) => {
4693
4790
  };
4694
4791
  var readIdentity = (paths) => {
4695
4792
  const identity = readOptional(paths.identity);
4696
- if (identity === null && (fs10.existsSync(paths.active) || fs10.existsSync(paths.generations) && fs10.readdirSync(paths.generations).length > 0)) {
4793
+ if (identity === null && (fs12.existsSync(paths.active) || fs12.existsSync(paths.generations) && fs12.readdirSync(paths.generations).length > 0)) {
4697
4794
  throw new ServerStoreError(
4698
4795
  "Server identity.env is missing. Restore it from a retained generation or backup; refusing to generate replacement credentials."
4699
4796
  );
@@ -4703,7 +4800,7 @@ var readIdentity = (paths) => {
4703
4800
  var readActive = (paths) => {
4704
4801
  let target;
4705
4802
  try {
4706
- target = fs10.readlinkSync(paths.active);
4803
+ target = fs12.readlinkSync(paths.active);
4707
4804
  } catch (cause) {
4708
4805
  if (hasCode(cause, "ENOENT")) return null;
4709
4806
  throw cause;
@@ -4713,13 +4810,13 @@ var readActive = (paths) => {
4713
4810
  "Server active pointer is invalid. Restore the symlink to a retained generation before retrying."
4714
4811
  );
4715
4812
  }
4716
- const directory = path10.join(paths.configDir, target);
4813
+ const directory = path12.join(paths.configDir, target);
4717
4814
  const files = {
4718
- identity: fs10.readFileSync(path10.join(directory, fileNames.identity), "utf8"),
4719
- config: fs10.readFileSync(path10.join(directory, fileNames.config), "utf8"),
4720
- env: fs10.readFileSync(path10.join(directory, fileNames.env), "utf8"),
4721
- compose: fs10.readFileSync(path10.join(directory, fileNames.compose), "utf8"),
4722
- postgresInit: fs10.readFileSync(path10.join(directory, fileNames.postgresInit), "utf8")
4815
+ identity: fs12.readFileSync(path12.join(directory, fileNames.identity), "utf8"),
4816
+ config: fs12.readFileSync(path12.join(directory, fileNames.config), "utf8"),
4817
+ env: fs12.readFileSync(path12.join(directory, fileNames.env), "utf8"),
4818
+ compose: fs12.readFileSync(path12.join(directory, fileNames.compose), "utf8"),
4819
+ postgresInit: fs12.readFileSync(path12.join(directory, fileNames.postgresInit), "utf8")
4723
4820
  };
4724
4821
  if (readIdentity(paths) !== files.identity) {
4725
4822
  throw new ServerStoreError(
@@ -4729,20 +4826,20 @@ var readActive = (paths) => {
4729
4826
  return { directory, files };
4730
4827
  };
4731
4828
  var publishIdentity = (paths, identity) => {
4732
- const temporary = path10.join(paths.configDir, `.identity-${randomUUID()}`);
4829
+ const temporary = path12.join(paths.configDir, `.identity-${randomUUID()}`);
4733
4830
  writeDurable(temporary, identity);
4734
- fs10.linkSync(temporary, paths.identity);
4831
+ fs12.linkSync(temporary, paths.identity);
4735
4832
  syncDirectory(paths.configDir);
4736
- fs10.unlinkSync(temporary);
4833
+ fs12.unlinkSync(temporary);
4737
4834
  };
4738
4835
  var prepareGeneration = (paths, files) => {
4739
- fs10.mkdirSync(paths.generations, { recursive: true, mode: 448 });
4836
+ fs12.mkdirSync(paths.generations, { recursive: true, mode: 448 });
4740
4837
  const generationName = `gen-${randomUUID()}`;
4741
- const directory = path10.join(paths.generations, generationName);
4742
- fs10.mkdirSync(directory, { mode: 448 });
4838
+ const directory = path12.join(paths.generations, generationName);
4839
+ fs12.mkdirSync(directory, { mode: 448 });
4743
4840
  for (const key of fileKeys) {
4744
4841
  writeDurable(
4745
- path10.join(directory, fileNames[key]),
4842
+ path12.join(directory, fileNames[key]),
4746
4843
  files[key],
4747
4844
  key === "postgresInit" ? 493 : 384
4748
4845
  );
@@ -4753,18 +4850,18 @@ var prepareGeneration = (paths, files) => {
4753
4850
  return { directory, files };
4754
4851
  };
4755
4852
  var activateGeneration = (paths, generation) => {
4756
- const relative4 = path10.relative(paths.configDir, generation.directory);
4757
- if (!/^generations\/gen-[0-9a-f-]{36}$/.test(relative4) || readIdentity(paths) !== fs10.readFileSync(path10.join(generation.directory, "identity.env"), "utf8")) {
4853
+ const relative4 = path12.relative(paths.configDir, generation.directory);
4854
+ if (!/^generations\/gen-[0-9a-f-]{36}$/.test(relative4) || readIdentity(paths) !== fs12.readFileSync(path12.join(generation.directory, "identity.env"), "utf8")) {
4758
4855
  throw new ServerStoreError("Cannot activate a generation outside this installation identity.");
4759
4856
  }
4760
4857
  for (const key of fileKeys) {
4761
- if (fs10.readFileSync(path10.join(generation.directory, fileNames[key]), "utf8") !== generation.files[key]) {
4858
+ if (fs12.readFileSync(path12.join(generation.directory, fileNames[key]), "utf8") !== generation.files[key]) {
4762
4859
  throw new ServerStoreError("Cannot activate an incomplete or changed server generation.");
4763
4860
  }
4764
4861
  }
4765
- const pointer = path10.join(paths.configDir, `.active-${randomUUID()}`);
4766
- fs10.symlinkSync(relative4, pointer);
4767
- fs10.renameSync(pointer, paths.active);
4862
+ const pointer = path12.join(paths.configDir, `.active-${randomUUID()}`);
4863
+ fs12.symlinkSync(relative4, pointer);
4864
+ fs12.renameSync(pointer, paths.active);
4768
4865
  syncDirectory(paths.configDir);
4769
4866
  };
4770
4867
  var prepareFiles = (paths, files) => {
@@ -4773,7 +4870,7 @@ var prepareFiles = (paths, files) => {
4773
4870
  throw new ServerStoreError("Server identity already exists; refusing to replace credentials.");
4774
4871
  }
4775
4872
  const active = readActive(paths);
4776
- if (active !== null && fileKeys.every((key) => files[key] === active.files[key]) && (fs10.statSync(path10.join(active.directory, fileNames.postgresInit)).mode & 4095) === 493)
4873
+ if (active !== null && fileKeys.every((key) => files[key] === active.files[key]) && (fs12.statSync(path12.join(active.directory, fileNames.postgresInit)).mode & 4095) === 493)
4777
4874
  return active;
4778
4875
  if (identity === null) publishIdentity(paths, files.identity);
4779
4876
  return prepareGeneration(paths, files);
@@ -4786,9 +4883,9 @@ var commitGeneration = (paths, files) => {
4786
4883
  var createStore = (configDir, lock) => {
4787
4884
  const paths = {
4788
4885
  configDir,
4789
- identity: path10.join(configDir, "identity.env"),
4790
- generations: path10.join(configDir, "generations"),
4791
- active: path10.join(configDir, "active")
4886
+ identity: path12.join(configDir, "identity.env"),
4887
+ generations: path12.join(configDir, "generations"),
4888
+ active: path12.join(configDir, "active")
4792
4889
  };
4793
4890
  const whileOwned = (operation) => attempt(() => {
4794
4891
  lock.assertOwned();
@@ -4801,13 +4898,13 @@ var createStore = (configDir, lock) => {
4801
4898
  prepare: (files) => whileOwned(() => prepareFiles(paths, files)),
4802
4899
  activate: (generation) => whileOwned(() => activateGeneration(paths, generation)),
4803
4900
  createBackup: (previous, target) => whileOwned(() => {
4804
- const backups = path10.join(configDir, "backups");
4805
- fs10.mkdirSync(backups, { recursive: true, mode: 448 });
4806
- fs10.chmodSync(backups, 448);
4807
- const directory = path10.join(backups, `upgrade-${randomUUID()}`);
4808
- fs10.mkdirSync(directory, { mode: 448 });
4901
+ const backups = path12.join(configDir, "backups");
4902
+ fs12.mkdirSync(backups, { recursive: true, mode: 448 });
4903
+ fs12.chmodSync(backups, 448);
4904
+ const directory = path12.join(backups, `upgrade-${randomUUID()}`);
4905
+ fs12.mkdirSync(directory, { mode: 448 });
4809
4906
  writeDurable(
4810
- path10.join(directory, "recovery.json"),
4907
+ path12.join(directory, "recovery.json"),
4811
4908
  `${JSON.stringify(
4812
4909
  {
4813
4910
  previousGeneration: previous.directory,
@@ -4823,21 +4920,21 @@ var createStore = (configDir, lock) => {
4823
4920
  syncDirectory(directory);
4824
4921
  syncDirectory(backups);
4825
4922
  syncDirectory(configDir);
4826
- const partialFile = path10.join(directory, "database.sql.partial");
4923
+ const partialFile = path12.join(directory, "database.sql.partial");
4827
4924
  return {
4828
4925
  directory,
4829
4926
  partialFile,
4830
4927
  complete: () => whileOwned(() => {
4831
- if (fs10.statSync(partialFile).size === 0)
4928
+ if (fs12.statSync(partialFile).size === 0)
4832
4929
  throw new ServerStoreError("Database backup is empty; refusing target startup.");
4833
- const fd = fs10.openSync(partialFile, "r");
4930
+ const fd = fs12.openSync(partialFile, "r");
4834
4931
  try {
4835
- fs10.fchmodSync(fd, 384);
4836
- fs10.fsyncSync(fd);
4932
+ fs12.fchmodSync(fd, 384);
4933
+ fs12.fsyncSync(fd);
4837
4934
  } finally {
4838
- fs10.closeSync(fd);
4935
+ fs12.closeSync(fd);
4839
4936
  }
4840
- fs10.renameSync(partialFile, path10.join(directory, "database.sql"));
4937
+ fs12.renameSync(partialFile, path12.join(directory, "database.sql"));
4841
4938
  syncDirectory(directory);
4842
4939
  })
4843
4940
  };
@@ -4846,7 +4943,7 @@ var createStore = (configDir, lock) => {
4846
4943
  };
4847
4944
  var refuseFlatLayout = (configDir) => {
4848
4945
  if (["server.json", "server.env", "compose.yaml", "postgres-init.sh"].some(
4849
- (name) => fs10.existsSync(path10.join(configDir, name))
4946
+ (name) => fs12.existsSync(path12.join(configDir, name))
4850
4947
  )) {
4851
4948
  throw new ServerStoreError(
4852
4949
  "Unreleased flat server configuration found. Preserve its credentials and volumes; migrate it to the generation layout before retrying. Setup will not replace this identity."
@@ -4854,7 +4951,7 @@ var refuseFlatLayout = (configDir) => {
4854
4951
  }
4855
4952
  };
4856
4953
  var withServerStore = async (directory, operation, options = {}) => {
4857
- const configDir = path10.resolve(directory);
4954
+ const configDir = path12.resolve(directory);
4858
4955
  let lock;
4859
4956
  let result;
4860
4957
  try {
@@ -4871,9 +4968,9 @@ var withServerStore = async (directory, operation, options = {}) => {
4871
4968
  };
4872
4969
 
4873
4970
  // src/version.ts
4874
- import * as fs11 from "node:fs";
4971
+ import * as fs13 from "node:fs";
4875
4972
  var cliVersion = () => {
4876
- const raw = fs11.readFileSync(new URL("../package.json", import.meta.url), "utf8");
4973
+ const raw = fs13.readFileSync(new URL("../package.json", import.meta.url), "utf8");
4877
4974
  const parsed = JSON.parse(raw);
4878
4975
  if (typeof parsed === "object" && parsed !== null && "version" in parsed) {
4879
4976
  const version = parsed.version;
@@ -5576,7 +5673,7 @@ var resolveServerVersion = async (runtime, options, existing) => {
5576
5673
  return version;
5577
5674
  };
5578
5675
  var parseDockerSocketPath = (socket) => {
5579
- if (!path11.isAbsolute(socket) || /[\r\n$'"#:\\]/.test(socket)) {
5676
+ if (!path13.isAbsolute(socket) || /[\r\n$'"#:\\]/.test(socket)) {
5580
5677
  throw setupError(
5581
5678
  "--docker-socket must be an absolute path without line breaks or Compose interpolation characters."
5582
5679
  );
@@ -5602,8 +5699,8 @@ var resolveAssets = async (runtime, serverVersion, existing, store, options) =>
5602
5699
  if (options.assetsDir !== void 0) {
5603
5700
  try {
5604
5701
  const [compose2, postgresInit2] = await Promise.all([
5605
- readFile(path11.join(options.assetsDir, COMPOSE_ASSET), "utf8"),
5606
- readFile(path11.join(options.assetsDir, POSTGRES_INIT_ASSET), "utf8")
5702
+ readFile(path13.join(options.assetsDir, COMPOSE_ASSET), "utf8"),
5703
+ readFile(path13.join(options.assetsDir, POSTGRES_INIT_ASSET), "utf8")
5607
5704
  ]);
5608
5705
  validateComposeAsset(compose2);
5609
5706
  validatePostgresAsset(postgresInit2);
@@ -6129,10 +6226,10 @@ var manageServer = async (command, args, runtime, store) => {
6129
6226
  };
6130
6227
  var nodeServerRuntime = () => {
6131
6228
  const environment = { ...process.env };
6132
- const home = os7.homedir();
6133
- const configHome = environment["XDG_CONFIG_HOME"] ?? path11.join(home, ".config");
6229
+ const home = os8.homedir();
6230
+ const configHome = environment["XDG_CONFIG_HOME"] ?? path13.join(home, ".config");
6134
6231
  return {
6135
- configDir: path11.join(configHome, "mend"),
6232
+ configDir: path13.join(configHome, "mend"),
6136
6233
  platform: process.platform,
6137
6234
  cliVersion: cliVersion(),
6138
6235
  run: (command, args, options) => runServerProcess(command, args, environment, options),
@@ -6585,8 +6682,8 @@ var createServiceTunnels = (options) => {
6585
6682
  };
6586
6683
 
6587
6684
  // src/skills.ts
6588
- import * as fs12 from "node:fs";
6589
- import * as path12 from "node:path";
6685
+ import * as fs14 from "node:fs";
6686
+ import * as path14 from "node:path";
6590
6687
  var DEFAULT_SKILLS_DIR = ".agents/skills";
6591
6688
  var MAX_SKILL_FILES = 64;
6592
6689
  var MAX_SKILL_FILE_BYTES = 512 * 1024;
@@ -6609,12 +6706,12 @@ var readFrontmatterDescription = (contents) => {
6609
6706
  var walkFiles = (root) => {
6610
6707
  const found = [];
6611
6708
  const visit = (dir) => {
6612
- for (const entry of fs12.readdirSync(dir, { withFileTypes: true })) {
6709
+ for (const entry of fs14.readdirSync(dir, { withFileTypes: true })) {
6613
6710
  if (IGNORED_DIRS.has(entry.name)) continue;
6614
- const absolute = path12.join(dir, entry.name);
6711
+ const absolute = path14.join(dir, entry.name);
6615
6712
  let stat;
6616
6713
  try {
6617
- stat = fs12.statSync(absolute);
6714
+ stat = fs14.statSync(absolute);
6618
6715
  } catch {
6619
6716
  continue;
6620
6717
  }
@@ -6628,7 +6725,7 @@ var walkFiles = (root) => {
6628
6725
  var scanSkillLibrary = (root) => {
6629
6726
  let entries;
6630
6727
  try {
6631
- entries = fs12.readdirSync(root, { withFileTypes: true });
6728
+ entries = fs14.readdirSync(root, { withFileTypes: true });
6632
6729
  } catch {
6633
6730
  return { error: `${root} is not a readable directory` };
6634
6731
  }
@@ -6636,23 +6733,23 @@ var scanSkillLibrary = (root) => {
6636
6733
  const notes = [];
6637
6734
  for (const entry of entries.toSorted((a, b) => a.name.localeCompare(b.name))) {
6638
6735
  if (entry.name.startsWith(".")) continue;
6639
- const skillDir = path12.join(root, entry.name);
6736
+ const skillDir = path14.join(root, entry.name);
6640
6737
  let stat;
6641
6738
  try {
6642
- stat = fs12.statSync(skillDir);
6739
+ stat = fs14.statSync(skillDir);
6643
6740
  } catch {
6644
6741
  continue;
6645
6742
  }
6646
6743
  if (!stat.isDirectory()) continue;
6647
- if (!fs12.existsSync(path12.join(skillDir, "SKILL.md"))) {
6744
+ if (!fs14.existsSync(path14.join(skillDir, "SKILL.md"))) {
6648
6745
  notes.push({ skill: entry.name, message: "no SKILL.md \u2014 skipped" });
6649
6746
  continue;
6650
6747
  }
6651
6748
  const files = [];
6652
6749
  let bytes = 0;
6653
6750
  for (const absolute of walkFiles(skillDir)) {
6654
- const relative4 = path12.relative(skillDir, absolute).split(path12.sep).join("/");
6655
- const buffer = fs12.readFileSync(absolute);
6751
+ const relative4 = path14.relative(skillDir, absolute).split(path14.sep).join("/");
6752
+ const buffer = fs14.readFileSync(absolute);
6656
6753
  if (buffer.byteLength > MAX_SKILL_FILE_BYTES) {
6657
6754
  notes.push({ skill: entry.name, message: `${relative4} is over 512KB \u2014 skipped` });
6658
6755
  continue;
@@ -6687,16 +6784,16 @@ var scanSkillLibrary = (root) => {
6687
6784
  };
6688
6785
 
6689
6786
  // src/ssh-setup.ts
6690
- import * as os9 from "node:os";
6691
- import * as path14 from "node:path";
6787
+ import * as os10 from "node:os";
6788
+ import * as path16 from "node:path";
6692
6789
 
6693
6790
  // ../../packages/workspace-ssh/src/index.ts
6694
- import { spawnSync as spawnSync4 } from "node:child_process";
6791
+ import { spawnSync as spawnSync5 } from "node:child_process";
6695
6792
  import { createHash as createHash3 } from "node:crypto";
6696
- import * as fs13 from "node:fs";
6793
+ import * as fs15 from "node:fs";
6697
6794
  import { isIP as isIP2 } from "node:net";
6698
- import * as os8 from "node:os";
6699
- import * as path13 from "node:path";
6795
+ import * as os9 from "node:os";
6796
+ import * as path15 from "node:path";
6700
6797
  var LEGACY_BLOCK_BEGIN = "# >>> mend workspace ssh (managed by `mend ssh setup`) >>>";
6701
6798
  var LEGACY_BLOCK_END = "# <<< mend workspace ssh <<<";
6702
6799
  var WorkspaceSshError = class extends Error {
@@ -6783,8 +6880,8 @@ var blockBegin = (alias) => `# >>> mend workspace ssh ${alias} (managed) >>>`;
6783
6880
  var blockEnd = (alias) => `# <<< mend workspace ssh ${alias} <<<`;
6784
6881
  var hasControls = (value) => /[\p{Cc}\p{Zl}\p{Zp}]/u.test(value);
6785
6882
  var parseIdentityPath = (value) => {
6786
- const resolved = path13.resolve(
6787
- value.startsWith("~/") ? path13.join(os8.homedir(), value.slice(2)) : value
6883
+ const resolved = path15.resolve(
6884
+ value.startsWith("~/") ? path15.join(os9.homedir(), value.slice(2)) : value
6788
6885
  );
6789
6886
  if (value === "" || hasControls(value) || hasControls(resolved) || value.includes("${") || resolved.includes("${")) {
6790
6887
  return failure(
@@ -6930,7 +7027,7 @@ var workspaceSshPublicKeyFingerprint = (publicKey) => {
6930
7027
  var publicKeyIdentity = (publicKey) => publicKey.trim().split(/\s+/).slice(0, 2).join(" ");
6931
7028
  var agentKeys = () => {
6932
7029
  if (!process.env["SSH_AUTH_SOCK"]) return [];
6933
- const listed = spawnSync4("ssh-add", ["-L"], {
7030
+ const listed = spawnSync5("ssh-add", ["-L"], {
6934
7031
  encoding: "utf8",
6935
7032
  timeout: 3e3,
6936
7033
  stdio: ["ignore", "pipe", "pipe"],
@@ -6940,7 +7037,7 @@ var agentKeys = () => {
6940
7037
  };
6941
7038
  var readText = (file) => {
6942
7039
  try {
6943
- return success(fs13.readFileSync(file, "utf8"));
7040
+ return success(fs15.readFileSync(file, "utf8"));
6944
7041
  } catch (cause) {
6945
7042
  const error = cause instanceof Error && "code" in cause ? cause.code : void 0;
6946
7043
  return error === "ENOENT" ? success("") : failure(new WorkspaceSshError("key", `Could not read ${file}.`, cause));
@@ -6967,7 +7064,7 @@ var readRequiredKey = (keyPath, source) => {
6967
7064
  const privatePath = publicPath.slice(0, -".pub".length);
6968
7065
  const read = readText(publicPath);
6969
7066
  if (!read.ok) return read;
6970
- const derived = spawnSync4("ssh-keygen", ["-y", "-P", "", "-f", privatePath], {
7067
+ const derived = spawnSync5("ssh-keygen", ["-y", "-P", "", "-f", privatePath], {
6971
7068
  encoding: "utf8",
6972
7069
  timeout: 3e3,
6973
7070
  stdio: ["ignore", "pipe", "pipe"],
@@ -6998,19 +7095,19 @@ var readRequiredKey = (keyPath, source) => {
6998
7095
  var readOptionalKey = (keyPath) => {
6999
7096
  const parsed = parseIdentityPath(keyPath);
7000
7097
  if (!parsed.ok) return parsed;
7001
- if (!fs13.existsSync(parsed.value) && !fs13.existsSync(publicKeyPath(parsed.value)))
7098
+ if (!fs15.existsSync(parsed.value) && !fs15.existsSync(publicKeyPath(parsed.value)))
7002
7099
  return success(null);
7003
7100
  return readRequiredKey(parsed.value, "existing");
7004
7101
  };
7005
7102
  var pinAgentKey = (configHome, publicKey) => {
7006
- const identityFile = path13.resolve(
7103
+ const identityFile = path15.resolve(
7007
7104
  configHome,
7008
7105
  "ssh",
7009
7106
  `agent-${hashIdentity(publicKeyIdentity(publicKey))}.pub`
7010
7107
  );
7011
7108
  try {
7012
- fs13.mkdirSync(path13.dirname(identityFile), { recursive: true, mode: 448 });
7013
- fs13.writeFileSync(identityFile, `${publicKey}
7109
+ fs15.mkdirSync(path15.dirname(identityFile), { recursive: true, mode: 448 });
7110
+ fs15.writeFileSync(identityFile, `${publicKey}
7014
7111
  `, { mode: 384 });
7015
7112
  return success({ publicKey, identityFile, source: "agent" });
7016
7113
  } catch (cause) {
@@ -7021,15 +7118,15 @@ var pinAgentKey = (configHome, publicKey) => {
7021
7118
  };
7022
7119
  var generateDedicatedKey = (privatePath) => {
7023
7120
  try {
7024
- fs13.mkdirSync(path13.dirname(privatePath), { recursive: true, mode: 448 });
7121
+ fs15.mkdirSync(path15.dirname(privatePath), { recursive: true, mode: 448 });
7025
7122
  } catch (cause) {
7026
7123
  return failure(
7027
- new WorkspaceSshError("key", `Could not create ${path13.dirname(privatePath)}.`, cause)
7124
+ new WorkspaceSshError("key", `Could not create ${path15.dirname(privatePath)}.`, cause)
7028
7125
  );
7029
7126
  }
7030
- const generated = spawnSync4(
7127
+ const generated = spawnSync5(
7031
7128
  "ssh-keygen",
7032
- ["-t", "ed25519", "-f", privatePath, "-N", "", "-C", `mend-${os8.hostname()}`],
7129
+ ["-t", "ed25519", "-f", privatePath, "-N", "", "-C", `mend-${os9.hostname()}`],
7033
7130
  { encoding: "utf8", timeout: 3e3, stdio: ["ignore", "pipe", "pipe"] }
7034
7131
  );
7035
7132
  if (generated.status !== 0) {
@@ -7053,7 +7150,7 @@ var generateDedicatedKey = (privatePath) => {
7053
7150
  return fresh;
7054
7151
  };
7055
7152
  var dedicatedKey = (configHome, create) => {
7056
- const privatePath = path13.join(configHome, "ssh", "id_ed25519");
7153
+ const privatePath = path15.join(configHome, "ssh", "id_ed25519");
7057
7154
  const existing = readOptionalKey(privatePath);
7058
7155
  if (existing.ok === false) return failure(existing.error);
7059
7156
  if (existing.value !== null || !create) return existing;
@@ -7101,10 +7198,10 @@ var writeWorkspaceSshConfig = (configFile, target, identityFile) => {
7101
7198
  const reconciled = reconcileWorkspaceSshConfig(before.value, target, identityFile);
7102
7199
  if (reconciled.ok === false) return failure(reconciled.error);
7103
7200
  try {
7104
- fs13.mkdirSync(path13.dirname(configFile), { recursive: true, mode: 448 });
7105
- fs13.chmodSync(path13.dirname(configFile), 448);
7106
- fs13.writeFileSync(configFile, reconciled.value, { mode: 384 });
7107
- fs13.chmodSync(configFile, 384);
7201
+ fs15.mkdirSync(path15.dirname(configFile), { recursive: true, mode: 448 });
7202
+ fs15.chmodSync(path15.dirname(configFile), 448);
7203
+ fs15.writeFileSync(configFile, reconciled.value, { mode: 384 });
7204
+ fs15.chmodSync(configFile, 384);
7108
7205
  return success(void 0);
7109
7206
  } catch (cause) {
7110
7207
  return failure(new WorkspaceSshError("config", `Could not write ${configFile}.`, cause));
@@ -7117,7 +7214,7 @@ var dim5 = ansi("2");
7117
7214
  var green5 = ansi("32");
7118
7215
  var warn = ansi("33");
7119
7216
  var say5 = (line) => console.log(line);
7120
- var sshConfigPath = () => path14.join(os9.homedir(), ".ssh", "config");
7217
+ var sshConfigPath = () => path16.join(os10.homedir(), ".ssh", "config");
7121
7218
  var flagValue2 = (args, flag) => {
7122
7219
  const index = args.indexOf(flag);
7123
7220
  return index === -1 || args[index + 1] === void 0 ? null : String(args[index + 1]);
@@ -7187,7 +7284,7 @@ var setup = async (api2, cliHome, serverUrl, args) => {
7187
7284
  if (picked.value === null) return showFailure("No workspace SSH key is available.");
7188
7285
  const registered = await api2("POST", "/workspace-ssh/keys", {
7189
7286
  publicKey: picked.value.publicKey,
7190
- name: os9.hostname()
7287
+ name: os10.hostname()
7191
7288
  });
7192
7289
  const sourceLabel = {
7193
7290
  explicit: "from --key",
@@ -7229,8 +7326,8 @@ var sshCommand = async (args, api2, cliHome, serverUrl) => {
7229
7326
  };
7230
7327
 
7231
7328
  // src/uninstall.ts
7232
- import * as fs14 from "node:fs";
7233
- import * as path15 from "node:path";
7329
+ import * as fs16 from "node:fs";
7330
+ import * as path17 from "node:path";
7234
7331
  var UNINSTALL_USAGE = "usage: mend uninstall [--all | --server | --home] [--yes]";
7235
7332
  var parseUninstallArgs = (args) => {
7236
7333
  let scope = null;
@@ -7252,14 +7349,14 @@ var parseUninstallArgs = (args) => {
7252
7349
  var SERVER_FILES = ["identity.env", "active", "generations", "backups"];
7253
7350
  var countEntries = (directory) => {
7254
7351
  try {
7255
- return fs14.readdirSync(directory).length;
7352
+ return fs16.readdirSync(directory).length;
7256
7353
  } catch {
7257
7354
  return 0;
7258
7355
  }
7259
7356
  };
7260
7357
  var exists = (file) => {
7261
7358
  try {
7262
- fs14.lstatSync(file);
7359
+ fs16.lstatSync(file);
7263
7360
  return true;
7264
7361
  } catch {
7265
7362
  return false;
@@ -7268,7 +7365,7 @@ var exists = (file) => {
7268
7365
  var managedBlockCount = (sshConfigFile) => {
7269
7366
  let config;
7270
7367
  try {
7271
- config = fs14.readFileSync(sshConfigFile, "utf8");
7368
+ config = fs16.readFileSync(sshConfigFile, "utf8");
7272
7369
  } catch {
7273
7370
  return 0;
7274
7371
  }
@@ -7292,27 +7389,27 @@ var describeUninstall = async (runtime, scope) => {
7292
7389
  if (!read.error.message.startsWith("No Mend server is configured")) throw read.error;
7293
7390
  server = "none";
7294
7391
  } else if (read.value === null) {
7295
- server = exists(path15.join(configDir, "identity.env")) ? {
7392
+ server = exists(path17.join(configDir, "identity.env")) ? {
7296
7393
  version: "(no active generation)",
7297
7394
  appUrl: "",
7298
7395
  dockerContext: "",
7299
- generations: countEntries(path15.join(configDir, "generations")),
7300
- backups: countEntries(path15.join(configDir, "backups"))
7396
+ generations: countEntries(path17.join(configDir, "generations")),
7397
+ backups: countEntries(path17.join(configDir, "backups"))
7301
7398
  } : "none";
7302
7399
  } else {
7303
7400
  server = {
7304
7401
  version: read.value.config.serverVersion,
7305
7402
  appUrl: read.value.config.appUrl,
7306
7403
  dockerContext: read.value.config.dockerContext,
7307
- generations: countEntries(path15.join(configDir, "generations")),
7308
- backups: countEntries(path15.join(configDir, "backups"))
7404
+ generations: countEntries(path17.join(configDir, "generations")),
7405
+ backups: countEntries(path17.join(configDir, "backups"))
7309
7406
  };
7310
7407
  }
7311
7408
  }
7312
7409
  let home = null;
7313
7410
  if (scope !== "server") {
7314
- const cliConfig = path15.join(runtime.cliHome, "cli.json");
7315
- const sshDirectory = path15.join(runtime.cliHome, "ssh");
7411
+ const cliConfig = path17.join(runtime.cliHome, "cli.json");
7412
+ const sshDirectory = path17.join(runtime.cliHome, "ssh");
7316
7413
  home = {
7317
7414
  cliConfig: exists(cliConfig) ? cliConfig : null,
7318
7415
  sshDirectory: exists(sshDirectory) ? sshDirectory : null,
@@ -7444,7 +7541,7 @@ var removeServer = async (runtime, failures, leftovers) => {
7444
7541
  }
7445
7542
  }
7446
7543
  for (const name of SERVER_FILES) {
7447
- fs14.rmSync(path15.join(configDir, name), { recursive: true, force: true });
7544
+ fs16.rmSync(path17.join(configDir, name), { recursive: true, force: true });
7448
7545
  }
7449
7546
  server.writeLine(`removed ${configDir}/{identity.env, active, generations, backups}`);
7450
7547
  },
@@ -7455,20 +7552,20 @@ var removeServer = async (runtime, failures, leftovers) => {
7455
7552
  var removeHome = async (runtime, plan, failures, leftovers) => {
7456
7553
  const { server } = runtime;
7457
7554
  if (plan.cliConfig !== null) {
7458
- fs14.rmSync(plan.cliConfig, { force: true });
7555
+ fs16.rmSync(plan.cliConfig, { force: true });
7459
7556
  server.writeLine(`removed ${plan.cliConfig}`);
7460
7557
  }
7461
7558
  if (plan.sshDirectory !== null) {
7462
- fs14.rmSync(plan.sshDirectory, { recursive: true, force: true });
7559
+ fs16.rmSync(plan.sshDirectory, { recursive: true, force: true });
7463
7560
  server.writeLine(`removed ${plan.sshDirectory}`);
7464
7561
  }
7465
7562
  if (plan.managedSshBlocks > 0) {
7466
7563
  try {
7467
- const before = fs14.readFileSync(runtime.sshConfigFile, "utf8");
7564
+ const before = fs16.readFileSync(runtime.sshConfigFile, "utf8");
7468
7565
  const stripped = stripManagedWorkspaceSshBlocks(before);
7469
7566
  if (!stripped.ok) throw stripped.error;
7470
7567
  if (stripped.value.removed > 0) {
7471
- fs14.writeFileSync(runtime.sshConfigFile, stripped.value.config, { mode: 384 });
7568
+ fs16.writeFileSync(runtime.sshConfigFile, stripped.value.config, { mode: 384 });
7472
7569
  server.writeLine(
7473
7570
  `removed ${plural(stripped.value.removed, "managed block")} from ${runtime.sshConfigFile}`
7474
7571
  );
@@ -7481,12 +7578,12 @@ var removeHome = async (runtime, plan, failures, leftovers) => {
7481
7578
  }
7482
7579
  let remaining = [];
7483
7580
  try {
7484
- remaining = fs14.readdirSync(runtime.cliHome);
7581
+ remaining = fs16.readdirSync(runtime.cliHome);
7485
7582
  } catch {
7486
7583
  return;
7487
7584
  }
7488
7585
  if (remaining.length === 0) {
7489
- fs14.rmdirSync(runtime.cliHome);
7586
+ fs16.rmdirSync(runtime.cliHome);
7490
7587
  server.writeLine(`removed ${runtime.cliHome}`);
7491
7588
  } else {
7492
7589
  leftovers.push(
@@ -7550,19 +7647,19 @@ var upgradeUrl = async (input) => {
7550
7647
  // src/main.ts
7551
7648
  var mendCliHome = () => {
7552
7649
  const xdg = process.env["XDG_CONFIG_HOME"];
7553
- const preferred = path16.join(
7554
- xdg === void 0 || xdg === "" ? path16.join(os10.homedir(), ".config") : xdg,
7650
+ const preferred = path18.join(
7651
+ xdg === void 0 || xdg === "" ? path18.join(os11.homedir(), ".config") : xdg,
7555
7652
  "mend"
7556
7653
  );
7557
- const legacy = path16.join(os10.homedir(), ".mend");
7558
- return !fs15.existsSync(preferred) && fs15.existsSync(legacy) ? legacy : preferred;
7654
+ const legacy = path18.join(os11.homedir(), ".mend");
7655
+ return !fs17.existsSync(preferred) && fs17.existsSync(legacy) ? legacy : preferred;
7559
7656
  };
7560
- var CONFIG_PATH = path16.join(mendCliHome(), "cli.json");
7657
+ var CONFIG_PATH = path18.join(mendCliHome(), "cli.json");
7561
7658
  var loadConfig = () => {
7562
7659
  let fileConfig = {};
7563
- if (fs15.existsSync(CONFIG_PATH)) {
7660
+ if (fs17.existsSync(CONFIG_PATH)) {
7564
7661
  try {
7565
- fileConfig = JSON.parse(fs15.readFileSync(CONFIG_PATH, "utf8"));
7662
+ fileConfig = JSON.parse(fs17.readFileSync(CONFIG_PATH, "utf8"));
7566
7663
  } catch {
7567
7664
  fail6(`could not parse ${CONFIG_PATH}`);
7568
7665
  }
@@ -7814,7 +7911,7 @@ var adopt = async (config, args) => {
7814
7911
  }
7815
7912
  const sourceIssue = repositoryCloneUrlIssue(source);
7816
7913
  if (sourceIssue !== null) return fail6(sourceIssue);
7817
- const projectName = name ?? normalizeProjectName(path16.basename(source, ".git"));
7914
+ const projectName = name ?? normalizeProjectName(path18.basename(source, ".git"));
7818
7915
  const auth = authFlagIndex !== -1 && args[authFlagIndex + 1] !== void 0 ? String(args[authFlagIndex + 1]) : null;
7819
7916
  if (auth !== null && auth !== "ambient" && auth !== "mend-key" && auth !== "bridge") {
7820
7917
  return fail6(`--auth takes "ambient", "mend-key", or "bridge", not "${auth}"`);
@@ -7863,7 +7960,7 @@ var findProject = async (config, explicit, adoptCwd = false) => {
7863
7960
  const sourceIssue = repositoryCloneUrlIssue(facts.originUrl);
7864
7961
  if (sourceIssue !== null) return fail6(sourceIssue);
7865
7962
  const adopted = await api(config, "POST", "/projects", {
7866
- name: normalizeProjectName(path16.basename(facts.repoRoot)),
7963
+ name: normalizeProjectName(path18.basename(facts.repoRoot)),
7867
7964
  source: facts.originUrl
7868
7965
  });
7869
7966
  say6(`${green6("\u2713")} adopted \xB7 ${adopted.name} \xB7 ${dim6(adopted.storePath)}`);
@@ -8824,13 +8921,13 @@ var serviceRestart = async (config, args) => {
8824
8921
  };
8825
8922
  var serviceInit = async (args) => {
8826
8923
  const root = gitTopLevel(process.cwd()) ?? process.cwd();
8827
- const target = path16.join(root, "mend.toml");
8828
- if (fs15.existsSync(target)) {
8924
+ const target = path18.join(root, "mend.toml");
8925
+ if (fs17.existsSync(target)) {
8829
8926
  return fail6(`${target} already exists \u2014 edit it directly (init never merges)`);
8830
8927
  }
8831
- const rootFiles = fs15.readdirSync(root);
8928
+ const rootFiles = fs17.readdirSync(root);
8832
8929
  const proposals = [];
8833
- const readRoot = (name) => fs15.readFileSync(path16.join(root, name), "utf8");
8930
+ const readRoot = (name) => fs17.readFileSync(path18.join(root, name), "utf8");
8834
8931
  if (rootFiles.includes("package.json")) {
8835
8932
  proposals.push(...proposeFromPackageJson(readRoot("package.json"), rootFiles));
8836
8933
  }
@@ -8840,13 +8937,13 @@ var serviceInit = async (args) => {
8840
8937
  );
8841
8938
  for (const glob of globs) {
8842
8939
  const parent = glob.replace(/\/?\*+$/, "");
8843
- const dirs = glob.endsWith("*") ? fs15.existsSync(path16.join(root, parent)) ? fs15.readdirSync(path16.join(root, parent)).map((dir) => path16.join(parent, dir)) : [] : [glob];
8940
+ const dirs = glob.endsWith("*") ? fs17.existsSync(path18.join(root, parent)) ? fs17.readdirSync(path18.join(root, parent)).map((dir) => path18.join(parent, dir)) : [] : [glob];
8844
8941
  for (const dir of dirs) {
8845
- const manifest = path16.join(root, dir, "package.json");
8846
- if (!fs15.existsSync(manifest)) continue;
8942
+ const manifest = path18.join(root, dir, "package.json");
8943
+ if (!fs17.existsSync(manifest)) continue;
8847
8944
  for (const proposal of proposeFromWorkspacePackage(
8848
- path16.basename(dir),
8849
- fs15.readFileSync(manifest, "utf8"),
8945
+ path18.basename(dir),
8946
+ fs17.readFileSync(manifest, "utf8"),
8850
8947
  rootFiles
8851
8948
  )) {
8852
8949
  if (!proposals.some((existing) => existing.name === proposal.name)) {
@@ -8890,7 +8987,7 @@ var serviceInit = async (args) => {
8890
8987
  return;
8891
8988
  }
8892
8989
  }
8893
- fs15.writeFileSync(target, toml);
8990
+ fs17.writeFileSync(target, toml);
8894
8991
  say6(`${green6("\u2713")} wrote ${target} \u2014 commit it, then: mend service run ${proposals[0]?.name}`);
8895
8992
  };
8896
8993
  var tunnelServices = async (config, services, portOverride) => {
@@ -8994,23 +9091,23 @@ var serviceCommand = async (config, args) => {
8994
9091
  }
8995
9092
  };
8996
9093
  var isProvider = (value) => value === "claude" || value === "codex" || value === "github";
8997
- var readIfExists = (file) => fs15.existsSync(file) ? fs15.readFileSync(file, "utf8") : null;
9094
+ var readIfExists = (file) => fs17.existsSync(file) ? fs17.readFileSync(file, "utf8") : null;
8998
9095
  var localCredential = (provider) => {
8999
- const home = os10.homedir();
9096
+ const home = os11.homedir();
9000
9097
  switch (provider) {
9001
9098
  case "codex":
9002
9099
  return readIfExists(
9003
- path16.join(process.env["CODEX_HOME"] ?? path16.join(home, ".codex"), "auth.json")
9100
+ path18.join(process.env["CODEX_HOME"] ?? path18.join(home, ".codex"), "auth.json")
9004
9101
  );
9005
9102
  case "claude":
9006
9103
  return readIfExists(
9007
- path16.join(
9008
- process.env["CLAUDE_CONFIG_DIR"] ?? path16.join(home, ".claude"),
9104
+ path18.join(
9105
+ process.env["CLAUDE_CONFIG_DIR"] ?? path18.join(home, ".claude"),
9009
9106
  ".credentials.json"
9010
9107
  )
9011
9108
  );
9012
9109
  case "github": {
9013
- const result = spawnSync5("gh", ["auth", "token"], { encoding: "utf8" });
9110
+ const result = spawnSync6("gh", ["auth", "token"], { encoding: "utf8" });
9014
9111
  const token = result.status === 0 ? result.stdout.trim() : "";
9015
9112
  return token === "" ? null : token;
9016
9113
  }
@@ -9022,7 +9119,7 @@ var accountLine = (account) => {
9022
9119
  const identity = pick("login") ?? pick("email") ?? pick("accountEmail") ?? pick("accountId");
9023
9120
  const suffix = pick("tokenSuffix");
9024
9121
  const facts = [
9025
- account.status === "active" ? "connected" : account.status,
9122
+ account.status === "active" ? "connected" : account.status === "invalid" ? "reconnect needed \xB7 the provider refused the login" : account.status,
9026
9123
  identity,
9027
9124
  suffix === null ? null : `\u2026${suffix}`,
9028
9125
  `since ${account.connectedAt.slice(0, 10)}`
@@ -9055,7 +9152,7 @@ var claudeGrantSecret = () => {
9055
9152
  return read.kind === "missing" ? null : read.secret;
9056
9153
  };
9057
9154
  var doctorBundle = (config, args) => doctorBundleCommand(args, {
9058
- defaultDir: path16.join(mendCliHome(), "bundles"),
9155
+ defaultDir: path18.join(mendCliHome(), "bundles"),
9059
9156
  now: () => /* @__PURE__ */ new Date(),
9060
9157
  say: say6,
9061
9158
  warn: (line) => process.stderr.write(`${line}
@@ -9096,74 +9193,69 @@ var staleGrantReason = (secret) => {
9096
9193
  };
9097
9194
  var claudeGrant = async () => {
9098
9195
  const cli = claudeCli();
9099
- const dir = claudeGrantDir(mendCliHome());
9196
+ const home = mendCliHome();
9100
9197
  const personal = personalClaudeDir();
9101
9198
  const personalBefore = grantStatus(cli, personal);
9102
- let status = grantStatus(cli, dir);
9103
- if (status === null) {
9104
- fail6(
9105
- "claude: could not run `claude auth status` \u2014 install Claude Code, set MEND_CLAUDE_BIN, or paste a credential: mend connect claude --from-stdin"
9106
- );
9107
- return null;
9108
- }
9109
- if (!status.loggedIn) {
9110
- say6(` Mend needs its own Claude login, kept in ${dir}`);
9199
+ const dir = throwawayLoginDir(home, "claude-login-");
9200
+ try {
9201
+ if (grantStatus(cli, dir) === null) {
9202
+ fail6(
9203
+ "claude: could not run `claude auth status` \u2014 install Claude Code, set MEND_CLAUDE_BIN, or paste a credential: mend connect claude --from-stdin"
9204
+ );
9205
+ return null;
9206
+ }
9207
+ say6(" Mend needs its own Claude login; it is sent to your server and not kept here");
9111
9208
  say6(dim6(" your own Claude login stays as it is"));
9112
9209
  if (!runClaudeLogin(cli, dir)) {
9113
9210
  fail6("claude: the login did not complete");
9114
9211
  return null;
9115
9212
  }
9116
- status = grantStatus(cli, dir) ?? status;
9117
- if (!status.loggedIn) {
9213
+ const status = grantStatus(cli, dir);
9214
+ if (status === null || !status.loggedIn) {
9118
9215
  fail6("claude: the login completed but Claude still reports no grant in Mend's directory");
9119
9216
  return null;
9120
9217
  }
9121
- }
9122
- if (status.configDirectory !== null && path16.resolve(status.configDirectory) !== path16.resolve(dir)) {
9123
- fail6(
9124
- `claude: this Claude read ${status.configDirectory} instead of ${dir}, so a separate grant is not possible \u2014 connect the shared one deliberately with --use-my-login`
9125
- );
9126
- return null;
9127
- }
9128
- let read = readGrant(dir);
9129
- if (read.kind !== "missing") {
9218
+ if (status.configDirectory !== null && path18.resolve(status.configDirectory) !== path18.resolve(dir)) {
9219
+ fail6(
9220
+ `claude: this Claude read ${status.configDirectory} instead of ${dir}, so a separate grant is not possible \u2014 connect the shared one deliberately with --use-my-login`
9221
+ );
9222
+ return null;
9223
+ }
9224
+ const read = readGrant(dir);
9225
+ if (read.kind === "missing") {
9226
+ const where = read.triedService === null ? read.triedPath : `${read.triedPath} or the Keychain item ${read.triedService}`;
9227
+ fail6(`claude: logged in, but no credential to read \u2014 looked in ${where}`);
9228
+ return null;
9229
+ }
9130
9230
  const why = staleGrantReason(read.secret);
9131
9231
  if (why !== null) {
9132
- say6(` Mend's Claude grant is ${why}; logging in again`);
9133
- if (!runClaudeLogin(cli, dir)) {
9134
- fail6("claude: the login did not complete");
9135
- return null;
9136
- }
9137
- read = readGrant(dir);
9138
- const still = read.kind === "missing" ? "missing" : staleGrantReason(read.secret);
9139
- if (still !== null) {
9140
- fail6(`claude: the grant is still ${still} after logging in`);
9141
- return null;
9142
- }
9232
+ fail6(`claude: the new login is already ${why}`);
9233
+ return null;
9143
9234
  }
9235
+ const mine = localCredential("claude");
9236
+ if (mine !== null && sameGrant(read.secret, mine)) {
9237
+ fail6(
9238
+ "claude: that is the same grant this machine's Claude holds, so both sides would race on refresh \u2014 connect it deliberately with --use-my-login"
9239
+ );
9240
+ return null;
9241
+ }
9242
+ const personalAfter = grantStatus(cli, personal);
9243
+ if (personalBefore?.loggedIn === true && personalAfter?.loggedIn === false) {
9244
+ say6(
9245
+ ` your own Claude login was signed out by this one \u2014 this account allows one grant at a time. Run \`claude auth login\` to get it back, and connect the shared grant with --use-my-login instead.`
9246
+ );
9247
+ } else if (personalAfter?.loggedIn === true) {
9248
+ say6(dim6(" your own Claude login still works \xB7 verified"));
9249
+ }
9250
+ const kept = claudeGrantDir(home);
9251
+ if (fs17.existsSync(kept)) {
9252
+ forgetGrant(kept);
9253
+ say6(dim6(` removed the copy an older mend kept in ${kept} \xB7 the server refreshes the login`));
9254
+ }
9255
+ return read.secret;
9256
+ } finally {
9257
+ forgetGrant(dir);
9144
9258
  }
9145
- if (read.kind === "missing") {
9146
- const where = read.triedService === null ? read.triedPath : `${read.triedPath} or the Keychain item ${read.triedService}`;
9147
- fail6(`claude: logged in, but no credential to read \u2014 looked in ${where}`);
9148
- return null;
9149
- }
9150
- const mine = localCredential("claude");
9151
- if (mine !== null && sameGrant(read.secret, mine)) {
9152
- fail6(
9153
- "claude: that is the same grant this machine's Claude holds, so both sides would race on refresh \u2014 remove Mend's directory and log in again, or accept the race with --use-my-login"
9154
- );
9155
- return null;
9156
- }
9157
- const personalAfter = grantStatus(cli, personal);
9158
- if (personalBefore?.loggedIn === true && personalAfter?.loggedIn === false) {
9159
- say6(
9160
- ` your own Claude login was signed out by this one \u2014 this account allows one grant at a time. Run \`claude auth login\` to get it back, and connect the shared grant with --use-my-login instead.`
9161
- );
9162
- } else if (personalAfter?.loggedIn === true) {
9163
- say6(dim6(" your own Claude login still works \xB7 verified"));
9164
- }
9165
- say6(dim6(` grant ${read.kind === "file" ? read.path : `keychain ${read.service}`}`));
9166
- return read.secret;
9167
9259
  };
9168
9260
  var connectCommand = async (config, args) => {
9169
9261
  const [providerArg, ...flags] = args;
@@ -9182,8 +9274,17 @@ var connectCommand = async (config, args) => {
9182
9274
  }
9183
9275
  let secret;
9184
9276
  if (flags.includes("--from-stdin")) {
9185
- secret = fs15.readFileSync(0, "utf8").trim();
9277
+ secret = fs17.readFileSync(0, "utf8").trim();
9186
9278
  if (secret === "") return fail6("nothing on stdin");
9279
+ } else if (provider === "codex" && !flags.includes("--use-my-login")) {
9280
+ const grant = codexGrant({
9281
+ cli: codexCli(),
9282
+ personalAuthJson: readIfExists(path18.join(personalCodexHome(), "auth.json")),
9283
+ say: say6,
9284
+ parent: mendCliHome()
9285
+ });
9286
+ if (grant.kind === "failed") return fail6(grant.reason);
9287
+ secret = grant.secret;
9187
9288
  } else if (provider === "claude" && !flags.includes("--use-my-login")) {
9188
9289
  secret = await claudeGrant();
9189
9290
  if (secret === null) return;
@@ -9193,10 +9294,10 @@ var connectCommand = async (config, args) => {
9193
9294
  const where = provider === "github" ? "`gh auth login` first, or pipe a token: gh auth token | mend connect github --from-stdin" : provider === "codex" ? "`codex login` first, or: mend connect codex --from-stdin < auth.json" : "`claude auth login` first, or: mend connect claude --from-stdin";
9194
9295
  return fail6(`${provider}: no credential on this machine \u2014 ${where}`);
9195
9296
  }
9196
- if (provider === "claude") {
9297
+ if (provider === "claude" || provider === "codex") {
9197
9298
  say6(
9198
9299
  dim6(
9199
- " --use-my-login: Mend and this machine will share one grant, and whichever refreshes second is signed out"
9300
+ " --use-my-login: Mend and this machine will share one login, and whichever refreshes second is signed out"
9200
9301
  )
9201
9302
  );
9202
9303
  }
@@ -9228,14 +9329,14 @@ var takeFlagValue4 = (args, flag) => {
9228
9329
  return at !== -1 && args[at + 1] !== void 0 ? String(args[at + 1]) : null;
9229
9330
  };
9230
9331
  var saveCliConfig = (next) => {
9231
- fs15.mkdirSync(path16.dirname(CONFIG_PATH), { recursive: true, mode: 448 });
9232
- fs15.writeFileSync(
9332
+ fs17.mkdirSync(path18.dirname(CONFIG_PATH), { recursive: true, mode: 448 });
9333
+ fs17.writeFileSync(
9233
9334
  CONFIG_PATH,
9234
9335
  `${JSON.stringify({ url: next.url, token: next.token, deviceId: next.deviceId }, null, 2)}
9235
9336
  `,
9236
9337
  { mode: 384 }
9237
9338
  );
9238
- fs15.chmodSync(CONFIG_PATH, 384);
9339
+ fs17.chmodSync(CONFIG_PATH, 384);
9239
9340
  };
9240
9341
  var login = async (config, args) => {
9241
9342
  await loginCommand(args, {
@@ -9248,7 +9349,7 @@ var login = async (config, args) => {
9248
9349
  });
9249
9350
  };
9250
9351
  var logout = async (config) => {
9251
- if (!fs15.existsSync(CONFIG_PATH) && config.token === null) {
9352
+ if (!fs17.existsSync(CONFIG_PATH) && config.token === null) {
9252
9353
  say6(dim6("nothing saved \u2014 already signed out"));
9253
9354
  return;
9254
9355
  }
@@ -9301,8 +9402,8 @@ var uninstallCommand = async (config, args) => {
9301
9402
  const runtime = {
9302
9403
  server,
9303
9404
  cliHome: mendCliHome(),
9304
- sshConfigFile: path16.join(os10.homedir(), ".ssh", "config"),
9305
- signedIn: config.token === null || !fs15.existsSync(CONFIG_PATH) ? null : { url: config.url, deviceId: config.deviceId },
9405
+ sshConfigFile: path18.join(os11.homedir(), ".ssh", "config"),
9406
+ signedIn: config.token === null || !fs17.existsSync(CONFIG_PATH) ? null : { url: config.url, deviceId: config.deviceId },
9306
9407
  revokeDevice: async () => {
9307
9408
  if (config.deviceId === null) return "no device id saved";
9308
9409
  try {
@@ -9366,7 +9467,7 @@ var keysShare = async (config) => {
9366
9467
  return fail6("SSH_AUTH_SOCK is not set \u2014 start (or plug in) your ssh-agent first");
9367
9468
  }
9368
9469
  await shareAgent({
9369
- url: () => socketUrl(config, "keys-bridge", { host: os10.hostname() }),
9470
+ url: () => socketUrl(config, "keys-bridge", { host: os11.hostname() }),
9370
9471
  agentSock,
9371
9472
  signal: new AbortController().signal,
9372
9473
  onEvent: (event) => {
@@ -9496,7 +9597,7 @@ ${usageOf("dotfiles repo")}`);
9496
9597
  var dotfilesSync = async (config, args) => {
9497
9598
  const all = args.includes("--all");
9498
9599
  const requestedPaths = args.filter((arg) => !arg.startsWith("--"));
9499
- const home = os10.homedir();
9600
+ const home = os11.homedir();
9500
9601
  if (!all && requestedPaths.length === 0) {
9501
9602
  const found = scanDotfileCandidates(home);
9502
9603
  if (found.length === 0) {
@@ -9523,13 +9624,13 @@ var dotfilesSync = async (config, args) => {
9523
9624
  if ("error" in read) return fail6(read.error);
9524
9625
  const result = await api(config, "POST", "/dotfiles/snapshot", {
9525
9626
  files: read.files,
9526
- source: os10.hostname(),
9627
+ source: os11.hostname(),
9527
9628
  merge: false
9528
9629
  });
9529
9630
  const snapshot = result.snapshot;
9530
9631
  if (snapshot === null) return fail6("the server accepted the sync but reports no snapshot");
9531
9632
  say6(
9532
- `${green6("synced")} ${snapshot.files.length} file${snapshot.files.length === 1 ? "" : "s"} from ${os10.hostname()} \xB7 ${dim6(snapshot.sha.slice(0, 7))} ${dim6("\u2014 applies from the next session launch")}`
9633
+ `${green6("synced")} ${snapshot.files.length} file${snapshot.files.length === 1 ? "" : "s"} from ${os11.hostname()} \xB7 ${dim6(snapshot.sha.slice(0, 7))} ${dim6("\u2014 applies from the next session launch")}`
9533
9634
  );
9534
9635
  };
9535
9636
  var envLoad = async (config, args) => {
@@ -9543,10 +9644,10 @@ var envLoad = async (config, args) => {
9543
9644
  const positional = args.filter(
9544
9645
  (arg, i) => !arg.startsWith("--") && args[i - 1] !== "--project" && !consumed.has(i)
9545
9646
  );
9546
- const file = path16.resolve(positional[0] ?? ".env");
9647
+ const file = path18.resolve(positional[0] ?? ".env");
9547
9648
  let contents;
9548
9649
  try {
9549
- contents = fs15.readFileSync(file, "utf8");
9650
+ contents = fs17.readFileSync(file, "utf8");
9550
9651
  } catch {
9551
9652
  return fail6(`cannot read ${file} \u2014 pass a path: mend env load path/to/.env`);
9552
9653
  }
@@ -9562,10 +9663,10 @@ var envLoad = async (config, args) => {
9562
9663
  { contents, allSecret, secretNames }
9563
9664
  );
9564
9665
  if (report.loaded.length === 0 && report.rejected.length === 0 && report.malformedLines.length === 0) {
9565
- say6(dim6(`${path16.basename(file)} has no variables`));
9666
+ say6(dim6(`${path18.basename(file)} has no variables`));
9566
9667
  return;
9567
9668
  }
9568
- say6(`${green6("\u2713")} loaded ${path16.basename(file)} into ${project2.name}`);
9669
+ say6(`${green6("\u2713")} loaded ${path18.basename(file)} into ${project2.name}`);
9569
9670
  for (const line of formatLoadReport(report, { dim: dim6, warn: amber2 })) say6(line);
9570
9671
  const plaintextUrls = report.loaded.filter(
9571
9672
  (entry) => entry.lane === "configuration" && /_(URL|URI|DSN)$/.test(entry.name)
@@ -9756,7 +9857,7 @@ var skillsList = async (config, args) => {
9756
9857
  };
9757
9858
  var skillsPush = async (config, args) => {
9758
9859
  const dirFlag = takeFlagValue4(args, "--dir");
9759
- const root = dirFlag === null ? path16.join(os10.homedir(), DEFAULT_SKILLS_DIR) : path16.resolve(dirFlag);
9860
+ const root = dirFlag === null ? path18.join(os11.homedir(), DEFAULT_SKILLS_DIR) : path18.resolve(dirFlag);
9760
9861
  const scanned = scanSkillLibrary(root);
9761
9862
  if ("error" in scanned) return fail6(scanned.error);
9762
9863
  for (const note of scanned.notes) say6(dim6(` ${note.skill}: ${note.message}`));
@@ -10431,14 +10532,14 @@ var dashboard = async (config, options = {}) => {
10431
10532
  `the dashboard needs Node >= 26 (node:ffi) \u2014 this is ${process.version}; every other command still works`
10432
10533
  );
10433
10534
  }
10434
- const rerun = spawnSync5(
10535
+ const rerun = spawnSync6(
10435
10536
  process.execPath,
10436
10537
  ["--experimental-ffi", "--disable-warning=ExperimentalWarning", ...process.argv.slice(1)],
10437
10538
  { stdio: "inherit" }
10438
10539
  );
10439
10540
  process.exit(rerun.status ?? 0);
10440
10541
  }
10441
- const { runDashboard } = await import("./dashboard-KZ4XGZ6W.js");
10542
+ const { runDashboard } = await import("./dashboard-MGR4YUFD.js");
10442
10543
  const agentShare = await startShareIfBridge(config);
10443
10544
  const tunnels = options.noTunnel === true || serverIsLocal(config) ? null : createServiceTunnels({
10444
10545
  listServices: () => fetchServices(config),
@@ -10472,7 +10573,7 @@ var startShareIfBridge = async (config) => {
10472
10573
  }
10473
10574
  if (access.mode !== "bridge") return null;
10474
10575
  return startAgentShare({
10475
- url: () => socketUrl(config, "keys-bridge", { host: os10.hostname() }),
10576
+ url: () => socketUrl(config, "keys-bridge", { host: os11.hostname() }),
10476
10577
  agentSock
10477
10578
  });
10478
10579
  };
@@ -10512,15 +10613,16 @@ var manCommand = (words) => {
10512
10613
  }
10513
10614
  const version = cliVersion();
10514
10615
  const page = doc === null ? renderManIndex(version) : renderManPage(doc, version);
10515
- const file = path16.join(os10.tmpdir(), `mend-man-${process.pid}-${manFileName(doc)}`);
10516
- fs15.writeFileSync(file, page);
10517
- const result = spawnSync5("man", ["-l", file], { stdio: "inherit" });
10518
- fs15.rmSync(file, { force: true });
10616
+ const file = path18.join(os11.tmpdir(), `mend-man-${process.pid}-${manFileName(doc)}`);
10617
+ fs17.writeFileSync(file, page);
10618
+ const result = spawnSync6("man", ["-l", file], { stdio: "inherit" });
10619
+ fs17.rmSync(file, { force: true });
10519
10620
  if (result.error !== void 0 || result.status !== 0) {
10520
10621
  say6(doc === null ? renderIndex() : renderCommand(doc));
10521
10622
  }
10522
10623
  };
10523
10624
  var main = async () => {
10625
+ useHttp1();
10524
10626
  const [command, ...rest] = process.argv.slice(2);
10525
10627
  const ownArgs = rest.slice(0, rest.indexOf("--") === -1 ? rest.length : rest.indexOf("--"));
10526
10628
  if (command !== void 0 && command !== "help" && ownArgs.some((a) => a === "--help" || a === "-h")) {