@mycadet/cli 0.12.10 → 0.13.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.
Files changed (105) hide show
  1. package/README.md +13 -0
  2. package/node_modules/@mycadet/assistant-api/node_modules/@mycadet/service-contracts/src/__tests__/ingress.test.ts +10 -10
  3. package/node_modules/@mycadet/assistant-api/node_modules/@mycadet/service-contracts/src/ingress.ts +3 -3
  4. package/node_modules/@mycadet/local-mode/node_modules/@mycadet/service-contracts/src/__tests__/ingress.test.ts +10 -10
  5. package/node_modules/@mycadet/local-mode/node_modules/@mycadet/service-contracts/src/ingress.ts +3 -3
  6. package/node_modules/@mycadet/service-contracts/src/__tests__/ingress.test.ts +10 -10
  7. package/node_modules/@mycadet/service-contracts/src/ingress.ts +3 -3
  8. package/package.json +3 -2
  9. package/src/__tests__/assistant-client-cloud-auth.test.ts +2 -2
  10. package/src/__tests__/backup-ops-matching.test.ts +15 -13
  11. package/src/__tests__/backup-ops.test.ts +105 -0
  12. package/src/__tests__/backup.test.ts +114 -673
  13. package/src/__tests__/cloud-login-poll.test.ts +69 -0
  14. package/src/__tests__/cloud-releases.test.ts +82 -0
  15. package/src/__tests__/commands-mock.ts +101 -0
  16. package/src/__tests__/debug.test.ts +17 -91
  17. package/src/__tests__/devices.test.ts +64 -2
  18. package/src/__tests__/ensure-binary.test.ts +52 -0
  19. package/src/__tests__/gateway-token.test.ts +267 -0
  20. package/src/__tests__/hatch-next-steps.test.ts +38 -0
  21. package/src/__tests__/host-teleport-docker.test.ts +371 -0
  22. package/src/__tests__/host-teleport.test.ts +405 -0
  23. package/src/__tests__/multi-local.test.ts +3 -3
  24. package/src/__tests__/nginx-ingress.test.ts +233 -36
  25. package/src/__tests__/orphan-detection.test.ts +1 -1
  26. package/src/__tests__/paired-lifecycle.test.ts +2 -2
  27. package/src/__tests__/ps-cloud-status.test.ts +8 -7
  28. package/src/__tests__/root-backup-docker.test.ts +294 -0
  29. package/src/__tests__/root-backup.test.ts +527 -0
  30. package/src/__tests__/root-restore-command.test.ts +147 -0
  31. package/src/__tests__/root-signing-key.test.ts +50 -0
  32. package/src/__tests__/setup.test.ts +17 -7
  33. package/src/__tests__/sleep.test.ts +11 -0
  34. package/src/__tests__/teleport.test.ts +68 -2996
  35. package/src/__tests__/tunnel-startup-summary.test.ts +110 -0
  36. package/src/__tests__/tunnel-stop.test.ts +226 -0
  37. package/src/__tests__/tunnel.test.ts +13 -3
  38. package/src/__tests__/upgrade-local.test.ts +21 -11
  39. package/src/__tests__/upgrade-replay-env.test.ts +2 -2
  40. package/src/__tests__/upgrade-root-recovery.test.ts +185 -0
  41. package/src/__tests__/windows-lifecycle.test.ts +25 -0
  42. package/src/commands/backup.ts +44 -399
  43. package/src/commands/client.ts +3 -3
  44. package/src/commands/completions.ts +0 -2
  45. package/src/commands/debug.ts +75 -131
  46. package/src/commands/devices.ts +117 -47
  47. package/src/commands/gateway/token.ts +77 -23
  48. package/src/commands/hatch.ts +10 -52
  49. package/src/commands/pair.ts +9 -3
  50. package/src/commands/ps.ts +4 -2
  51. package/src/commands/restore.ts +77 -444
  52. package/src/commands/retire.ts +2 -3
  53. package/src/commands/sleep.ts +15 -2
  54. package/src/commands/teleport.ts +47 -1559
  55. package/src/commands/tunnel.ts +43 -4
  56. package/src/commands/upgrade.ts +84 -157
  57. package/src/commands/wake.ts +1 -1
  58. package/src/index.ts +0 -4
  59. package/src/lib/__tests__/http-client-version.test.ts +29 -0
  60. package/src/lib/__tests__/runtime-url.test.ts +3 -75
  61. package/src/lib/__tests__/web-dist.test.ts +27 -1
  62. package/src/lib/assistant-client.ts +1 -1
  63. package/src/lib/assistant-config.ts +20 -23
  64. package/src/lib/backup-ops.ts +37 -251
  65. package/src/lib/cloud-client.ts +10 -13
  66. package/src/lib/cloud-login-poll.ts +75 -0
  67. package/src/lib/cloud-login.ts +5 -2
  68. package/src/lib/cloud-releases.ts +54 -10
  69. package/src/lib/cloud-values.ts +1 -1
  70. package/src/lib/confirm-action.ts +2 -2
  71. package/src/lib/docker.ts +65 -34
  72. package/src/lib/ensure-binary.ts +65 -6
  73. package/src/lib/github-repository.ts +2 -0
  74. package/src/lib/guardian-token.ts +1 -23
  75. package/src/lib/hatch-local.ts +18 -52
  76. package/src/lib/hatch-next-steps.ts +15 -2
  77. package/src/lib/host-teleport.ts +506 -0
  78. package/src/lib/http-client.ts +25 -0
  79. package/src/lib/live-voice/tunnel.test.ts +1 -1
  80. package/src/lib/live-voice/tunnel.ts +3 -3
  81. package/src/lib/local.ts +10 -8
  82. package/src/lib/nginx-ingress.ts +254 -36
  83. package/src/lib/process.ts +13 -0
  84. package/src/lib/root-backup.ts +917 -0
  85. package/src/lib/root-signing-key.ts +31 -0
  86. package/src/lib/runtime-url.ts +0 -29
  87. package/src/lib/teleport-backup.ts +3 -16
  88. package/src/lib/tunnel.ts +86 -34
  89. package/src/lib/tunnels/cadet.ts +12 -1
  90. package/src/lib/tunnels/cloudflare.ts +36 -1
  91. package/src/lib/tunnels/ngrok.ts +16 -2
  92. package/src/lib/tunnels/process-lifecycle.ts +26 -0
  93. package/src/lib/tunnels/tailscale.ts +79 -1
  94. package/src/lib/upgrade-lifecycle.ts +63 -141
  95. package/src/lib/web-dist.ts +23 -1
  96. package/src/lib/xdg-log.ts +11 -0
  97. package/src/__tests__/bundle-staging.test.ts +0 -268
  98. package/src/__tests__/unpair.test.ts +0 -160
  99. package/src/commands/rollback.ts +0 -479
  100. package/src/commands/unpair.ts +0 -122
  101. package/src/lib/__tests__/job-polling.test.ts +0 -278
  102. package/src/lib/__tests__/local-runtime-client.test.ts +0 -666
  103. package/src/lib/bundle-staging.ts +0 -220
  104. package/src/lib/job-polling.ts +0 -195
  105. package/src/lib/local-runtime-client.ts +0 -374
@@ -10,7 +10,7 @@ import { green } from "../lib/color";
10
10
  import { HATCH_ART, HATCHED_EMOJI, VALID_REMOTE_HOSTS } from "../lib/constants";
11
11
  import type { RemoteHost } from "../lib/constants";
12
12
  import { hatchDocker } from "../lib/docker";
13
- import { parseFeatureFlagArgs, readAmbientFlagEnvVars } from "../lib/flag-args";
13
+ import { readAmbientFlagEnvVars } from "../lib/flag-args";
14
14
  import { hatchLocal } from "../lib/hatch-local";
15
15
  import {
16
16
  getCloudUrl,
@@ -23,37 +23,26 @@ const DEFAULT_REMOTE: RemoteHost = "local";
23
23
 
24
24
  interface HatchArgs {
25
25
  verbose: boolean;
26
- keepAlive: boolean;
27
26
  name: string | null;
28
27
  remote: RemoteHost;
29
28
  watch: boolean;
30
29
  sourcePath: string | null;
31
30
  configValues: Record<string, string>;
32
31
  flagEnvVars: Record<string, string>;
33
- analyze: boolean;
34
- disableCloud: boolean;
35
32
  netnsContainer: string | null;
36
33
  gatewayPort: number | null;
37
34
  assistantCaCert: string | null;
38
35
  }
39
36
 
40
37
  function parseArgs(): HatchArgs {
41
- const { envVars: cliFlagVars, remaining: args } = parseFeatureFlagArgs(
42
- process.argv.slice(3),
43
- );
44
- const flagEnvVars = { ...readAmbientFlagEnvVars(), ...cliFlagVars };
45
- const disableCloudAmbient =
46
- process.env.CADET_DISABLE_CLOUD?.trim().toLowerCase();
47
- let disableCloud =
48
- disableCloudAmbient === "true" || disableCloudAmbient === "1";
38
+ const args = process.argv.slice(3);
39
+ const flagEnvVars = readAmbientFlagEnvVars();
49
40
  let verbose = false;
50
- let keepAlive = false;
51
41
  let name: string | null = null;
52
42
  let remote: RemoteHost = DEFAULT_REMOTE;
53
43
  let watch = false;
54
44
  let sourcePath: string | null = null;
55
45
  const configValues: Record<string, string> = {};
56
- let analyze = false;
57
46
  let netnsContainer: string | null = null;
58
47
  let gatewayPort: number | null = null;
59
48
  let assistantCaCert: string | null = null;
@@ -69,47 +58,33 @@ function parseArgs(): HatchArgs {
69
58
  console.log(
70
59
  " -v, --verbose Show service startup logs and extended next steps",
71
60
  );
72
- console.log(" --name <name> Custom instance name");
61
+ console.log(" --name <name> Custom name for this assistant");
73
62
  console.log(
74
63
  " --remote <host> Remote host (local, docker, custom, cloud)",
75
64
  );
76
65
  console.log(
77
- " --watch Run assistant and gateway in watch mode (hot reload on source changes)",
78
- );
79
- console.log(
80
- " --source <path> Build images from a local source tree at <path>. Useful for callers that want each run to pick up local CLI changes.",
66
+ " --watch Run Cadet in watch mode with hot reload on source changes",
81
67
  );
82
68
  console.log(
83
- " --keep-alive Stay alive after hatch, exit when gateway stops",
69
+ " --source <path> Build images from a local source tree at <path>",
84
70
  );
85
71
  console.log(
86
72
  " --config <key=value> Set a workspace config value (repeatable)",
87
73
  );
88
74
  console.log(
89
- " --flag <key=value> Set a feature flag override as CADET_FLAG_<KEY> env var (repeatable)",
75
+ " --netns-container <name> Join an existing container's network namespace instead of creating a per-instance network.",
90
76
  );
91
77
  console.log(
92
- " --analyze Emit a structured hatch-timing log line on stdout",
78
+ " --gateway-port <port> Use an explicit host port for accessing the assistant.",
93
79
  );
94
80
  console.log(
95
- " --disable-cloud Suppress all outbound platform API calls",
96
- );
97
- console.log(
98
- " --netns-container <name> Join an existing container's network namespace (docker target only) instead of creating a per-instance network. The namespace owner publishes host ports, so --gateway-port is required.",
99
- );
100
- console.log(
101
- " --gateway-port <port> Use an explicit host port for the gateway runtime URL instead of auto-allocating. Required with --netns-container.",
102
- );
103
- console.log(
104
- " --assistant-ca-cert <path> Trust an extra PEM CA bundle in the assistant container (NODE_EXTRA_CA_CERTS) from process start. Useful behind a TLS-terminating egress proxy.",
81
+ " --assistant-ca-cert <path> Trust an extra PEM CA bundle in the assistant container from process start.",
105
82
  );
106
83
  process.exit(0);
107
84
  } else if (arg === "-v" || arg == "--verbose") {
108
85
  verbose = true;
109
86
  } else if (arg === "--watch") {
110
87
  watch = true;
111
- } else if (arg === "--analyze") {
112
- analyze = true;
113
88
  } else if (arg === "--source") {
114
89
  const next = args[i + 1];
115
90
  if (!next || next.startsWith("-")) {
@@ -118,8 +93,6 @@ function parseArgs(): HatchArgs {
118
93
  }
119
94
  sourcePath = next;
120
95
  i++;
121
- } else if (arg === "--keep-alive") {
122
- keepAlive = true;
123
96
  } else if (arg === "--name") {
124
97
  const next = args[i + 1];
125
98
  if (!next || next.startsWith("-")) {
@@ -163,8 +136,6 @@ function parseArgs(): HatchArgs {
163
136
  const value = next.slice(eqIndex + 1);
164
137
  configValues[key] = value;
165
138
  i++;
166
- } else if (arg === "--disable-cloud") {
167
- disableCloud = true;
168
139
  } else if (arg === "--netns-container") {
169
140
  const next = args[i + 1];
170
141
  if (!next || next.startsWith("-")) {
@@ -194,7 +165,7 @@ function parseArgs(): HatchArgs {
194
165
  i++;
195
166
  } else {
196
167
  console.error(
197
- `Error: Unknown argument '${arg}'. Valid options: -v, --verbose, --watch, --source <path>, --keep-alive, --name <name>, --remote <${VALID_REMOTE_HOSTS.join("|")}>, --config <key=value>, --flag <key=value>, --analyze, --disable-cloud, --netns-container <name>, --gateway-port <port>, --assistant-ca-cert <path>`,
168
+ `Error: Unknown argument '${arg}'. Valid options: -v, --verbose, --watch, --source <path>, --name <name>, --remote <${VALID_REMOTE_HOSTS.join("|")}>, --config <key=value>, --netns-container <name>, --gateway-port <port>, --assistant-ca-cert <path>`,
198
169
  );
199
170
  process.exit(1);
200
171
  }
@@ -202,15 +173,12 @@ function parseArgs(): HatchArgs {
202
173
 
203
174
  return {
204
175
  verbose,
205
- keepAlive,
206
176
  name,
207
177
  remote,
208
178
  watch,
209
179
  sourcePath,
210
180
  configValues,
211
181
  flagEnvVars,
212
- analyze,
213
- disableCloud,
214
182
  netnsContainer,
215
183
  gatewayPort,
216
184
  assistantCaCert,
@@ -230,25 +198,17 @@ export const hatch = Object.assign(
230
198
 
231
199
  const {
232
200
  verbose,
233
- keepAlive,
234
201
  name,
235
202
  remote,
236
203
  watch,
237
204
  sourcePath,
238
205
  configValues,
239
206
  flagEnvVars,
240
- analyze,
241
- disableCloud,
242
207
  netnsContainer,
243
208
  gatewayPort,
244
209
  assistantCaCert,
245
210
  } = parseArgs();
246
211
 
247
- if (disableCloud) {
248
- process.env.CADET_DISABLE_CLOUD = "true";
249
- flagEnvVars.CADET_DISABLE_CLOUD = "true";
250
- }
251
-
252
212
  if (watch && remote !== "local" && remote !== "docker") {
253
213
  console.error(
254
214
  "Error: --watch is only supported for local and docker hatch targets.",
@@ -286,7 +246,6 @@ export const hatch = Object.assign(
286
246
  await hatchLocal({
287
247
  name,
288
248
  watch,
289
- keepAlive,
290
249
  configValues,
291
250
  flagEnvVars,
292
251
  verbose,
@@ -301,7 +260,6 @@ export const hatch = Object.assign(
301
260
  configValues,
302
261
  flagEnvVars,
303
262
  sourcePath,
304
- analyze,
305
263
  netnsContainer: netnsContainer ?? undefined,
306
264
  gatewayPort: gatewayPort ?? undefined,
307
265
  assistantCaCertPath: assistantCaCert ?? undefined,
@@ -90,7 +90,7 @@ const RETIRED_FLAGS = new Map<string, string>([
90
90
  ]);
91
91
 
92
92
  function printUsage(): void {
93
- console.log(`cadet pair [beta] - Print a pairing link and QR code for another device
93
+ console.log(`cadet pair - Print a pairing link and QR code for another device
94
94
 
95
95
  USAGE:
96
96
  cadet pair [assistant] [options]
@@ -586,6 +586,10 @@ export const pair = Object.assign(
586
586
  console.log(qr);
587
587
  });
588
588
  console.log("");
589
+ console.log("Or enter this code on the pairing page:");
590
+ console.log("");
591
+ console.log(` ${challenge.deviceCode}`);
592
+ console.log("");
589
593
  if (appUrl) {
590
594
  console.log("The QR opens the Cadet app. App link:");
591
595
  console.log("");
@@ -598,10 +602,12 @@ export const pair = Object.assign(
598
602
  console.log("");
599
603
  console.log(` ${pairUrl}`);
600
604
  console.log("");
601
- console.log(`On another computer, run: cadet connect import "${pairUrl}"`);
605
+ console.log("Or on another computer, run:");
606
+ console.log("");
607
+ console.log(` cadet connect import "${pairUrl}"`);
602
608
  console.log("");
603
609
  console.log(`Expires: ${challenge.expiresAt}`);
604
610
  },
605
- { description: "Print a pairing link and QR code for another device [beta]" },
611
+ { description: "Print a pairing link and QR code for another device" },
606
612
  );
607
613
 
@@ -1,3 +1,4 @@
1
+ import { getNginxIngressPort } from "../lib/nginx-ingress.js";
1
2
  import { isCloudHome } from "../lib/cloud-values.js";
2
3
  import { join } from "path";
3
4
 
@@ -649,10 +650,10 @@ async function getRootManagedRows(): Promise<RootManagedRow[]> {
649
650
  rows.push({
650
651
  assistantId: app.assistantId,
651
652
  row: {
652
- name: "nginx edge",
653
+ name: "nginx",
653
654
  type: APP_TYPE,
654
655
  status: withStatusEmoji(alive ? "running" : "not running"),
655
- info: alive ? `PID ${app.pid}` : `PID ${app.pid} (exited)`,
656
+ info: `port ${app.port ?? getNginxIngressPort()}, PID ${app.pid}${alive ? "" : " (exited)"}`,
656
657
  },
657
658
  });
658
659
  }
@@ -813,6 +814,7 @@ export async function listAllAssistants(verbose: boolean): Promise<void> {
813
814
  ),
814
815
  { name: "NAME", type: "TYPE", status: "STATUS", info: "INFO" },
815
816
  );
817
+ console.log("");
816
818
  }
817
819
 
818
820
  // ── Entry point ─────────────────────────────────────────────────