@madarco/agentbox 0.10.1 → 0.11.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 (41) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/dist/{_cloud-attach-2DGI6FUA.js → _cloud-attach-45ECDTRL.js} +4 -4
  3. package/dist/{chunk-MTVI44DW.js → chunk-ECLLV5JH.js} +6 -3
  4. package/dist/chunk-ECLLV5JH.js.map +1 -0
  5. package/dist/{chunk-M2UWJKFA.js → chunk-MXXXKJYS.js} +5 -5
  6. package/dist/chunk-MXXXKJYS.js.map +1 -0
  7. package/dist/{chunk-I7NOGCL4.js → chunk-PZ2TJF2U.js} +23 -11
  8. package/dist/chunk-PZ2TJF2U.js.map +1 -0
  9. package/dist/{chunk-I24B6AXR.js → chunk-R5XIDQFR.js} +6 -3
  10. package/dist/chunk-R5XIDQFR.js.map +1 -0
  11. package/dist/{chunk-PWUVHPN6.js → chunk-SNTHHWKY.js} +7 -3
  12. package/dist/chunk-SNTHHWKY.js.map +1 -0
  13. package/dist/{chunk-LEV3KICD.js → chunk-ZGVMN54V.js} +6 -3
  14. package/dist/{chunk-LEV3KICD.js.map → chunk-ZGVMN54V.js.map} +1 -1
  15. package/dist/{chunk-CDKVD6UO.js → chunk-ZJXTIH6C.js} +119 -87
  16. package/dist/chunk-ZJXTIH6C.js.map +1 -0
  17. package/dist/{dist-SBCQVFCE.js → dist-ASLPRUQR.js} +3 -3
  18. package/dist/{dist-BD5QJRDC.js → dist-PTJ6CEQY.js} +5 -5
  19. package/dist/{dist-SJHY3HYN.js → dist-RAZP76VX.js} +5 -5
  20. package/dist/{dist-BNI5PQYK.js → dist-WMQDMTWS.js} +5 -5
  21. package/dist/index.js +619 -546
  22. package/dist/index.js.map +1 -1
  23. package/dist/{prepared-state-MQHD3M5F-O5M4NIN4.js → prepared-state-MQHD3M5F-KE4DT3GX.js} +2 -2
  24. package/package.json +4 -4
  25. package/runtime/docker/packages/ctl/dist/bin.cjs +5 -2
  26. package/runtime/hetzner/ctl.cjs +5 -2
  27. package/runtime/relay/bin.cjs +37 -19
  28. package/runtime/vercel/ctl.cjs +5 -2
  29. package/runtime/vercel/scripts/provision.sh +20 -0
  30. package/dist/chunk-CDKVD6UO.js.map +0 -1
  31. package/dist/chunk-I24B6AXR.js.map +0 -1
  32. package/dist/chunk-I7NOGCL4.js.map +0 -1
  33. package/dist/chunk-M2UWJKFA.js.map +0 -1
  34. package/dist/chunk-MTVI44DW.js.map +0 -1
  35. package/dist/chunk-PWUVHPN6.js.map +0 -1
  36. /package/dist/{_cloud-attach-2DGI6FUA.js.map → _cloud-attach-45ECDTRL.js.map} +0 -0
  37. /package/dist/{dist-SBCQVFCE.js.map → dist-ASLPRUQR.js.map} +0 -0
  38. /package/dist/{dist-BD5QJRDC.js.map → dist-PTJ6CEQY.js.map} +0 -0
  39. /package/dist/{dist-SJHY3HYN.js.map → dist-RAZP76VX.js.map} +0 -0
  40. /package/dist/{dist-BNI5PQYK.js.map → dist-WMQDMTWS.js.map} +0 -0
  41. /package/dist/{prepared-state-MQHD3M5F-O5M4NIN4.js.map → prepared-state-MQHD3M5F-KE4DT3GX.js.map} +0 -0
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  maskKey,
6
6
  readDaytonaCredStatus,
7
7
  secretsPath
8
- } from "./chunk-LEV3KICD.js";
8
+ } from "./chunk-ZGVMN54V.js";
9
9
  import {
10
10
  detectEgressIp,
11
11
  ensureHetznerCredentials,
@@ -15,7 +15,7 @@ import {
15
15
  readHetznerCredStatus,
16
16
  secretsPath as secretsPath2,
17
17
  syncFirewallSource
18
- } from "./chunk-I24B6AXR.js";
18
+ } from "./chunk-R5XIDQFR.js";
19
19
  import {
20
20
  detectSbx,
21
21
  ensureVercelCredentials,
@@ -23,7 +23,7 @@ import {
23
23
  maskKey as maskKey3,
24
24
  readVercelCredStatus,
25
25
  secretsPath as secretsPath3
26
- } from "./chunk-MTVI44DW.js";
26
+ } from "./chunk-ECLLV5JH.js";
27
27
  import {
28
28
  agentSpecsForCloud,
29
29
  ensureAgentVolumesForCloud,
@@ -31,7 +31,7 @@ import {
31
31
  probeCloudCheckpoint,
32
32
  resolveCloudCheckpoint,
33
33
  seedAgentVolumesIfFresh
34
- } from "./chunk-M2UWJKFA.js";
34
+ } from "./chunk-MXXXKJYS.js";
35
35
  import {
36
36
  ADVANCED_HINT_GROUPS,
37
37
  ALERT_BAND_ROWS,
@@ -61,7 +61,7 @@ import {
61
61
  statusLine,
62
62
  stripTitleGlyph,
63
63
  subscribePrompts
64
- } from "./chunk-I7NOGCL4.js";
64
+ } from "./chunk-PZ2TJF2U.js";
65
65
  import {
66
66
  AmbiguousBoxError,
67
67
  BOX_STATUS_EVENT,
@@ -207,20 +207,21 @@ import {
207
207
  waitForTmuxPaneContent,
208
208
  warmUpClaudeCredentials,
209
209
  writeJob
210
- } from "./chunk-CDKVD6UO.js";
210
+ } from "./chunk-ZJXTIH6C.js";
211
211
  import {
212
212
  DEFAULT_BOX_IMAGE,
213
213
  STATE_DIR,
214
214
  ensureImage,
215
+ hostOpenCommand,
215
216
  imageInfo,
216
217
  readState,
217
218
  resolveBoxRef
218
- } from "./chunk-PWUVHPN6.js";
219
+ } from "./chunk-SNTHHWKY.js";
219
220
  import "./chunk-G3H2L3O2.js";
220
221
 
221
222
  // src/version.ts
222
- var AGENTBOX_VERSION = true ? "0.10.1" : "0.0.0-dev";
223
- var AGENTBOX_COMMIT = true ? "1957cb4a" : "dev";
223
+ var AGENTBOX_VERSION = true ? "0.11.1" : "0.0.0-dev";
224
+ var AGENTBOX_COMMIT = true ? "b00384ce" : "dev";
224
225
 
225
226
  // src/index.ts
226
227
  import { Command as Command46 } from "commander";
@@ -591,7 +592,7 @@ function parsePositiveInt(raw, label) {
591
592
  }
592
593
 
593
594
  // src/commands/claude.ts
594
- import { confirm as confirm3, intro, isCancel as isCancel4, log as log9, outro as outro2, spinner as spinner3 } from "@clack/prompts";
595
+ import { confirm as confirm3, intro, isCancel as isCancel4, log as log8, outro, spinner as spinner3 } from "@clack/prompts";
595
596
  import { Command as Command2 } from "commander";
596
597
 
597
598
  // src/auth.ts
@@ -822,9 +823,6 @@ function resolveAttachInOption(opts) {
822
823
  return void 0;
823
824
  }
824
825
 
825
- // src/commands/_cloud-agent-create.ts
826
- import { log as log4, outro } from "@clack/prompts";
827
-
828
826
  // src/lib/progress.ts
829
827
  import { spinner } from "@clack/prompts";
830
828
 
@@ -867,6 +865,138 @@ function makeProgressReporter(verbose) {
867
865
  };
868
866
  }
869
867
 
868
+ // src/lib/launch-recap.ts
869
+ import { homedir as homedir2 } from "os";
870
+ import { note } from "@clack/prompts";
871
+
872
+ // src/lib/from-branch.ts
873
+ import { execa } from "execa";
874
+ var SHA_RE = /^[0-9a-f]{7,40}$/i;
875
+ var FromBranchError = class extends Error {
876
+ constructor(message) {
877
+ super(message);
878
+ this.name = "FromBranchError";
879
+ }
880
+ };
881
+ async function resolveFromBranch(ref, opts) {
882
+ if (!ref || ref.length === 0) return void 0;
883
+ const remote = opts.remote ?? "origin";
884
+ const isSha = SHA_RE.test(ref);
885
+ if (!isSha) {
886
+ const fetched = await execa(
887
+ "git",
888
+ ["-C", opts.repo, "fetch", "--quiet", remote, ref],
889
+ { reject: false }
890
+ );
891
+ if (fetched.exitCode !== 0) {
892
+ }
893
+ }
894
+ const verify = await execa(
895
+ "git",
896
+ ["-C", opts.repo, "rev-parse", "--verify", `${ref}^{commit}`],
897
+ { reject: false }
898
+ );
899
+ if (verify.exitCode !== 0) {
900
+ throw new FromBranchError(
901
+ `--from-branch: unknown ref "${ref}" (not found in ${opts.repo} after fetch). Provide a branch, tag, or SHA reachable from the host repo.`
902
+ );
903
+ }
904
+ return ref;
905
+ }
906
+ var UseBranchError = class extends Error {
907
+ constructor(message) {
908
+ super(message);
909
+ this.name = "UseBranchError";
910
+ }
911
+ };
912
+ async function resolveUseBranch(name, opts) {
913
+ if (!name || name.length === 0) return void 0;
914
+ const remote = opts.remote ?? "origin";
915
+ await execa("git", ["-C", opts.repo, "fetch", "--quiet", remote, name], {
916
+ reject: false
917
+ });
918
+ const exists = await execa(
919
+ "git",
920
+ ["-C", opts.repo, "show-ref", "--verify", "--quiet", `refs/heads/${name}`],
921
+ { reject: false }
922
+ );
923
+ if (exists.exitCode !== 0) {
924
+ throw new UseBranchError(
925
+ `--use-branch: no local branch "${name}" in ${opts.repo}. Create or check it out on the host first (--use-branch reuses an existing branch; use --from-branch to fork a new box branch from a ref).`
926
+ );
927
+ }
928
+ return name;
929
+ }
930
+ async function currentHostBranch(repo) {
931
+ const r = await execa("git", ["-C", repo, "rev-parse", "--abbrev-ref", "HEAD"], {
932
+ reject: false
933
+ });
934
+ if (r.exitCode !== 0) return void 0;
935
+ const branch = r.stdout.trim();
936
+ if (!branch || branch === "HEAD") return void 0;
937
+ return branch;
938
+ }
939
+ async function resolveBranchSelection(opts) {
940
+ if (opts.useBranch && opts.fromBranch) {
941
+ throw new UseBranchError(
942
+ "--use-branch and --from-branch are mutually exclusive: --use-branch reuses an existing branch, --from-branch forks a new box branch from a base ref. Pass only one."
943
+ );
944
+ }
945
+ if (opts.useBranch) {
946
+ return { useBranch: await resolveUseBranch(opts.useBranch, { repo: opts.repo }) };
947
+ }
948
+ if (opts.fromBranch) {
949
+ return { fromBranch: await resolveFromBranch(opts.fromBranch, { repo: opts.repo }) };
950
+ }
951
+ if (opts.providerName !== "docker" && opts.cloudUseCurrentBranch) {
952
+ const current = await currentHostBranch(opts.repo);
953
+ if (current) {
954
+ opts.log?.(`cloud.useCurrentBranch: starting box on host branch "${current}"`);
955
+ return { useBranch: current };
956
+ }
957
+ opts.log?.(
958
+ "cloud.useCurrentBranch is set but host HEAD is detached; forking a fresh branch instead"
959
+ );
960
+ }
961
+ return {};
962
+ }
963
+
964
+ // src/lib/launch-recap.ts
965
+ function homeShorten(p) {
966
+ const home = homedir2();
967
+ return p === home || p.startsWith(home + "/") ? "~" + p.slice(home.length) : p;
968
+ }
969
+ function whiten(text) {
970
+ if (process.env.NO_COLOR) return text;
971
+ return text.split("\n").map((line) => `\x1B[0m\x1B[97m${line}\x1B[0m`).join("\n");
972
+ }
973
+ async function printLaunchRecap(args) {
974
+ const { record } = args;
975
+ const rows = [];
976
+ rows.push([
977
+ "box",
978
+ args.checkpointRef ? `${record.name} (${args.checkpointRef})` : record.name
979
+ ]);
980
+ if (record.projectRoot) {
981
+ rows.push(["project", homeShorten(record.projectRoot)]);
982
+ }
983
+ const toBranch = record.gitWorktrees?.find((w) => w.kind === "root")?.branch;
984
+ if (toBranch) {
985
+ if (args.useBranch) {
986
+ rows.push(["branch", `${toBranch} (reused)`]);
987
+ } else {
988
+ const base = args.fromBranch ?? await currentHostBranch(args.workspacePath) ?? "HEAD";
989
+ rows.push(["branch", `${base} \u2192 ${toBranch}`]);
990
+ }
991
+ }
992
+ const pad4 = Math.max(...rows.map(([label]) => label.length)) + 2;
993
+ const body = rows.map(([label, value]) => `${label.padEnd(pad4)}${value}`).join("\n");
994
+ const instruction = args.attaching ? `Ctrl+a d to detach. Reattach with: agentbox ${args.mode} attach ${args.reattach}` : `Attach with: agentbox ${args.mode} attach ${args.reattach}`;
995
+ note(whiten(`${body}
996
+
997
+ ${instruction}`));
998
+ }
999
+
870
1000
  // src/commands/_cloud-agent-create.ts
871
1001
  async function cloudAgentCreate(args) {
872
1002
  const s = makeProgressReporter(args.verbose === true);
@@ -877,12 +1007,7 @@ async function cloudAgentCreate(args) {
877
1007
  onLog: (line) => s.message(line)
878
1008
  });
879
1009
  const nSuffix = typeof result.record.projectIndex === "number" ? ` \xB7 n ${String(result.record.projectIndex)}` : "";
880
- s.stop(`box ${result.record.name} ready${nSuffix}`);
881
- log4.info(`id: ${result.record.id}`);
882
- log4.info(`provider: ${result.record.provider}`);
883
- if (result.record.cloud?.sandboxId) {
884
- log4.info(`sandboxId: ${result.record.cloud.sandboxId}`);
885
- }
1010
+ s.stop(`box ready${nSuffix}`);
886
1011
  let extraArgs = args.extraArgs;
887
1012
  if (args.beforeStart) {
888
1013
  const hook = await args.beforeStart(result.record);
@@ -890,13 +1015,19 @@ async function cloudAgentCreate(args) {
890
1015
  extraArgs = [...hook.agentArgsPrefix, ...extraArgs ?? []];
891
1016
  }
892
1017
  }
1018
+ await printLaunchRecap({
1019
+ record: result.record,
1020
+ mode: args.mode,
1021
+ reattach: typeof result.record.projectIndex === "number" ? String(result.record.projectIndex) : result.record.name,
1022
+ workspacePath: args.request.workspacePath,
1023
+ fromBranch: args.request.fromBranch,
1024
+ useBranch: args.request.useBranch,
1025
+ checkpointRef: args.request.checkpointRef,
1026
+ attaching: args.attach !== false
1027
+ });
893
1028
  if (args.attach === false) {
894
- outro(
895
- `session not started \u2014 attach with: agentbox ${args.mode} attach ${result.record.name}`
896
- );
897
1029
  return;
898
1030
  }
899
- outro(`attaching ${args.mode} \u2014 Control+a d to detach, leaves the agent running`);
900
1031
  await cloudAgentAttach({
901
1032
  box: result.record,
902
1033
  binary: args.binary,
@@ -915,7 +1046,7 @@ async function cloudAgentCreate(args) {
915
1046
  import { join as join4 } from "path";
916
1047
 
917
1048
  // src/carry-prompt.ts
918
- import { isCancel, log as log5, select } from "@clack/prompts";
1049
+ import { isCancel, log as log4, select } from "@clack/prompts";
919
1050
 
920
1051
  // src/fmt.ts
921
1052
  function fmtBytes(n) {
@@ -999,7 +1130,7 @@ function printSummary(entries) {
999
1130
  ` ${pad(e.rawSrc, srcW)} \u2192 ${pad(e.rawDest, destW)} ${pad(size, 9)} ${flags.join(", ")}`
1000
1131
  );
1001
1132
  }
1002
- log5.message(rows.join("\n"));
1133
+ log4.message(rows.join("\n"));
1003
1134
  }
1004
1135
  function pad(s, w) {
1005
1136
  if (s.length >= w) return s;
@@ -1008,13 +1139,13 @@ function pad(s, w) {
1008
1139
 
1009
1140
  // src/lib/carry-resolve.ts
1010
1141
  import { realpath, stat as stat2 } from "fs/promises";
1011
- import { homedir as homedir2 } from "os";
1142
+ import { homedir as homedir3 } from "os";
1012
1143
  import { isAbsolute, join as join3, normalize, resolve } from "path";
1013
1144
  var DEFAULT_MAX_BYTES = 50 * 1024 * 1024;
1014
1145
  var DENYLIST_DEST_PREFIXES = ["/proc", "/sys", "/dev"];
1015
1146
  var DENYLIST_DEST_EXACT = /* @__PURE__ */ new Set(["/etc/passwd", "/etc/shadow"]);
1016
1147
  async function resolveCarry(items, opts) {
1017
- const home = opts.homeDir ?? homedir2();
1148
+ const home = opts.homeDir ?? homedir3();
1018
1149
  const cap = opts.maxBytes ?? readMaxBytesFromEnv() ?? DEFAULT_MAX_BYTES;
1019
1150
  const projectRoot = opts.projectRoot;
1020
1151
  const entries = [];
@@ -1208,7 +1339,7 @@ async function dirSizeCapped(dir, cap) {
1208
1339
 
1209
1340
  // src/lib/carry-gate.ts
1210
1341
  async function runCarryGate(args) {
1211
- const log45 = args.onLog ?? (() => {
1342
+ const log44 = args.onLog ?? (() => {
1212
1343
  });
1213
1344
  const yamlPath = join4(args.projectRoot, "agentbox.yaml");
1214
1345
  const items = await loadCarrySection(yamlPath);
@@ -1230,108 +1361,16 @@ async function runCarryGate(args) {
1230
1361
  });
1231
1362
  if (decision === "cancel") return { decision: "cancel" };
1232
1363
  if (decision === "skip-this-run") {
1233
- log45(`carry: skipped for this box (${String(resolved.entries.length)} entry/entries not copied)`);
1364
+ log44(`carry: skipped for this box (${String(resolved.entries.length)} entry/entries not copied)`);
1234
1365
  return { decision: "skip", entries: [] };
1235
1366
  }
1236
1367
  return { decision: "approve", entries: resolved.entries };
1237
1368
  }
1238
1369
 
1239
- // src/lib/from-branch.ts
1240
- import { execa } from "execa";
1241
- var SHA_RE = /^[0-9a-f]{7,40}$/i;
1242
- var FromBranchError = class extends Error {
1243
- constructor(message) {
1244
- super(message);
1245
- this.name = "FromBranchError";
1246
- }
1247
- };
1248
- async function resolveFromBranch(ref, opts) {
1249
- if (!ref || ref.length === 0) return void 0;
1250
- const remote = opts.remote ?? "origin";
1251
- const isSha = SHA_RE.test(ref);
1252
- if (!isSha) {
1253
- const fetched = await execa(
1254
- "git",
1255
- ["-C", opts.repo, "fetch", "--quiet", remote, ref],
1256
- { reject: false }
1257
- );
1258
- if (fetched.exitCode !== 0) {
1259
- }
1260
- }
1261
- const verify = await execa(
1262
- "git",
1263
- ["-C", opts.repo, "rev-parse", "--verify", `${ref}^{commit}`],
1264
- { reject: false }
1265
- );
1266
- if (verify.exitCode !== 0) {
1267
- throw new FromBranchError(
1268
- `--from-branch: unknown ref "${ref}" (not found in ${opts.repo} after fetch). Provide a branch, tag, or SHA reachable from the host repo.`
1269
- );
1270
- }
1271
- return ref;
1272
- }
1273
- var UseBranchError = class extends Error {
1274
- constructor(message) {
1275
- super(message);
1276
- this.name = "UseBranchError";
1277
- }
1278
- };
1279
- async function resolveUseBranch(name, opts) {
1280
- if (!name || name.length === 0) return void 0;
1281
- const remote = opts.remote ?? "origin";
1282
- await execa("git", ["-C", opts.repo, "fetch", "--quiet", remote, name], {
1283
- reject: false
1284
- });
1285
- const exists = await execa(
1286
- "git",
1287
- ["-C", opts.repo, "show-ref", "--verify", "--quiet", `refs/heads/${name}`],
1288
- { reject: false }
1289
- );
1290
- if (exists.exitCode !== 0) {
1291
- throw new UseBranchError(
1292
- `--use-branch: no local branch "${name}" in ${opts.repo}. Create or check it out on the host first (--use-branch reuses an existing branch; use --from-branch to fork a new box branch from a ref).`
1293
- );
1294
- }
1295
- return name;
1296
- }
1297
- async function currentHostBranch(repo) {
1298
- const r = await execa("git", ["-C", repo, "rev-parse", "--abbrev-ref", "HEAD"], {
1299
- reject: false
1300
- });
1301
- if (r.exitCode !== 0) return void 0;
1302
- const branch = r.stdout.trim();
1303
- if (!branch || branch === "HEAD") return void 0;
1304
- return branch;
1305
- }
1306
- async function resolveBranchSelection(opts) {
1307
- if (opts.useBranch && opts.fromBranch) {
1308
- throw new UseBranchError(
1309
- "--use-branch and --from-branch are mutually exclusive: --use-branch reuses an existing branch, --from-branch forks a new box branch from a base ref. Pass only one."
1310
- );
1311
- }
1312
- if (opts.useBranch) {
1313
- return { useBranch: await resolveUseBranch(opts.useBranch, { repo: opts.repo }) };
1314
- }
1315
- if (opts.fromBranch) {
1316
- return { fromBranch: await resolveFromBranch(opts.fromBranch, { repo: opts.repo }) };
1317
- }
1318
- if (opts.providerName !== "docker" && opts.cloudUseCurrentBranch) {
1319
- const current = await currentHostBranch(opts.repo);
1320
- if (current) {
1321
- opts.log?.(`cloud.useCurrentBranch: starting box on host branch "${current}"`);
1322
- return { useBranch: current };
1323
- }
1324
- opts.log?.(
1325
- "cloud.useCurrentBranch is set but host HEAD is detached; forking a fresh branch instead"
1326
- );
1327
- }
1328
- return {};
1329
- }
1330
-
1331
1370
  // src/session-teleport/claude.ts
1332
1371
  import { mkdir, mkdtemp, readdir, readFile as readFile2, stat as stat3, writeFile } from "fs/promises";
1333
1372
  import { existsSync } from "fs";
1334
- import { homedir as homedir3, tmpdir } from "os";
1373
+ import { homedir as homedir4, tmpdir } from "os";
1335
1374
  import { join as join5 } from "path";
1336
1375
 
1337
1376
  // src/session-teleport/cwd-encoding.ts
@@ -1352,7 +1391,7 @@ var TeleportError = class extends Error {
1352
1391
  // src/session-teleport/claude.ts
1353
1392
  var BOX_CLAUDE_PROJECTS_DIR = `/home/vscode/.claude/projects/${BOX_WORKSPACE_ENCODED}`;
1354
1393
  async function resolveClaudeTeleport(opts) {
1355
- const hostHome = opts.hostHome ?? homedir3();
1394
+ const hostHome = opts.hostHome ?? homedir4();
1356
1395
  const projectDir = join5(
1357
1396
  hostHome,
1358
1397
  ".claude",
@@ -1439,10 +1478,10 @@ async function rewriteSessionFile(src, dst, hostCwd) {
1439
1478
  // src/session-teleport/codex.ts
1440
1479
  import { mkdtemp as mkdtemp2, readdir as readdir2, readFile as readFile3, stat as stat4, writeFile as writeFile2 } from "fs/promises";
1441
1480
  import { existsSync as existsSync2 } from "fs";
1442
- import { homedir as homedir4, tmpdir as tmpdir2 } from "os";
1481
+ import { homedir as homedir5, tmpdir as tmpdir2 } from "os";
1443
1482
  import { join as join6 } from "path";
1444
1483
  async function resolveCodexTeleport(opts) {
1445
- const hostHome = opts.hostHome ?? homedir4();
1484
+ const hostHome = opts.hostHome ?? homedir5();
1446
1485
  const sessionsRoot = join6(hostHome, ".codex", "sessions");
1447
1486
  if (!existsSync2(sessionsRoot)) {
1448
1487
  throw new TeleportError(
@@ -1649,29 +1688,29 @@ async function uploadTeleport(input) {
1649
1688
  }
1650
1689
 
1651
1690
  // src/lib/install-hint.ts
1652
- import { log as log6 } from "@clack/prompts";
1691
+ import { log as log5 } from "@clack/prompts";
1653
1692
  import { existsSync as existsSync3, mkdirSync, writeFileSync } from "fs";
1654
- import { homedir as homedir5 } from "os";
1693
+ import { homedir as homedir6 } from "os";
1655
1694
  import { join as join7 } from "path";
1656
1695
  function maybeShowInstallHint() {
1657
1696
  try {
1658
- const skill = join7(homedir5(), ".claude", "skills", "agentbox", "SKILL.md");
1697
+ const skill = join7(homedir6(), ".claude", "skills", "agentbox", "SKILL.md");
1659
1698
  if (existsSync3(skill)) return;
1660
- const marker = join7(homedir5(), ".agentbox", "install-hint-shown");
1699
+ const marker = join7(homedir6(), ".agentbox", "install-hint-shown");
1661
1700
  if (existsSync3(marker)) return;
1662
- mkdirSync(join7(homedir5(), ".agentbox"), { recursive: true });
1701
+ mkdirSync(join7(homedir6(), ".agentbox"), { recursive: true });
1663
1702
  writeFileSync(marker, "");
1664
- log6.info("tip: run 'agentbox install' to enable the /agentbox fork command in host Claude");
1703
+ log5.info("tip: run 'agentbox install' to enable the /agentbox fork command in host Claude");
1665
1704
  } catch {
1666
1705
  }
1667
1706
  }
1668
1707
 
1669
1708
  // src/lib/log-file.ts
1670
1709
  import { closeSync, mkdirSync as mkdirSync2, openSync, renameSync, symlinkSync, unlinkSync, writeFileSync as writeFileSync2, writeSync } from "fs";
1671
- import { homedir as homedir6 } from "os";
1710
+ import { homedir as homedir7 } from "os";
1672
1711
  import { join as join8 } from "path";
1673
1712
  function stateDir() {
1674
- return process.env.AGENTBOX_HOME ?? join8(homedir6(), ".agentbox");
1713
+ return process.env.AGENTBOX_HOME ?? join8(homedir7(), ".agentbox");
1675
1714
  }
1676
1715
  function logsDir() {
1677
1716
  return join8(stateDir(), "logs");
@@ -1795,7 +1834,7 @@ function resolveLimits(box, flags) {
1795
1834
  }
1796
1835
 
1797
1836
  // src/portless-prompt.ts
1798
- import { confirm, isCancel as isCancel2, log as log7, spinner as spinner2 } from "@clack/prompts";
1837
+ import { confirm, isCancel as isCancel2, log as log6, spinner as spinner2 } from "@clack/prompts";
1799
1838
  async function setupPortlessHost() {
1800
1839
  let state = await detectPortless();
1801
1840
  if (!state.installed) {
@@ -1805,13 +1844,13 @@ async function setupPortlessHost() {
1805
1844
  resetPortlessCache();
1806
1845
  s2.stop(ok ? "portless installed" : "portless install failed");
1807
1846
  if (!ok) {
1808
- log7.warn(`Could not install Portless \u2014 run \`${portlessInstallHint()}\` yourself.`);
1847
+ log6.warn(`Could not install Portless \u2014 run \`${portlessInstallHint()}\` yourself.`);
1809
1848
  return;
1810
1849
  }
1811
1850
  state = await detectPortless();
1812
1851
  }
1813
1852
  if (state.proxyRunning) {
1814
- log7.info("Portless proxy already running \u2014 boxes will use it.");
1853
+ log6.info("Portless proxy already running \u2014 boxes will use it.");
1815
1854
  return;
1816
1855
  }
1817
1856
  const s = spinner2();
@@ -1823,7 +1862,7 @@ async function setupPortlessHost() {
1823
1862
  s.stop("portless proxy started");
1824
1863
  } else {
1825
1864
  s.stop("portless proxy did not start");
1826
- log7.warn(`Could not start the Portless proxy \u2014 run \`${portlessStartHint()}\` yourself.`);
1865
+ log6.warn(`Could not start the Portless proxy \u2014 run \`${portlessStartHint()}\` yourself.`);
1827
1866
  }
1828
1867
  }
1829
1868
  async function maybePromptPortless(args) {
@@ -1838,7 +1877,7 @@ async function maybePromptPortless(args) {
1838
1877
  try {
1839
1878
  await setConfigValue("global", "portless.enabled", answer, args.cwd, { raw: false });
1840
1879
  } catch (err) {
1841
- log7.warn(
1880
+ log6.warn(
1842
1881
  `Could not save the Portless preference: ${err instanceof Error ? err.message : String(err)}`
1843
1882
  );
1844
1883
  }
@@ -1847,18 +1886,18 @@ async function maybePromptPortless(args) {
1847
1886
  }
1848
1887
 
1849
1888
  // src/wizard.ts
1850
- import { confirm as confirm2, isCancel as isCancel3, log as log8, multiselect } from "@clack/prompts";
1889
+ import { confirm as confirm2, isCancel as isCancel3, log as log7, multiselect } from "@clack/prompts";
1851
1890
  import { basename } from "path";
1852
1891
 
1853
1892
  // src/provider/cloud-backend.ts
1854
1893
  async function cloudBackendForProvider(provider) {
1855
1894
  switch (provider) {
1856
1895
  case "daytona":
1857
- return (await import("./dist-BD5QJRDC.js")).daytonaBackend;
1896
+ return (await import("./dist-PTJ6CEQY.js")).daytonaBackend;
1858
1897
  case "hetzner":
1859
- return (await import("./dist-BNI5PQYK.js")).hetznerBackend;
1898
+ return (await import("./dist-WMQDMTWS.js")).hetznerBackend;
1860
1899
  case "vercel":
1861
- return (await import("./dist-SJHY3HYN.js")).vercelBackend;
1900
+ return (await import("./dist-RAZP76VX.js")).vercelBackend;
1862
1901
  default:
1863
1902
  return null;
1864
1903
  }
@@ -1909,7 +1948,7 @@ async function maybeRunSetupWizard(args) {
1909
1948
  const proj = await findProjectRoot(args.workspace);
1910
1949
  if (proj.hasAgentboxYaml) return { action: "proceed" };
1911
1950
  if (args.checkpointRef && await checkpointAppliesHere(args)) {
1912
- log8.info(`starting from checkpoint "${args.checkpointRef}"; skipping agentbox.yaml setup`);
1951
+ log7.info(`starting from checkpoint "${args.checkpointRef}"; skipping agentbox.yaml setup`);
1913
1952
  return { action: "proceed" };
1914
1953
  }
1915
1954
  let envFilesToImport;
@@ -1998,7 +2037,7 @@ function logPrune(rebuild) {
1998
2037
  if (rebuild.prunedBytes <= 0) return;
1999
2038
  const mb = Math.round(rebuild.prunedBytes / 1024 / 1024);
2000
2039
  const n = rebuild.pruned.length;
2001
- log9.info(`pruned ${String(n)} stale plugin cache${n === 1 ? "" : "s"} (${String(mb)} MB freed)`);
2040
+ log8.info(`pruned ${String(n)} stale plugin cache${n === 1 ? "" : "s"} (${String(mb)} MB freed)`);
2002
2041
  }
2003
2042
  var RELAY_HOST_URL = `http://127.0.0.1:${String(DEFAULT_RELAY_PORT)}`;
2004
2043
  async function attachClaudeWrapped(box, sessionName, reattach, onError, openIn) {
@@ -2062,7 +2101,7 @@ async function maybeRunClaudeLogin(args) {
2062
2101
  const message = args.authSource === "auth-file" ? "You're on a legacy API token (shows as 'Claude API'). Sign in with your Claude subscription instead?" : "Sign in with your Claude subscription? (saved and reused by every box)";
2063
2102
  const answer = await confirm3({ message, initialValue: true });
2064
2103
  if (isCancel4(answer) || !answer) {
2065
- log9.info("Skipped sign-in \u2014 claude will prompt you to /login inside the box.");
2104
+ log8.info("Skipped sign-in \u2014 claude will prompt you to /login inside the box.");
2066
2105
  return;
2067
2106
  }
2068
2107
  const s = spinner3();
@@ -2076,10 +2115,10 @@ async function maybeRunClaudeLogin(args) {
2076
2115
  s.stop("image ready");
2077
2116
  const exitCode = await runClaudeLoginContainer(args.image, ["--claudeai"]);
2078
2117
  if (exitCode !== 0) {
2079
- log9.warn("Claude login did not complete; continuing \u2014 run `agentbox claude login` to retry.");
2118
+ log8.warn("Claude login did not complete; continuing \u2014 run `agentbox claude login` to retry.");
2080
2119
  return;
2081
2120
  }
2082
- log9.success("Signed in with your Claude subscription \u2014 saved for future boxes.");
2121
+ log8.success("Signed in with your Claude subscription \u2014 saved for future boxes.");
2083
2122
  }
2084
2123
  async function maybeRunCloudClaudeLogin(args) {
2085
2124
  if (!process.stdin.isTTY || args.yes) return;
@@ -2090,7 +2129,7 @@ async function maybeRunCloudClaudeLogin(args) {
2090
2129
  const message = expired ? "Your saved Claude login looks expired. Sign in again? (saved and reused by every box)" : "Sign in with your Claude subscription? (saved and reused by every box)";
2091
2130
  const answer = await confirm3({ message, initialValue: true });
2092
2131
  if (isCancel4(answer) || !answer) {
2093
- log9.info("Skipped sign-in \u2014 claude will prompt you to /login inside the box.");
2132
+ log8.info("Skipped sign-in \u2014 claude will prompt you to /login inside the box.");
2094
2133
  return;
2095
2134
  }
2096
2135
  const s = spinner3();
@@ -2104,10 +2143,10 @@ async function maybeRunCloudClaudeLogin(args) {
2104
2143
  s.stop("image ready");
2105
2144
  const exitCode = await runClaudeLoginContainer(args.image, ["--claudeai"]);
2106
2145
  if (exitCode !== 0) {
2107
- log9.warn("Claude login did not complete; continuing \u2014 run `agentbox claude login` to retry.");
2146
+ log8.warn("Claude login did not complete; continuing \u2014 run `agentbox claude login` to retry.");
2108
2147
  return;
2109
2148
  }
2110
- log9.success("Signed in with your Claude subscription \u2014 saved for future boxes.");
2149
+ log8.success("Signed in with your Claude subscription \u2014 saved for future boxes.");
2111
2150
  }
2112
2151
  var claudeCommand = new Command2("claude").description("Create a sandboxed box and launch Claude Code in a detachable tmux session").option("-w, --workspace <path>", "host workspace to mount", process.cwd()).option("-n, --name <name>", "friendly box name (default: <workspace-basename>-<id>)").option("--host-snapshot", "APFS-clone the host workspace into a per-box scratch dir before seeding /workspace (stabilizes the tar-pipe source)").option("--no-host-snapshot", "tar-pipe directly from the live host workspace at create time").option(
2113
2152
  "--snapshot <ref>",
@@ -2174,14 +2213,14 @@ var claudeCommand = new Command2("claude").description("Create a sandboxed box a
2174
2213
  intro("Starting Claude in a box...");
2175
2214
  let resumeMode = null;
2176
2215
  if (opts.continue === true && opts.resume) {
2177
- log9.error("only one of -c / --continue / --resume can be passed");
2216
+ log8.error("only one of -c / --continue / --resume can be passed");
2178
2217
  cmdLog.close();
2179
2218
  process.exit(2);
2180
2219
  }
2181
2220
  if (opts.continue === true) resumeMode = { kind: "continue" };
2182
2221
  else if (opts.resume) resumeMode = { kind: "resume", id: opts.resume };
2183
2222
  if (resumeMode && opts.initialPrompt && opts.initialPrompt.length > 0) {
2184
- log9.error("-i / --initial-prompt cannot be combined with -c / --resume (seeding a new turn into a resumed session is not supported).");
2223
+ log8.error("-i / --initial-prompt cannot be combined with -c / --resume (seeding a new turn into a resumed session is not supported).");
2185
2224
  cmdLog.close();
2186
2225
  process.exit(2);
2187
2226
  }
@@ -2196,7 +2235,7 @@ var claudeCommand = new Command2("claude").description("Create a sandboxed box a
2196
2235
  });
2197
2236
  } catch (err) {
2198
2237
  if (err instanceof TeleportError) {
2199
- log9.error(err.message);
2238
+ log8.error(err.message);
2200
2239
  cmdLog.close();
2201
2240
  process.exit(2);
2202
2241
  }
@@ -2211,7 +2250,7 @@ var claudeCommand = new Command2("claude").description("Create a sandboxed box a
2211
2250
  const isCloud = providerName !== "docker";
2212
2251
  if (opts.initialPrompt && opts.initialPrompt.length > 0) {
2213
2252
  if (isCloud) {
2214
- log9.error("-i / --initial-prompt is currently docker-only (cloud sessions only start on attach).");
2253
+ log8.error("-i / --initial-prompt is currently docker-only (cloud sessions only start on attach).");
2215
2254
  cmdLog.close();
2216
2255
  process.exit(2);
2217
2256
  }
@@ -2222,7 +2261,7 @@ var claudeCommand = new Command2("claude").description("Create a sandboxed box a
2222
2261
  });
2223
2262
  } catch (err) {
2224
2263
  if (err instanceof MissingAgentCredsError) {
2225
- log9.error(err.message);
2264
+ log8.error(err.message);
2226
2265
  cmdLog.close();
2227
2266
  process.exit(2);
2228
2267
  }
@@ -2240,7 +2279,7 @@ var claudeCommand = new Command2("claude").description("Create a sandboxed box a
2240
2279
  maxRunningOverride,
2241
2280
  maxWorkingOverride
2242
2281
  });
2243
- outro2(
2282
+ outro(
2244
2283
  `job ${result.job.id} queued (${String(result.runningCount)}/${String(result.maxConcurrent)} running); log: ${result.job.logPath}`
2245
2284
  );
2246
2285
  cmdLog.close();
@@ -2280,13 +2319,13 @@ var claudeCommand = new Command2("claude").description("Create a sandboxed box a
2280
2319
  onLog: (line) => cmdLog.write(line)
2281
2320
  });
2282
2321
  if (gate.decision === "cancel") {
2283
- log9.warn("carry: cancelled \u2014 not creating the box");
2322
+ log8.warn("carry: cancelled \u2014 not creating the box");
2284
2323
  cmdLog.close();
2285
2324
  process.exit(0);
2286
2325
  }
2287
2326
  if (gate.decision === "approve") carryEntries = gate.entries;
2288
2327
  } catch (err) {
2289
- log9.error(err instanceof Error ? err.message : String(err));
2328
+ log8.error(err instanceof Error ? err.message : String(err));
2290
2329
  cmdLog.close();
2291
2330
  process.exit(1);
2292
2331
  }
@@ -2316,7 +2355,7 @@ var claudeCommand = new Command2("claude").description("Create a sandboxed box a
2316
2355
  }));
2317
2356
  } catch (err) {
2318
2357
  if (err instanceof FromBranchError || err instanceof UseBranchError) {
2319
- log9.error(err.message);
2358
+ log8.error(err.message);
2320
2359
  cmdLog.close();
2321
2360
  process.exit(2);
2322
2361
  }
@@ -2360,7 +2399,7 @@ var claudeCommand = new Command2("claude").description("Create a sandboxed box a
2360
2399
  return { agentArgsPrefix: resumePrepared.forwardArgs };
2361
2400
  } catch (err) {
2362
2401
  if (err instanceof TeleportError) {
2363
- log9.error(err.message);
2402
+ log8.error(err.message);
2364
2403
  cmdLog.close();
2365
2404
  process.exit(2);
2366
2405
  }
@@ -2430,8 +2469,8 @@ var claudeCommand = new Command2("claude").description("Create a sandboxed box a
2430
2469
  } catch (err) {
2431
2470
  if (err instanceof TeleportError) {
2432
2471
  s.stop("teleport failed");
2433
- log9.error(err.message);
2434
- log9.info(
2472
+ log8.error(err.message);
2473
+ log8.info(
2435
2474
  `The box ${result.record.container} is up but unused. Destroy it with: agentbox destroy ${result.record.container} -y`
2436
2475
  );
2437
2476
  cmdLog.close();
@@ -2448,20 +2487,26 @@ var claudeCommand = new Command2("claude").description("Create a sandboxed box a
2448
2487
  boxName: result.record.name
2449
2488
  });
2450
2489
  const nSuffix = typeof result.record.projectIndex === "number" ? ` \xB7 n ${String(result.record.projectIndex)}` : "";
2451
- s.stop(`box ${result.record.container} ready${nSuffix}`);
2490
+ s.stop(`box ready${nSuffix}`);
2452
2491
  logPrune(rebuild);
2453
2492
  for (const f of rebuild.failed) {
2454
- log9.warn(`plugin install failed for ${f.dir}; claude may still load it. stderr:
2493
+ log8.warn(`plugin install failed for ${f.dir}; claude may still load it. stderr:
2455
2494
  ${f.stderr.trim()}`);
2456
2495
  }
2457
2496
  maybeShowInstallHint();
2497
+ await printLaunchRecap({
2498
+ record: result.record,
2499
+ mode: "claude",
2500
+ reattach: reattachRef(result.record),
2501
+ workspacePath: opts.workspace,
2502
+ fromBranch,
2503
+ useBranch,
2504
+ checkpointRef,
2505
+ attaching: opts.attach !== false
2506
+ });
2458
2507
  if (opts.attach === false) {
2459
- outro2(
2460
- `session started \u2014 attach with: agentbox claude attach ${reattachRef(result.record)}`
2461
- );
2462
2508
  return;
2463
2509
  }
2464
- outro2("attaching \u2014 Control+a d to detach, leaves claude running");
2465
2510
  await attachClaudeWrapped(
2466
2511
  result.record,
2467
2512
  sessionName,
@@ -2473,10 +2518,10 @@ ${f.stderr.trim()}`);
2473
2518
  s.stop("failed");
2474
2519
  cmdLog.write(`FAIL: ${err instanceof Error ? err.stack ?? err.message : String(err)}`);
2475
2520
  if (err instanceof ClaudeSessionError) {
2476
- log9.error(err.message);
2521
+ log8.error(err.message);
2477
2522
  if (containerName) {
2478
- log9.info(`The box ${containerName} is still running. Destroy it with:`);
2479
- log9.info(` agentbox destroy ${containerName} -y`);
2523
+ log8.info(`The box ${containerName} is still running. Destroy it with:`);
2524
+ log8.info(` agentbox destroy ${containerName} -y`);
2480
2525
  }
2481
2526
  cmdLog.close();
2482
2527
  process.exit(1);
@@ -2514,12 +2559,12 @@ async function startOrAttachClaude(box, claudeArgs, opts, resumePrepared) {
2514
2559
  );
2515
2560
  }
2516
2561
  if (!wantAttach) {
2517
- outro2(
2562
+ outro(
2518
2563
  `session "${sessionName}" already running \u2014 attach with: agentbox claude attach ${reattachRef(box)}`
2519
2564
  );
2520
2565
  return;
2521
2566
  }
2522
- outro2(`session "${sessionName}" already running \u2014 attaching (Control+a d to detach)`);
2567
+ outro(`session "${sessionName}" already running \u2014 attaching (Control+a d to detach)`);
2523
2568
  await attachClaudeWrapped(box, sessionName, reattachRef(box), void 0, openIn);
2524
2569
  return;
2525
2570
  }
@@ -2577,7 +2622,7 @@ async function startOrAttachClaude(box, claudeArgs, opts, resumePrepared) {
2577
2622
  } catch (err) {
2578
2623
  if (err instanceof TeleportError) {
2579
2624
  s.stop("teleport failed");
2580
- log9.error(err.message);
2625
+ log8.error(err.message);
2581
2626
  process.exit(2);
2582
2627
  }
2583
2628
  throw err;
@@ -2593,16 +2638,16 @@ async function startOrAttachClaude(box, claudeArgs, opts, resumePrepared) {
2593
2638
  s.stop(`box ${box.container} ready`);
2594
2639
  logPrune(rebuild);
2595
2640
  for (const f of rebuild.failed) {
2596
- log9.warn(`plugin install failed for ${f.dir}; claude may still load it. stderr:
2641
+ log8.warn(`plugin install failed for ${f.dir}; claude may still load it. stderr:
2597
2642
  ${f.stderr.trim()}`);
2598
2643
  }
2599
2644
  if (!wantAttach) {
2600
- outro2(
2645
+ outro(
2601
2646
  `session "${sessionName}" started \u2014 attach with: agentbox claude attach ${reattachRef(box)}`
2602
2647
  );
2603
2648
  return;
2604
2649
  }
2605
- outro2("attaching \u2014 Control+a d to detach, leaves claude running");
2650
+ outro("attaching \u2014 Control+a d to detach, leaves claude running");
2606
2651
  await attachClaudeWrapped(box, sessionName, reattachRef(box), void 0, openIn);
2607
2652
  }
2608
2653
  var claudeAttachCommand = new Command2("attach").description(
@@ -2632,7 +2677,7 @@ var claudeAttachCommand = new Command2("attach").description(
2632
2677
  await startOrAttachClaude(box, [], { ...opts, syncConfig: false });
2633
2678
  } catch (err) {
2634
2679
  if (err instanceof ClaudeSessionError) {
2635
- log9.error(err.message);
2680
+ log8.error(err.message);
2636
2681
  process.exit(1);
2637
2682
  }
2638
2683
  handleLifecycleError(err);
@@ -2664,7 +2709,7 @@ var claudeStartCommand = new Command2("start").description(
2664
2709
  let effectiveClaudeArgs = shifted && idOrName ? [idOrName, ...claudeArgs] : claudeArgs;
2665
2710
  let resumeMode = null;
2666
2711
  if (opts.continue === true && opts.resume) {
2667
- log9.error("only one of -c / --continue / --resume can be passed");
2712
+ log8.error("only one of -c / --continue / --resume can be passed");
2668
2713
  process.exit(2);
2669
2714
  }
2670
2715
  if (opts.continue === true) resumeMode = { kind: "continue" };
@@ -2679,7 +2724,7 @@ var claudeStartCommand = new Command2("start").description(
2679
2724
  });
2680
2725
  } catch (err) {
2681
2726
  if (err instanceof TeleportError) {
2682
- log9.error(err.message);
2727
+ log8.error(err.message);
2683
2728
  process.exit(2);
2684
2729
  }
2685
2730
  throw err;
@@ -2687,7 +2732,7 @@ var claudeStartCommand = new Command2("start").description(
2687
2732
  }
2688
2733
  if ((box.provider ?? "docker") !== "docker") {
2689
2734
  if (opts.attach === false) {
2690
- outro2(
2735
+ outro(
2691
2736
  `--no-attach: cloud agent sessions are started lazily on attach. Run: agentbox claude attach ${reattachRef(box)}`
2692
2737
  );
2693
2738
  return;
@@ -2706,7 +2751,7 @@ var claudeStartCommand = new Command2("start").description(
2706
2751
  effectiveClaudeArgs = [...resumePrepared.forwardArgs, ...effectiveClaudeArgs];
2707
2752
  } catch (err) {
2708
2753
  if (err instanceof TeleportError) {
2709
- log9.error(err.message);
2754
+ log8.error(err.message);
2710
2755
  process.exit(2);
2711
2756
  }
2712
2757
  throw err;
@@ -2725,7 +2770,7 @@ var claudeStartCommand = new Command2("start").description(
2725
2770
  await startOrAttachClaude(box, effectiveClaudeArgs, opts, resumePrepared);
2726
2771
  } catch (err) {
2727
2772
  if (err instanceof ClaudeSessionError) {
2728
- log9.error(err.message);
2773
+ log8.error(err.message);
2729
2774
  process.exit(1);
2730
2775
  }
2731
2776
  handleLifecycleError(err);
@@ -2739,7 +2784,7 @@ var claudeLoginCommand = new Command2("login").description(
2739
2784
  ).action(async (args) => {
2740
2785
  intro("Signing in to Claude...");
2741
2786
  if (!process.stdin.isTTY) {
2742
- log9.error("`agentbox claude login` needs an interactive terminal.");
2787
+ log8.error("`agentbox claude login` needs an interactive terminal.");
2743
2788
  process.exit(1);
2744
2789
  }
2745
2790
  try {
@@ -2751,10 +2796,10 @@ var claudeLoginCommand = new Command2("login").description(
2751
2796
  s.stop("image ready");
2752
2797
  const exitCode = await runClaudeLoginContainer(image, args);
2753
2798
  if (exitCode !== 0) {
2754
- log9.warn(`\`claude auth login\` exited with code ${String(exitCode)}`);
2799
+ log8.warn(`\`claude auth login\` exited with code ${String(exitCode)}`);
2755
2800
  process.exit(exitCode);
2756
2801
  }
2757
- outro2("signed in \u2014 credentials saved for future boxes");
2802
+ outro("signed in \u2014 credentials saved for future boxes");
2758
2803
  } catch (err) {
2759
2804
  handleLifecycleError(err);
2760
2805
  }
@@ -2764,17 +2809,17 @@ claudeCommand.addCommand(claudeStartCommand);
2764
2809
  claudeCommand.addCommand(claudeLoginCommand);
2765
2810
 
2766
2811
  // src/commands/checkpoint.ts
2767
- import { confirm as confirm4, isCancel as isCancel5, log as log10 } from "@clack/prompts";
2812
+ import { confirm as confirm4, isCancel as isCancel5, log as log9 } from "@clack/prompts";
2768
2813
  import { Command as Command3 } from "commander";
2769
2814
  var CLOUD_BACKENDS = ["daytona", "hetzner", "vercel"];
2770
2815
  async function cloudProviderFor(backend) {
2771
2816
  switch (backend) {
2772
2817
  case "daytona":
2773
- return (await import("./dist-BD5QJRDC.js")).daytonaProvider;
2818
+ return (await import("./dist-PTJ6CEQY.js")).daytonaProvider;
2774
2819
  case "hetzner":
2775
- return (await import("./dist-BNI5PQYK.js")).hetznerProvider;
2820
+ return (await import("./dist-WMQDMTWS.js")).hetznerProvider;
2776
2821
  case "vercel":
2777
- return (await import("./dist-SJHY3HYN.js")).vercelProvider;
2822
+ return (await import("./dist-RAZP76VX.js")).vercelProvider;
2778
2823
  }
2779
2824
  }
2780
2825
  var CHECKPOINT_NOTICE = "Checkpoint in progress \u2014 the box will be unresponsive for a moment";
@@ -2798,10 +2843,10 @@ var createSub = new Command3("create").description("Capture a box state as a pro
2798
2843
  }
2799
2844
  const insp = await inspectBox(box.id);
2800
2845
  if (insp.state === "paused") {
2801
- log10.info("box is paused; unpausing");
2846
+ log9.info("box is paused; unpausing");
2802
2847
  await unpauseBox(box.id);
2803
2848
  } else if (insp.state === "stopped") {
2804
- log10.info("box is stopped; starting");
2849
+ log9.info("box is stopped; starting");
2805
2850
  await startBox(box.id);
2806
2851
  } else if (insp.state === "missing") {
2807
2852
  throw new Error(`box ${box.name} has no container; was it destroyed?`);
@@ -2836,13 +2881,13 @@ var createSub = new Command3("create").description("Capture a box state as a pro
2836
2881
  setDefault: opts.setDefault === true,
2837
2882
  replace: opts.replace === true,
2838
2883
  maxLayers: cfg.effective.checkpoint.maxLayers,
2839
- onLog: (line) => log10.info(line)
2884
+ onLog: (line) => log9.info(line)
2840
2885
  });
2841
- log10.success(
2886
+ log9.success(
2842
2887
  `checkpoint ${info.name} (${info.manifest.type}) -> ${info.dir}` + (opts.setDefault ? " [project default]" : "")
2843
2888
  );
2844
2889
  if (!opts.setDefault) {
2845
- log10.info(
2890
+ log9.info(
2846
2891
  `make it the default for new boxes: agentbox checkpoint set-default ${info.name}`
2847
2892
  );
2848
2893
  }
@@ -2957,7 +3002,7 @@ var rmSub = new Command3("rm").description("Delete a checkpoint (any provider th
2957
3002
  if (!opts.yes) {
2958
3003
  const ok = await confirm4({ message: `Delete checkpoint ${ref}?`, initialValue: false });
2959
3004
  if (isCancel5(ok) || !ok) {
2960
- log10.info("cancelled");
3005
+ log9.info("cancelled");
2961
3006
  return;
2962
3007
  }
2963
3008
  }
@@ -2978,7 +3023,7 @@ var rmSub = new Command3("rm").description("Delete a checkpoint (any provider th
2978
3023
  process.stdout.write(`removed ${backend} checkpoint ${ref}
2979
3024
  `);
2980
3025
  } catch (err) {
2981
- log10.warn(
3026
+ log9.warn(
2982
3027
  `${backend} checkpoint remove failed: ${err instanceof Error ? err.message : String(err)}`
2983
3028
  );
2984
3029
  }
@@ -2996,9 +3041,9 @@ var rmSub = new Command3("rm").description("Delete a checkpoint (any provider th
2996
3041
  for (const [key, projectValue, effectiveValue] of defKeys) {
2997
3042
  if (projectValue === ref) {
2998
3043
  await unsetConfigValue("project", key, projectRoot);
2999
- log10.info(`cleared project ${key} (was ${ref})`);
3044
+ log9.info(`cleared project ${key} (was ${ref})`);
3000
3045
  } else if (effectiveValue === ref) {
3001
- log10.warn(
3046
+ log9.warn(
3002
3047
  `${key} = ${ref} is set outside the per-project config (global or agentbox.yaml defaults) \u2014 clear it manually`
3003
3048
  );
3004
3049
  }
@@ -3009,17 +3054,17 @@ var rmSub = new Command3("rm").description("Delete a checkpoint (any provider th
3009
3054
  });
3010
3055
  async function runCloudCheckpointCreate(box, opts) {
3011
3056
  if (opts.merged) {
3012
- log10.warn("--merged is Docker-only (cloud snapshots are always flattened); ignoring");
3057
+ log9.warn("--merged is Docker-only (cloud snapshots are always flattened); ignoring");
3013
3058
  }
3014
3059
  const projectRoot = await projectRootFor(box.workspacePath, box.projectRoot);
3015
3060
  const name = opts.name ?? `${box.name}-${String(Date.now()).slice(-6)}`;
3016
3061
  const provider = await providerForBox(box);
3017
3062
  const state = await provider.probeState(box);
3018
3063
  if (state === "paused") {
3019
- log10.info("box is paused; resuming");
3064
+ log9.info("box is paused; resuming");
3020
3065
  await provider.resume(box);
3021
3066
  } else if (state === "stopped") {
3022
- log10.info("box is stopped; starting");
3067
+ log9.info("box is stopped; starting");
3023
3068
  await provider.start(box);
3024
3069
  } else if (state === "missing") {
3025
3070
  throw new Error(`cloud sandbox for ${box.name} is missing; was it deleted?`);
@@ -3033,7 +3078,7 @@ async function runCloudCheckpointCreate(box, opts) {
3033
3078
  initialValue: false
3034
3079
  });
3035
3080
  if (isCancel5(ok) || !ok) {
3036
- log10.info("cancelled");
3081
+ log9.info("cancelled");
3037
3082
  return;
3038
3083
  }
3039
3084
  }
@@ -3048,21 +3093,21 @@ async function runCloudCheckpointCreate(box, opts) {
3048
3093
  try {
3049
3094
  const saved = await provider.extractAgentCredentials(box);
3050
3095
  if (saved.length > 0) {
3051
- log10.info(`saved ${saved.join(", ")} login to ~/.agentbox for future boxes`);
3096
+ log9.info(`saved ${saved.join(", ")} login to ~/.agentbox for future boxes`);
3052
3097
  }
3053
3098
  } catch (err) {
3054
- log10.warn(`agent credential extract skipped: ${err instanceof Error ? err.message : String(err)}`);
3099
+ log9.warn(`agent credential extract skipped: ${err instanceof Error ? err.message : String(err)}`);
3055
3100
  }
3056
3101
  }
3057
- log10.info(`capturing cloud snapshot '${name}' (this may take a few minutes)`);
3102
+ log9.info(`capturing cloud snapshot '${name}' (this may take a few minutes)`);
3058
3103
  const result = await provider.checkpoint.create(box, name);
3059
- log10.success(`checkpoint ${result.ref} (daytona snapshot) captured`);
3104
+ log9.success(`checkpoint ${result.ref} (daytona snapshot) captured`);
3060
3105
  if (opts.setDefault) {
3061
3106
  const key = defaultCheckpointConfigKey(box.provider ?? "daytona");
3062
3107
  await setConfigValue("project", key, result.ref, projectRoot);
3063
- log10.info(`set project default checkpoint (${key}) -> ${result.ref}`);
3108
+ log9.info(`set project default checkpoint (${key}) -> ${result.ref}`);
3064
3109
  } else {
3065
- log10.info(
3110
+ log9.info(
3066
3111
  `make it the default for new boxes: agentbox checkpoint set-default --provider ${box.provider ?? "daytona"} ${result.ref}`
3067
3112
  );
3068
3113
  }
@@ -3074,15 +3119,15 @@ var checkpointCommand = new Command3("checkpoint").alias("checkpoints").descript
3074
3119
 
3075
3120
  // src/commands/code.ts
3076
3121
  import { spawn } from "child_process";
3077
- import { log as log11 } from "@clack/prompts";
3122
+ import { log as log10 } from "@clack/prompts";
3078
3123
  import { Command as Command4, InvalidArgumentError } from "commander";
3079
3124
 
3080
3125
  // src/ssh-config.ts
3081
3126
  import { promises as fs } from "fs";
3082
- import { homedir as homedir7 } from "os";
3127
+ import { homedir as homedir8 } from "os";
3083
3128
  import { join as join9 } from "path";
3084
3129
  function sshConfigPath() {
3085
- return join9(homedir7(), ".ssh", "config");
3130
+ return join9(homedir8(), ".ssh", "config");
3086
3131
  }
3087
3132
  function beginMarker(alias) {
3088
3133
  return `# BEGIN agentbox cloud box ${alias}`;
@@ -3133,7 +3178,7 @@ function buildBlock(opts) {
3133
3178
  }
3134
3179
  async function writeAgentboxSshAlias(opts) {
3135
3180
  const path = sshConfigPath();
3136
- await fs.mkdir(join9(homedir7(), ".ssh"), { recursive: true, mode: 448 });
3181
+ await fs.mkdir(join9(homedir8(), ".ssh"), { recursive: true, mode: 448 });
3137
3182
  const existing = await readConfig();
3138
3183
  const stripped = stripBlock(existing, opts.alias);
3139
3184
  const separator = stripped.length === 0 || stripped.endsWith("\n") ? "" : "\n";
@@ -3215,11 +3260,11 @@ var codeCommand = new Command4("code").description("Open a box in VS Code or Cur
3215
3260
  }
3216
3261
  const exit = await launchIde(folderUri, forcedIde);
3217
3262
  if (exit.code !== 0) {
3218
- log11.error(`failed to launch ${exit.flavor ? ideProfile(exit.flavor).displayName : "IDE"} via ${exit.via} (exit ${String(exit.code)})`);
3263
+ log10.error(`failed to launch ${exit.flavor ? ideProfile(exit.flavor).displayName : "IDE"} via ${exit.via} (exit ${String(exit.code)})`);
3219
3264
  process.stdout.write(folderUri + "\n");
3220
3265
  process.exit(1);
3221
3266
  }
3222
- log11.success(
3267
+ log10.success(
3223
3268
  `opening ${box.name} in ${ideProfile(exit.flavor).displayName} (${exit.via})`
3224
3269
  );
3225
3270
  } catch (err) {
@@ -3229,10 +3274,10 @@ var codeCommand = new Command4("code").description("Open a box in VS Code or Cur
3229
3274
  async function prepareDockerAttach(box, opts) {
3230
3275
  const insp = await inspectBox(box.id);
3231
3276
  if (insp.state === "paused") {
3232
- log11.info(`box is paused; unpausing`);
3277
+ log10.info(`box is paused; unpausing`);
3233
3278
  await unpauseBox(box.id);
3234
3279
  } else if (insp.state === "stopped") {
3235
- log11.info(`box is stopped; starting`);
3280
+ log10.info(`box is stopped; starting`);
3236
3281
  await startBox(box.id);
3237
3282
  } else if (insp.state === "missing") {
3238
3283
  throw new Error(`box ${box.name} has no container; was it destroyed?`);
@@ -3243,9 +3288,9 @@ async function prepareDockerAttach(box, opts) {
3243
3288
  const lines = [];
3244
3289
  if (reply.timedOut.length > 0) lines.push(`timed out: ${reply.timedOut.join(", ")}`);
3245
3290
  if (reply.failed.length > 0) lines.push(`failed: ${reply.failed.join(", ")}`);
3246
- log11.warn(`box not fully ready (${lines.join("; ")}). Opening anyway.`);
3291
+ log10.warn(`box not fully ready (${lines.join("; ")}). Opening anyway.`);
3247
3292
  } else {
3248
- log11.success("all units ready");
3293
+ log10.success("all units ready");
3249
3294
  }
3250
3295
  }
3251
3296
  if (opts.autoTerminals) {
@@ -3255,14 +3300,14 @@ async function prepareDockerAttach(box, opts) {
3255
3300
  regen: opts.regenTasks
3256
3301
  });
3257
3302
  if (r.status === "wrote") {
3258
- log11.info(`wrote /workspace/.vscode/tasks.json (${String(services.length)} service(s))`);
3303
+ log10.info(`wrote /workspace/.vscode/tasks.json (${String(services.length)} service(s))`);
3259
3304
  } else if (r.status === "skipped-user-owned") {
3260
- log11.warn(
3305
+ log10.warn(
3261
3306
  "user-owned .vscode/tasks.json detected; skipping auto-terminals (pass --regen-tasks to overwrite)"
3262
3307
  );
3263
3308
  }
3264
3309
  } catch (err) {
3265
- log11.warn(
3310
+ log10.warn(
3266
3311
  `auto-terminals failed: ${err instanceof Error ? err.message : String(err)}`
3267
3312
  );
3268
3313
  }
@@ -3274,10 +3319,10 @@ async function prepareCloudAttach(box, opts) {
3274
3319
  const p = await providerForBox(box);
3275
3320
  const state = await p.probeState(box);
3276
3321
  if (state === "paused") {
3277
- log11.info("box is paused; resuming");
3322
+ log10.info("box is paused; resuming");
3278
3323
  await p.resume(box);
3279
3324
  } else if (state === "stopped") {
3280
- log11.info("box is stopped; starting");
3325
+ log10.info("box is stopped; starting");
3281
3326
  await p.start(box);
3282
3327
  } else if (state === "missing") {
3283
3328
  throw new Error(`cloud sandbox for ${box.name} is missing; was it deleted?`);
@@ -3290,12 +3335,12 @@ async function prepareCloudAttach(box, opts) {
3290
3335
  const lines = [];
3291
3336
  if (reply.timedOut.length > 0) lines.push(`timed out: ${reply.timedOut.join(", ")}`);
3292
3337
  if (reply.failed.length > 0) lines.push(`failed: ${reply.failed.join(", ")}`);
3293
- log11.warn(`box not fully ready (${lines.join("; ")}). Opening anyway.`);
3338
+ log10.warn(`box not fully ready (${lines.join("; ")}). Opening anyway.`);
3294
3339
  } else {
3295
- log11.success("all units ready");
3340
+ log10.success("all units ready");
3296
3341
  }
3297
3342
  } catch (err) {
3298
- log11.warn(`wait-ready failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
3343
+ log10.warn(`wait-ready failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
3299
3344
  }
3300
3345
  }
3301
3346
  if (!p.buildAttach) {
@@ -3317,7 +3362,7 @@ async function prepareCloudAttach(box, opts) {
3317
3362
  user: target.user,
3318
3363
  identityFile: target.identityFile
3319
3364
  });
3320
- log11.info(`updated ~/.ssh/config alias ${alias}`);
3365
+ log10.info(`updated ~/.ssh/config alias ${alias}`);
3321
3366
  return `vscode-remote://ssh-remote+${alias}/workspace`;
3322
3367
  }
3323
3368
  async function runWaitReadyDocker(container, timeoutMs) {
@@ -3342,7 +3387,7 @@ async function launchIde(folderUri, forced) {
3342
3387
  if (code !== null) return code;
3343
3388
  const cursor = await tryCli("cursor", folderUri);
3344
3389
  if (cursor !== null) return cursor;
3345
- log11.warn("neither `code` nor `cursor` found in PATH; falling back to `open vscode://...`");
3390
+ log10.warn("neither `code` nor `cursor` found in PATH; falling back to `open vscode://...`");
3346
3391
  return launchOne("vscode", folderUri);
3347
3392
  }
3348
3393
  async function tryCli(flavor, folderUri) {
@@ -3355,11 +3400,11 @@ async function launchOne(flavor, folderUri) {
3355
3400
  const profile = ideProfile(flavor);
3356
3401
  const cliCode = await spawnCommand(profile.cli, ["--folder-uri", folderUri]);
3357
3402
  if (cliCode !== 127) return { code: cliCode, flavor, via: "cli" };
3358
- log11.warn(
3359
- `\`${profile.cli}\` not found in PATH; falling back to \`open ${profile.protocolScheme}://...\` (the %2B URL-encoding bug may break attach)`
3403
+ log10.warn(
3404
+ `\`${profile.cli}\` not found in PATH; falling back to \`${hostOpenCommand()} ${profile.protocolScheme}://...\` (the %2B URL-encoding bug may break attach)`
3360
3405
  );
3361
3406
  const url = `${profile.protocolScheme}://${folderUri.replace(/^vscode-remote:\/\//, "vscode-remote/")}`;
3362
- const fallback = await spawnCommand("open", [url]);
3407
+ const fallback = await spawnCommand(hostOpenCommand(), [url]);
3363
3408
  return { code: fallback, flavor, via: "open" };
3364
3409
  }
3365
3410
  function spawnCommand(cmd, args) {
@@ -3384,9 +3429,9 @@ async function fetchServiceNamesDocker(container) {
3384
3429
 
3385
3430
  // src/commands/codex.ts
3386
3431
  import { access } from "fs/promises";
3387
- import { homedir as homedir8 } from "os";
3432
+ import { homedir as homedir9 } from "os";
3388
3433
  import { join as join10 } from "path";
3389
- import { confirm as confirm5, intro as intro2, isCancel as isCancel6, log as log12, outro as outro3, spinner as spinner4 } from "@clack/prompts";
3434
+ import { confirm as confirm5, intro as intro2, isCancel as isCancel6, log as log11, outro as outro2, spinner as spinner4 } from "@clack/prompts";
3390
3435
  import { Command as Command5 } from "commander";
3391
3436
  function reattachRef2(r) {
3392
3437
  return typeof r.projectIndex === "number" ? String(r.projectIndex) : r.name;
@@ -3463,7 +3508,7 @@ async function maybeRunCodexLogin(args) {
3463
3508
  initialValue: true
3464
3509
  });
3465
3510
  if (isCancel6(answer) || !answer) {
3466
- log12.info("Skipped sign-in \u2014 codex will prompt you to sign in inside the box.");
3511
+ log11.info("Skipped sign-in \u2014 codex will prompt you to sign in inside the box.");
3467
3512
  return;
3468
3513
  }
3469
3514
  const s = spinner4();
@@ -3474,14 +3519,14 @@ async function maybeRunCodexLogin(args) {
3474
3519
  s.stop("image ready");
3475
3520
  const exitCode = await runCodexLoginContainer(args.image, []);
3476
3521
  if (exitCode !== 0) {
3477
- log12.warn("Codex login did not complete; continuing \u2014 run `agentbox codex login` to retry.");
3522
+ log11.warn("Codex login did not complete; continuing \u2014 run `agentbox codex login` to retry.");
3478
3523
  return;
3479
3524
  }
3480
- log12.success("Signed in to Codex \u2014 saved for future boxes.");
3525
+ log11.success("Signed in to Codex \u2014 saved for future boxes.");
3481
3526
  }
3482
3527
  async function cloudCodexCredAvailable(env = process.env) {
3483
3528
  if ((env["OPENAI_API_KEY"] ?? "").length > 0) return true;
3484
- for (const p of [CODEX_CREDENTIALS_BACKUP_FILE, join10(homedir8(), ".codex", "auth.json")]) {
3529
+ for (const p of [CODEX_CREDENTIALS_BACKUP_FILE, join10(homedir9(), ".codex", "auth.json")]) {
3485
3530
  try {
3486
3531
  await access(p);
3487
3532
  return true;
@@ -3498,7 +3543,7 @@ async function maybeRunCloudCodexLogin(args) {
3498
3543
  initialValue: true
3499
3544
  });
3500
3545
  if (isCancel6(answer) || !answer) {
3501
- log12.info("Skipped sign-in \u2014 codex will prompt you to sign in inside the box.");
3546
+ log11.info("Skipped sign-in \u2014 codex will prompt you to sign in inside the box.");
3502
3547
  return;
3503
3548
  }
3504
3549
  const s = spinner4();
@@ -3509,12 +3554,12 @@ async function maybeRunCloudCodexLogin(args) {
3509
3554
  s.stop("image ready");
3510
3555
  const exitCode = await runCodexLoginContainer(args.image, []);
3511
3556
  if (exitCode !== 0) {
3512
- log12.warn("Codex login did not complete; continuing \u2014 run `agentbox codex login` to retry.");
3557
+ log11.warn("Codex login did not complete; continuing \u2014 run `agentbox codex login` to retry.");
3513
3558
  return;
3514
3559
  }
3515
3560
  const { copied } = await extractCodexCredentials(SHARED_CODEX_VOLUME, args.image);
3516
- if (copied) log12.success("Signed in to Codex \u2014 saved for future boxes.");
3517
- else log12.warn("Codex login finished but no auth.json was captured \u2014 sign in inside the box if needed.");
3561
+ if (copied) log11.success("Signed in to Codex \u2014 saved for future boxes.");
3562
+ else log11.warn("Codex login finished but no auth.json was captured \u2014 sign in inside the box if needed.");
3518
3563
  }
3519
3564
  var codexCommand = new Command5("codex").description("Create a sandboxed box and launch OpenAI Codex in a detachable tmux session").option("-w, --workspace <path>", "host workspace to mount", process.cwd()).option("-n, --name <name>", "friendly box name (default: <workspace-basename>-<id>)").option("--host-snapshot", "APFS-clone the host workspace into a per-box scratch dir before seeding /workspace (stabilizes the tar-pipe source)").option("--no-host-snapshot", "tar-pipe directly from the live host workspace at create time").option(
3520
3565
  "--snapshot <ref>",
@@ -3581,14 +3626,14 @@ var codexCommand = new Command5("codex").description("Create a sandboxed box and
3581
3626
  intro2("Starting Codex in a box...");
3582
3627
  let resumeMode = null;
3583
3628
  if (opts.continue === true && opts.resume) {
3584
- log12.error("only one of -c / --continue / --resume can be passed");
3629
+ log11.error("only one of -c / --continue / --resume can be passed");
3585
3630
  cmdLog.close();
3586
3631
  process.exit(2);
3587
3632
  }
3588
3633
  if (opts.continue === true) resumeMode = { kind: "continue" };
3589
3634
  else if (opts.resume) resumeMode = { kind: "resume", id: opts.resume };
3590
3635
  if (resumeMode && opts.initialPrompt && opts.initialPrompt.length > 0) {
3591
- log12.error("-i / --initial-prompt cannot be combined with -c / --resume.");
3636
+ log11.error("-i / --initial-prompt cannot be combined with -c / --resume.");
3592
3637
  cmdLog.close();
3593
3638
  process.exit(2);
3594
3639
  }
@@ -3603,7 +3648,7 @@ var codexCommand = new Command5("codex").description("Create a sandboxed box and
3603
3648
  });
3604
3649
  } catch (err) {
3605
3650
  if (err instanceof TeleportError) {
3606
- log12.error(err.message);
3651
+ log11.error(err.message);
3607
3652
  cmdLog.close();
3608
3653
  process.exit(2);
3609
3654
  }
@@ -3620,7 +3665,7 @@ var codexCommand = new Command5("codex").description("Create a sandboxed box and
3620
3665
  const checkpointRef = opts.snapshot && opts.snapshot.length > 0 ? opts.snapshot : providerDefault.length > 0 ? providerDefault : void 0;
3621
3666
  if (opts.initialPrompt && opts.initialPrompt.length > 0) {
3622
3667
  if (isCloud) {
3623
- log12.error("-i / --initial-prompt is currently docker-only (cloud sessions only start on attach).");
3668
+ log11.error("-i / --initial-prompt is currently docker-only (cloud sessions only start on attach).");
3624
3669
  cmdLog.close();
3625
3670
  process.exit(2);
3626
3671
  }
@@ -3631,7 +3676,7 @@ var codexCommand = new Command5("codex").description("Create a sandboxed box and
3631
3676
  });
3632
3677
  } catch (err) {
3633
3678
  if (err instanceof MissingAgentCredsError) {
3634
- log12.error(err.message);
3679
+ log11.error(err.message);
3635
3680
  cmdLog.close();
3636
3681
  process.exit(2);
3637
3682
  }
@@ -3649,7 +3694,7 @@ var codexCommand = new Command5("codex").description("Create a sandboxed box and
3649
3694
  maxRunningOverride,
3650
3695
  maxWorkingOverride
3651
3696
  });
3652
- outro3(
3697
+ outro2(
3653
3698
  `job ${result.job.id} queued (${String(result.runningCount)}/${String(result.maxConcurrent)} running); log: ${result.job.logPath}`
3654
3699
  );
3655
3700
  cmdLog.close();
@@ -3665,13 +3710,13 @@ var codexCommand = new Command5("codex").description("Create a sandboxed box and
3665
3710
  onLog: (line) => cmdLog.write(line)
3666
3711
  });
3667
3712
  if (gate.decision === "cancel") {
3668
- log12.warn("carry: cancelled \u2014 not creating the box");
3713
+ log11.warn("carry: cancelled \u2014 not creating the box");
3669
3714
  cmdLog.close();
3670
3715
  process.exit(0);
3671
3716
  }
3672
3717
  if (gate.decision === "approve") carryEntries = gate.entries;
3673
3718
  } catch (err) {
3674
- log12.error(err instanceof Error ? err.message : String(err));
3719
+ log11.error(err instanceof Error ? err.message : String(err));
3675
3720
  cmdLog.close();
3676
3721
  process.exit(1);
3677
3722
  }
@@ -3688,7 +3733,7 @@ var codexCommand = new Command5("codex").description("Create a sandboxed box and
3688
3733
  }));
3689
3734
  } catch (err) {
3690
3735
  if (err instanceof FromBranchError || err instanceof UseBranchError) {
3691
- log12.error(err.message);
3736
+ log11.error(err.message);
3692
3737
  cmdLog.close();
3693
3738
  process.exit(2);
3694
3739
  }
@@ -3732,7 +3777,7 @@ var codexCommand = new Command5("codex").description("Create a sandboxed box and
3732
3777
  return { agentArgsPrefix: resumePrepared.forwardArgs };
3733
3778
  } catch (err) {
3734
3779
  if (err instanceof TeleportError) {
3735
- log12.error(err.message);
3780
+ log11.error(err.message);
3736
3781
  cmdLog.close();
3737
3782
  process.exit(2);
3738
3783
  }
@@ -3807,8 +3852,8 @@ var codexCommand = new Command5("codex").description("Create a sandboxed box and
3807
3852
  } catch (err) {
3808
3853
  if (err instanceof TeleportError) {
3809
3854
  s.stop("teleport failed");
3810
- log12.error(err.message);
3811
- log12.info(
3855
+ log11.error(err.message);
3856
+ log11.info(
3812
3857
  `The box ${result.record.container} is up but unused. Destroy it with: agentbox destroy ${result.record.container} -y`
3813
3858
  );
3814
3859
  cmdLog.close();
@@ -3824,14 +3869,20 @@ var codexCommand = new Command5("codex").description("Create a sandboxed box and
3824
3869
  sessionName
3825
3870
  });
3826
3871
  const nSuffix = typeof result.record.projectIndex === "number" ? ` \xB7 n ${String(result.record.projectIndex)}` : "";
3827
- s.stop(`box ${result.record.container} ready${nSuffix}`);
3872
+ s.stop(`box ready${nSuffix}`);
3873
+ await printLaunchRecap({
3874
+ record: result.record,
3875
+ mode: "codex",
3876
+ reattach: reattachRef2(result.record),
3877
+ workspacePath: opts.workspace,
3878
+ fromBranch,
3879
+ useBranch,
3880
+ checkpointRef,
3881
+ attaching: opts.attach !== false
3882
+ });
3828
3883
  if (opts.attach === false) {
3829
- outro3(
3830
- `session started \u2014 attach with: agentbox codex attach ${reattachRef2(result.record)}`
3831
- );
3832
3884
  return;
3833
3885
  }
3834
- outro3("attaching \u2014 Control+a d to detach, leaves codex running");
3835
3886
  await attachCodexWrapped(
3836
3887
  result.record,
3837
3888
  sessionName,
@@ -3843,10 +3894,10 @@ var codexCommand = new Command5("codex").description("Create a sandboxed box and
3843
3894
  s.stop("failed");
3844
3895
  cmdLog.write(`FAIL: ${err instanceof Error ? err.stack ?? err.message : String(err)}`);
3845
3896
  if (err instanceof CodexSessionError) {
3846
- log12.error(err.message);
3897
+ log11.error(err.message);
3847
3898
  if (containerName) {
3848
- log12.info(`The box ${containerName} is still running. Destroy it with:`);
3849
- log12.info(` agentbox destroy ${containerName} -y`);
3899
+ log11.info(`The box ${containerName} is still running. Destroy it with:`);
3900
+ log11.info(` agentbox destroy ${containerName} -y`);
3850
3901
  }
3851
3902
  cmdLog.close();
3852
3903
  process.exit(1);
@@ -3883,12 +3934,12 @@ async function startOrAttachCodex(box, codexArgs, opts, resumePrepared) {
3883
3934
  );
3884
3935
  }
3885
3936
  if (!wantAttach) {
3886
- outro3(
3937
+ outro2(
3887
3938
  `session "${sessionName}" already running \u2014 attach with: agentbox codex attach ${reattachRef2(box)}`
3888
3939
  );
3889
3940
  return;
3890
3941
  }
3891
- outro3(`session "${sessionName}" already running \u2014 attaching (Control+a d to detach)`);
3942
+ outro2(`session "${sessionName}" already running \u2014 attaching (Control+a d to detach)`);
3892
3943
  await attachCodexWrapped(box, sessionName, reattachRef2(box), void 0, openIn);
3893
3944
  return;
3894
3945
  }
@@ -3932,7 +3983,7 @@ async function startOrAttachCodex(box, codexArgs, opts, resumePrepared) {
3932
3983
  } catch (err) {
3933
3984
  if (err instanceof TeleportError) {
3934
3985
  s.stop("teleport failed");
3935
- log12.error(err.message);
3986
+ log11.error(err.message);
3936
3987
  process.exit(2);
3937
3988
  }
3938
3989
  throw err;
@@ -3942,12 +3993,12 @@ async function startOrAttachCodex(box, codexArgs, opts, resumePrepared) {
3942
3993
  await startCodexSession({ container: box.container, codexArgs: effectiveArgs, sessionName });
3943
3994
  s.stop(`box ${box.container} ready`);
3944
3995
  if (!wantAttach) {
3945
- outro3(
3996
+ outro2(
3946
3997
  `session "${sessionName}" started \u2014 attach with: agentbox codex attach ${reattachRef2(box)}`
3947
3998
  );
3948
3999
  return;
3949
4000
  }
3950
- outro3("attaching \u2014 Control+a d to detach, leaves codex running");
4001
+ outro2("attaching \u2014 Control+a d to detach, leaves codex running");
3951
4002
  await attachCodexWrapped(box, sessionName, reattachRef2(box), void 0, openIn);
3952
4003
  }
3953
4004
  var codexAttachCommand = new Command5("attach").description(
@@ -3977,7 +4028,7 @@ var codexAttachCommand = new Command5("attach").description(
3977
4028
  await startOrAttachCodex(box, [], { ...opts, syncConfig: false });
3978
4029
  } catch (err) {
3979
4030
  if (err instanceof CodexSessionError) {
3980
- log12.error(err.message);
4031
+ log11.error(err.message);
3981
4032
  process.exit(1);
3982
4033
  }
3983
4034
  handleLifecycleError(err);
@@ -4009,7 +4060,7 @@ var codexStartCommand = new Command5("start").description(
4009
4060
  let effectiveCodexArgs = shifted && idOrName ? [idOrName, ...codexArgs] : codexArgs;
4010
4061
  let resumeMode = null;
4011
4062
  if (opts.continue === true && opts.resume) {
4012
- log12.error("only one of -c / --continue / --resume can be passed");
4063
+ log11.error("only one of -c / --continue / --resume can be passed");
4013
4064
  process.exit(2);
4014
4065
  }
4015
4066
  if (opts.continue === true) resumeMode = { kind: "continue" };
@@ -4024,7 +4075,7 @@ var codexStartCommand = new Command5("start").description(
4024
4075
  });
4025
4076
  } catch (err) {
4026
4077
  if (err instanceof TeleportError) {
4027
- log12.error(err.message);
4078
+ log11.error(err.message);
4028
4079
  process.exit(2);
4029
4080
  }
4030
4081
  throw err;
@@ -4032,7 +4083,7 @@ var codexStartCommand = new Command5("start").description(
4032
4083
  }
4033
4084
  if ((box.provider ?? "docker") !== "docker") {
4034
4085
  if (opts.attach === false) {
4035
- outro3(
4086
+ outro2(
4036
4087
  `--no-attach: cloud agent sessions are started lazily on attach. Run: agentbox codex attach ${reattachRef2(box)}`
4037
4088
  );
4038
4089
  return;
@@ -4051,7 +4102,7 @@ var codexStartCommand = new Command5("start").description(
4051
4102
  effectiveCodexArgs = [...resumePrepared.forwardArgs, ...effectiveCodexArgs];
4052
4103
  } catch (err) {
4053
4104
  if (err instanceof TeleportError) {
4054
- log12.error(err.message);
4105
+ log11.error(err.message);
4055
4106
  process.exit(2);
4056
4107
  }
4057
4108
  throw err;
@@ -4070,7 +4121,7 @@ var codexStartCommand = new Command5("start").description(
4070
4121
  await startOrAttachCodex(box, effectiveCodexArgs, opts, resumePrepared);
4071
4122
  } catch (err) {
4072
4123
  if (err instanceof CodexSessionError) {
4073
- log12.error(err.message);
4124
+ log11.error(err.message);
4074
4125
  process.exit(1);
4075
4126
  }
4076
4127
  handleLifecycleError(err);
@@ -4084,7 +4135,7 @@ var codexLoginCommand = new Command5("login").description(
4084
4135
  ).action(async (args) => {
4085
4136
  intro2("Signing in to Codex...");
4086
4137
  if (!process.stdin.isTTY) {
4087
- log12.error("`agentbox codex login` needs an interactive terminal.");
4138
+ log11.error("`agentbox codex login` needs an interactive terminal.");
4088
4139
  process.exit(1);
4089
4140
  }
4090
4141
  try {
@@ -4098,10 +4149,10 @@ var codexLoginCommand = new Command5("login").description(
4098
4149
  s.stop("image ready");
4099
4150
  const exitCode = await runCodexLoginContainer(image, args);
4100
4151
  if (exitCode !== 0) {
4101
- log12.warn(`\`codex login\` exited with code ${String(exitCode)}`);
4152
+ log11.warn(`\`codex login\` exited with code ${String(exitCode)}`);
4102
4153
  process.exit(exitCode);
4103
4154
  }
4104
- outro3("signed in \u2014 credentials saved for future boxes");
4155
+ outro2("signed in \u2014 credentials saved for future boxes");
4105
4156
  } catch (err) {
4106
4157
  handleLifecycleError(err);
4107
4158
  }
@@ -4112,9 +4163,9 @@ codexCommand.addCommand(codexLoginCommand);
4112
4163
 
4113
4164
  // src/commands/opencode.ts
4114
4165
  import { access as access2 } from "fs/promises";
4115
- import { homedir as homedir9 } from "os";
4166
+ import { homedir as homedir10 } from "os";
4116
4167
  import { join as join11 } from "path";
4117
- import { confirm as confirm6, intro as intro3, isCancel as isCancel7, log as log13, outro as outro4, spinner as spinner5 } from "@clack/prompts";
4168
+ import { confirm as confirm6, intro as intro3, isCancel as isCancel7, log as log12, outro as outro3, spinner as spinner5 } from "@clack/prompts";
4118
4169
  import { Command as Command6 } from "commander";
4119
4170
  function reattachRef3(r) {
4120
4171
  return typeof r.projectIndex === "number" ? String(r.projectIndex) : r.name;
@@ -4188,7 +4239,7 @@ async function maybeRunOpencodeLogin(args) {
4188
4239
  initialValue: true
4189
4240
  });
4190
4241
  if (isCancel7(answer) || !answer) {
4191
- log13.info("Skipped sign-in \u2014 opencode will prompt you to sign in inside the box.");
4242
+ log12.info("Skipped sign-in \u2014 opencode will prompt you to sign in inside the box.");
4192
4243
  return;
4193
4244
  }
4194
4245
  const s = spinner5();
@@ -4202,16 +4253,16 @@ async function maybeRunOpencodeLogin(args) {
4202
4253
  s.stop("image ready");
4203
4254
  const exitCode = await runOpencodeLoginContainer(args.image, []);
4204
4255
  if (exitCode !== 0) {
4205
- log13.warn("OpenCode login did not complete; continuing \u2014 run `agentbox opencode login` to retry.");
4256
+ log12.warn("OpenCode login did not complete; continuing \u2014 run `agentbox opencode login` to retry.");
4206
4257
  return;
4207
4258
  }
4208
- log13.success("Signed in to OpenCode \u2014 saved for future boxes.");
4259
+ log12.success("Signed in to OpenCode \u2014 saved for future boxes.");
4209
4260
  }
4210
4261
  async function cloudOpencodeCredAvailable(env = process.env) {
4211
4262
  for (const k of OPENCODE_FORWARDED_ENV_KEYS) {
4212
4263
  if ((env[k] ?? "").length > 0) return true;
4213
4264
  }
4214
- for (const p of [OPENCODE_CREDENTIALS_BACKUP_FILE, join11(homedir9(), ".local", "share", "opencode", "auth.json")]) {
4265
+ for (const p of [OPENCODE_CREDENTIALS_BACKUP_FILE, join11(homedir10(), ".local", "share", "opencode", "auth.json")]) {
4215
4266
  try {
4216
4267
  await access2(p);
4217
4268
  return true;
@@ -4228,7 +4279,7 @@ async function maybeRunCloudOpencodeLogin(args) {
4228
4279
  initialValue: true
4229
4280
  });
4230
4281
  if (isCancel7(answer) || !answer) {
4231
- log13.info("Skipped sign-in \u2014 opencode will prompt you to sign in inside the box.");
4282
+ log12.info("Skipped sign-in \u2014 opencode will prompt you to sign in inside the box.");
4232
4283
  return;
4233
4284
  }
4234
4285
  const s = spinner5();
@@ -4242,12 +4293,12 @@ async function maybeRunCloudOpencodeLogin(args) {
4242
4293
  s.stop("image ready");
4243
4294
  const exitCode = await runOpencodeLoginContainer(args.image, []);
4244
4295
  if (exitCode !== 0) {
4245
- log13.warn("OpenCode login did not complete; continuing \u2014 run `agentbox opencode login` to retry.");
4296
+ log12.warn("OpenCode login did not complete; continuing \u2014 run `agentbox opencode login` to retry.");
4246
4297
  return;
4247
4298
  }
4248
4299
  const { copied } = await extractOpencodeCredentials(SHARED_OPENCODE_VOLUME, args.image);
4249
- if (copied) log13.success("Signed in to OpenCode \u2014 saved for future boxes.");
4250
- else log13.warn("OpenCode login finished but no auth.json was captured \u2014 sign in inside the box if needed.");
4300
+ if (copied) log12.success("Signed in to OpenCode \u2014 saved for future boxes.");
4301
+ else log12.warn("OpenCode login finished but no auth.json was captured \u2014 sign in inside the box if needed.");
4251
4302
  }
4252
4303
  var opencodeCommand = new Command6("opencode").description("Create a sandboxed box and launch OpenCode in a detachable tmux session").option("-w, --workspace <path>", "host workspace to mount", process.cwd()).option("-n, --name <name>", "friendly box name (default: <workspace-basename>-<id>)").option("--host-snapshot", "APFS-clone the host workspace into a per-box scratch dir before seeding /workspace (stabilizes the tar-pipe source)").option("--no-host-snapshot", "tar-pipe directly from the live host workspace at create time").option(
4253
4304
  "--snapshot <ref>",
@@ -4315,7 +4366,7 @@ var opencodeCommand = new Command6("opencode").description("Create a sandboxed b
4315
4366
  });
4316
4367
  } catch (err) {
4317
4368
  if (err instanceof TeleportError) {
4318
- log13.error(err.message);
4369
+ log12.error(err.message);
4319
4370
  cmdLog.close();
4320
4371
  process.exit(2);
4321
4372
  }
@@ -4332,7 +4383,7 @@ var opencodeCommand = new Command6("opencode").description("Create a sandboxed b
4332
4383
  const checkpointRef = opts.snapshot && opts.snapshot.length > 0 ? opts.snapshot : providerDefault.length > 0 ? providerDefault : void 0;
4333
4384
  if (opts.initialPrompt && opts.initialPrompt.length > 0) {
4334
4385
  if (isCloud) {
4335
- log13.error("-i / --initial-prompt is currently docker-only (cloud sessions only start on attach).");
4386
+ log12.error("-i / --initial-prompt is currently docker-only (cloud sessions only start on attach).");
4336
4387
  cmdLog.close();
4337
4388
  process.exit(2);
4338
4389
  }
@@ -4343,7 +4394,7 @@ var opencodeCommand = new Command6("opencode").description("Create a sandboxed b
4343
4394
  });
4344
4395
  } catch (err) {
4345
4396
  if (err instanceof MissingAgentCredsError) {
4346
- log13.error(err.message);
4397
+ log12.error(err.message);
4347
4398
  cmdLog.close();
4348
4399
  process.exit(2);
4349
4400
  }
@@ -4361,7 +4412,7 @@ var opencodeCommand = new Command6("opencode").description("Create a sandboxed b
4361
4412
  maxRunningOverride,
4362
4413
  maxWorkingOverride
4363
4414
  });
4364
- outro4(
4415
+ outro3(
4365
4416
  `job ${result.job.id} queued (${String(result.runningCount)}/${String(result.maxConcurrent)} running); log: ${result.job.logPath}`
4366
4417
  );
4367
4418
  cmdLog.close();
@@ -4377,13 +4428,13 @@ var opencodeCommand = new Command6("opencode").description("Create a sandboxed b
4377
4428
  onLog: (line) => cmdLog.write(line)
4378
4429
  });
4379
4430
  if (gate.decision === "cancel") {
4380
- log13.warn("carry: cancelled \u2014 not creating the box");
4431
+ log12.warn("carry: cancelled \u2014 not creating the box");
4381
4432
  cmdLog.close();
4382
4433
  process.exit(0);
4383
4434
  }
4384
4435
  if (gate.decision === "approve") carryEntries = gate.entries;
4385
4436
  } catch (err) {
4386
- log13.error(err instanceof Error ? err.message : String(err));
4437
+ log12.error(err instanceof Error ? err.message : String(err));
4387
4438
  cmdLog.close();
4388
4439
  process.exit(1);
4389
4440
  }
@@ -4400,7 +4451,7 @@ var opencodeCommand = new Command6("opencode").description("Create a sandboxed b
4400
4451
  }));
4401
4452
  } catch (err) {
4402
4453
  if (err instanceof FromBranchError || err instanceof UseBranchError) {
4403
- log13.error(err.message);
4454
+ log12.error(err.message);
4404
4455
  cmdLog.close();
4405
4456
  process.exit(2);
4406
4457
  }
@@ -4489,14 +4540,20 @@ var opencodeCommand = new Command6("opencode").description("Create a sandboxed b
4489
4540
  sessionName
4490
4541
  });
4491
4542
  const nSuffix = typeof result.record.projectIndex === "number" ? ` \xB7 n ${String(result.record.projectIndex)}` : "";
4492
- s.stop(`box ${result.record.container} ready${nSuffix}`);
4543
+ s.stop(`box ready${nSuffix}`);
4544
+ await printLaunchRecap({
4545
+ record: result.record,
4546
+ mode: "opencode",
4547
+ reattach: reattachRef3(result.record),
4548
+ workspacePath: opts.workspace,
4549
+ fromBranch,
4550
+ useBranch,
4551
+ checkpointRef,
4552
+ attaching: opts.attach !== false
4553
+ });
4493
4554
  if (opts.attach === false) {
4494
- outro4(
4495
- `session started \u2014 attach with: agentbox opencode attach ${reattachRef3(result.record)}`
4496
- );
4497
4555
  return;
4498
4556
  }
4499
- outro4("attaching \u2014 Control+a d to detach, leaves opencode running");
4500
4557
  await attachOpencodeWrapped(
4501
4558
  result.record,
4502
4559
  sessionName,
@@ -4508,10 +4565,10 @@ var opencodeCommand = new Command6("opencode").description("Create a sandboxed b
4508
4565
  s.stop("failed");
4509
4566
  cmdLog.write(`FAIL: ${err instanceof Error ? err.stack ?? err.message : String(err)}`);
4510
4567
  if (err instanceof OpencodeSessionError) {
4511
- log13.error(err.message);
4568
+ log12.error(err.message);
4512
4569
  if (containerName) {
4513
- log13.info(`The box ${containerName} is still running. Destroy it with:`);
4514
- log13.info(` agentbox destroy ${containerName} -y`);
4570
+ log12.info(`The box ${containerName} is still running. Destroy it with:`);
4571
+ log12.info(` agentbox destroy ${containerName} -y`);
4515
4572
  }
4516
4573
  cmdLog.close();
4517
4574
  process.exit(1);
@@ -4537,12 +4594,12 @@ async function startOrAttachOpencode(box, opencodeArgs, opts) {
4537
4594
  const existing = await opencodeSessionInfo(box.container, sessionName);
4538
4595
  if (existing.running) {
4539
4596
  if (!wantAttach) {
4540
- outro4(
4597
+ outro3(
4541
4598
  `session "${sessionName}" already running \u2014 attach with: agentbox opencode attach ${reattachRef3(box)}`
4542
4599
  );
4543
4600
  return;
4544
4601
  }
4545
- outro4(`session "${sessionName}" already running \u2014 attaching (Control+a d to detach)`);
4602
+ outro3(`session "${sessionName}" already running \u2014 attaching (Control+a d to detach)`);
4546
4603
  await attachOpencodeWrapped(box, sessionName, reattachRef3(box), void 0, openIn);
4547
4604
  return;
4548
4605
  }
@@ -4572,12 +4629,12 @@ async function startOrAttachOpencode(box, opencodeArgs, opts) {
4572
4629
  await startOpencodeSession({ container: box.container, opencodeArgs, sessionName });
4573
4630
  s.stop(`box ${box.container} ready`);
4574
4631
  if (!wantAttach) {
4575
- outro4(
4632
+ outro3(
4576
4633
  `session "${sessionName}" started \u2014 attach with: agentbox opencode attach ${reattachRef3(box)}`
4577
4634
  );
4578
4635
  return;
4579
4636
  }
4580
- outro4("attaching \u2014 Control+a d to detach, leaves opencode running");
4637
+ outro3("attaching \u2014 Control+a d to detach, leaves opencode running");
4581
4638
  await attachOpencodeWrapped(box, sessionName, reattachRef3(box), void 0, openIn);
4582
4639
  }
4583
4640
  var opencodeAttachCommand = new Command6("attach").description(
@@ -4607,7 +4664,7 @@ var opencodeAttachCommand = new Command6("attach").description(
4607
4664
  await startOrAttachOpencode(box, [], { ...opts, syncConfig: false });
4608
4665
  } catch (err) {
4609
4666
  if (err instanceof OpencodeSessionError) {
4610
- log13.error(err.message);
4667
+ log12.error(err.message);
4611
4668
  process.exit(1);
4612
4669
  }
4613
4670
  handleLifecycleError(err);
@@ -4646,7 +4703,7 @@ var opencodeStartCommand = new Command6("start").description(
4646
4703
  });
4647
4704
  } catch (err) {
4648
4705
  if (err instanceof TeleportError) {
4649
- log13.error(err.message);
4706
+ log12.error(err.message);
4650
4707
  process.exit(2);
4651
4708
  }
4652
4709
  throw err;
@@ -4654,7 +4711,7 @@ var opencodeStartCommand = new Command6("start").description(
4654
4711
  }
4655
4712
  if ((box.provider ?? "docker") !== "docker") {
4656
4713
  if (opts.attach === false) {
4657
- outro4(
4714
+ outro3(
4658
4715
  `--no-attach: cloud agent sessions are started lazily on attach. Run: agentbox opencode attach ${reattachRef3(box)}`
4659
4716
  );
4660
4717
  return;
@@ -4675,7 +4732,7 @@ var opencodeStartCommand = new Command6("start").description(
4675
4732
  await startOrAttachOpencode(box, effectiveOpencodeArgs, opts);
4676
4733
  } catch (err) {
4677
4734
  if (err instanceof OpencodeSessionError) {
4678
- log13.error(err.message);
4735
+ log12.error(err.message);
4679
4736
  process.exit(1);
4680
4737
  }
4681
4738
  handleLifecycleError(err);
@@ -4689,7 +4746,7 @@ var opencodeLoginCommand = new Command6("login").description(
4689
4746
  ).action(async (args) => {
4690
4747
  intro3("Signing in to OpenCode...");
4691
4748
  if (!process.stdin.isTTY) {
4692
- log13.error("`agentbox opencode login` needs an interactive terminal.");
4749
+ log12.error("`agentbox opencode login` needs an interactive terminal.");
4693
4750
  process.exit(1);
4694
4751
  }
4695
4752
  try {
@@ -4703,10 +4760,10 @@ var opencodeLoginCommand = new Command6("login").description(
4703
4760
  s.stop("image ready");
4704
4761
  const exitCode = await runOpencodeLoginContainer(image, args);
4705
4762
  if (exitCode !== 0) {
4706
- log13.warn(`\`opencode auth login\` exited with code ${String(exitCode)}`);
4763
+ log12.warn(`\`opencode auth login\` exited with code ${String(exitCode)}`);
4707
4764
  process.exit(exitCode);
4708
4765
  }
4709
- outro4("signed in \u2014 credentials saved for future boxes");
4766
+ outro3("signed in \u2014 credentials saved for future boxes");
4710
4767
  } catch (err) {
4711
4768
  handleLifecycleError(err);
4712
4769
  }
@@ -4982,7 +5039,7 @@ function handleError(err) {
4982
5039
  var configCommand = new Command7("config").description("Read / write layered config (global, per-project, workspace `defaults:` block)").addCommand(getCommand).addCommand(setCommand).addCommand(unsetCommand).addCommand(listCommand).addCommand(pathCommand).addCommand(editCommand).addCommand(listProjectsCommand);
4983
5040
 
4984
5041
  // src/commands/cp.ts
4985
- import { log as log14 } from "@clack/prompts";
5042
+ import { log as log13 } from "@clack/prompts";
4986
5043
  import { Command as Command8 } from "commander";
4987
5044
  function parseBoxArg(arg) {
4988
5045
  const idx = arg.indexOf(":");
@@ -5065,10 +5122,10 @@ var cpCommand = new Command8("cp").description("Copy files between host and box
5065
5122
  }
5066
5123
  const insp = await inspectBox(box.id);
5067
5124
  if (insp.state === "paused") {
5068
- log14.info("box is paused; unpausing");
5125
+ log13.info("box is paused; unpausing");
5069
5126
  await unpauseBox(box.id);
5070
5127
  } else if (insp.state === "stopped") {
5071
- log14.info("box is stopped; starting");
5128
+ log13.info("box is stopped; starting");
5072
5129
  await startBox(box.id);
5073
5130
  } else if (insp.state === "missing") {
5074
5131
  throw new Error(`box ${box.name} has no container; was it destroyed?`);
@@ -5076,7 +5133,7 @@ var cpCommand = new Command8("cp").description("Copy files between host and box
5076
5133
  if (parsed.direction === "upload") {
5077
5134
  const result = await uploadToBox(box, parsed.hostPath, parsed.boxPath);
5078
5135
  if (result.warn) {
5079
- log14.warn(`copied to ${box.name}:${result.finalPath}, but ${result.warn}`);
5136
+ log13.warn(`copied to ${box.name}:${result.finalPath}, but ${result.warn}`);
5080
5137
  } else {
5081
5138
  process.stdout.write(`copied to ${box.name}:${result.finalPath}
5082
5139
  `);
@@ -5092,7 +5149,7 @@ var cpCommand = new Command8("cp").description("Copy files between host and box
5092
5149
  });
5093
5150
 
5094
5151
  // src/commands/create.ts
5095
- import { intro as intro4, log as log15, outro as outro5 } from "@clack/prompts";
5152
+ import { intro as intro4, log as log14, outro as outro4 } from "@clack/prompts";
5096
5153
  import { Command as Command9 } from "commander";
5097
5154
  import { execSync, spawnSync as spawnSync2 } from "child_process";
5098
5155
  function buildCliOverrides(opts) {
@@ -5215,13 +5272,13 @@ var createCommand = new Command9("create").description("Create and start a new a
5215
5272
  onLog: (line) => cmdLog.write(line)
5216
5273
  });
5217
5274
  if (gate.decision === "cancel") {
5218
- log15.warn("carry: cancelled \u2014 not creating the box");
5275
+ log14.warn("carry: cancelled \u2014 not creating the box");
5219
5276
  cmdLog.close();
5220
5277
  process.exit(0);
5221
5278
  }
5222
5279
  if (gate.decision === "approve") carryEntries = gate.entries;
5223
5280
  } catch (err) {
5224
- log15.error(err instanceof Error ? err.message : String(err));
5281
+ log14.error(err instanceof Error ? err.message : String(err));
5225
5282
  cmdLog.close();
5226
5283
  process.exit(1);
5227
5284
  }
@@ -5269,7 +5326,7 @@ var createCommand = new Command9("create").description("Create and start a new a
5269
5326
  } catch (err) {
5270
5327
  if (err instanceof FromBranchError || err instanceof UseBranchError) {
5271
5328
  s.stop("aborting: invalid branch selection");
5272
- log15.error(err.message);
5329
+ log14.error(err.message);
5273
5330
  cmdLog.close();
5274
5331
  process.exit(2);
5275
5332
  }
@@ -5311,17 +5368,17 @@ var createCommand = new Command9("create").description("Create and start a new a
5311
5368
  }
5312
5369
  });
5313
5370
  s.stop(`box ${result.record.container} ready`);
5314
- log15.info(`id: ${result.record.id}`);
5371
+ log14.info(`id: ${result.record.id}`);
5315
5372
  if (typeof result.record.projectIndex === "number") {
5316
- log15.info(`n: ${String(result.record.projectIndex)} (in ${projectRoot})`);
5373
+ log14.info(`n: ${String(result.record.projectIndex)} (in ${projectRoot})`);
5317
5374
  }
5318
- log15.info(`container: ${result.record.container}`);
5319
- log15.info(`image: ${result.record.image}${result.imageBuilt ? " (built just now)" : ""}`);
5375
+ log14.info(`container: ${result.record.container}`);
5376
+ log14.info(`image: ${result.record.image}${result.imageBuilt ? " (built just now)" : ""}`);
5320
5377
  if (result.record.snapshotDir) {
5321
- log15.info(`snapshot: ${result.record.snapshotDir}`);
5378
+ log14.info(`snapshot: ${result.record.snapshotDir}`);
5322
5379
  }
5323
5380
  if (result.record.checkpointSource) {
5324
- log15.info(
5381
+ log14.info(
5325
5382
  `checkpoint: ${result.record.checkpointSource.ref} (${result.record.checkpointSource.type}) \u2192 ${result.record.checkpointImage ?? "(missing)"}`
5326
5383
  );
5327
5384
  }
@@ -5333,7 +5390,7 @@ var createCommand = new Command9("create").description("Create and start a new a
5333
5390
  ` agentbox claude attach ${result.record.name}`,
5334
5391
  ` agentbox url ${result.record.name}`
5335
5392
  ];
5336
- log15.message(
5393
+ log14.message(
5337
5394
  [
5338
5395
  "",
5339
5396
  "Try it:",
@@ -5352,7 +5409,7 @@ var createCommand = new Command9("create").description("Create and start a new a
5352
5409
  const protectedPaths = boxes.map((b) => b.projectRoot).filter((p) => typeof p === "string");
5353
5410
  const res = await pruneOrphanProjectConfigs({ protectedPaths });
5354
5411
  if (res.removed.length > 0) {
5355
- log15.info(
5412
+ log14.info(
5356
5413
  `cleaned ${String(res.removed.length)} orphan project config dir(s): ` + res.removed.map((r) => r.originalPath).join(", ")
5357
5414
  );
5358
5415
  }
@@ -5360,9 +5417,9 @@ var createCommand = new Command9("create").description("Create and start a new a
5360
5417
  } catch {
5361
5418
  }
5362
5419
  }
5363
- outro5("done");
5420
+ outro4("done");
5364
5421
  if (attachClaudeAfter) {
5365
- const { cloudAgentAttach: cloudAgentAttach2 } = await import("./_cloud-attach-2DGI6FUA.js");
5422
+ const { cloudAgentAttach: cloudAgentAttach2 } = await import("./_cloud-attach-45ECDTRL.js");
5366
5423
  await cloudAgentAttach2({
5367
5424
  box: result.record,
5368
5425
  binary: "claude",
@@ -5378,14 +5435,14 @@ var createCommand = new Command9("create").description("Create and start a new a
5378
5435
  s.stop("failed");
5379
5436
  const msg = err instanceof Error ? err.message : String(err);
5380
5437
  cmdLog.write(`FAIL: ${err instanceof Error ? err.stack ?? err.message : String(err)}`);
5381
- log15.error(msg);
5438
+ log14.error(msg);
5382
5439
  try {
5383
5440
  const running = execSync('docker ps --format "{{.Names}}"', {
5384
5441
  stdio: ["ignore", "pipe", "ignore"]
5385
5442
  }).toString().split("\n").filter((n) => n.startsWith("agentbox-"));
5386
5443
  if (running.length > 0) {
5387
- log15.warn(`leftover containers: ${running.join(", ")}`);
5388
- log15.warn(`remove with: docker rm -f ${running.join(" ")}`);
5444
+ log14.warn(`leftover containers: ${running.join(", ")}`);
5445
+ log14.warn(`remove with: docker rm -f ${running.join(" ")}`);
5389
5446
  }
5390
5447
  } catch {
5391
5448
  }
@@ -5398,7 +5455,7 @@ var createCommand = new Command9("create").description("Create and start a new a
5398
5455
 
5399
5456
  // src/commands/dashboard.ts
5400
5457
  import { spawn as spawn2 } from "child_process";
5401
- import { log as log16 } from "@clack/prompts";
5458
+ import { log as log15 } from "@clack/prompts";
5402
5459
  import { Command as Command10 } from "commander";
5403
5460
 
5404
5461
  // src/dashboard/layout.ts
@@ -6922,7 +6979,7 @@ function toSidebar(b) {
6922
6979
  var dashboardCommand = new Command10("dashboard").description("Box list + the selected box live Agent session").argument("[box]", "initial box (default: first running box; -p restricts to the cwd project)").option("-p, --project", "only this project's boxes (default: all boxes globally)").action(async (idOrName, opts) => {
6923
6980
  try {
6924
6981
  if (!process.stdout.isTTY || !process.stdin.isTTY) {
6925
- log16.error("agentbox dashboard needs an interactive terminal");
6982
+ log15.error("agentbox dashboard needs an interactive terminal");
6926
6983
  process.exit(2);
6927
6984
  }
6928
6985
  const backend = await loadPtyBackend();
@@ -6932,10 +6989,10 @@ var dashboardCommand = new Command10("dashboard").description("Box list + the se
6932
6989
  ptySpawn = backend.ptySpawn;
6933
6990
  termCtor = backend.termCtor;
6934
6991
  } else {
6935
- log16.error(
6992
+ log15.error(
6936
6993
  "agentbox dashboard is unavailable here (native terminal backend failed to load)"
6937
6994
  );
6938
- log16.info("use `agentbox claude` / `agentbox claude attach` instead");
6995
+ log15.info("use `agentbox claude` / `agentbox claude attach` instead");
6939
6996
  process.exit(2);
6940
6997
  }
6941
6998
  const project = await findProjectRoot(process.cwd());
@@ -7247,9 +7304,9 @@ var dashboardCommand = new Command10("dashboard").description("Box list + the se
7247
7304
  if (!br.up) return `VNC: in-box browser unavailable (${br.reason ?? "box not running?"})`;
7248
7305
  } catch {
7249
7306
  }
7250
- detach("open", [url]);
7307
+ detach(hostOpenCommand(), [url]);
7251
7308
  if (exposedWebUrl) {
7252
- detach("open", [exposedWebUrl]);
7309
+ detach(hostOpenCommand(), [exposedWebUrl]);
7253
7310
  return "Opening VNC + web in browser\u2026";
7254
7311
  }
7255
7312
  return "Opening VNC in browser\u2026";
@@ -7258,7 +7315,7 @@ var dashboardCommand = new Command10("dashboard").description("Box list + the se
7258
7315
  const box = (await listBoxes()).find((b) => b.id === boxId);
7259
7316
  if (!box) return "box not found";
7260
7317
  const { url } = webTarget(box);
7261
- detach("open", [url]);
7318
+ detach(hostOpenCommand(), [url]);
7262
7319
  return `Opening ${url.replace(/^https?:\/\//, "")}\u2026`;
7263
7320
  };
7264
7321
  const openCode = async (boxId) => {
@@ -7340,11 +7397,11 @@ var dashboardCommand = new Command10("dashboard").description("Box list + the se
7340
7397
  });
7341
7398
 
7342
7399
  // ../../packages/sandbox-daytona/dist/cli.js
7343
- import { log as log17, spinner as spinner6 } from "@clack/prompts";
7400
+ import { log as log16, spinner as spinner6 } from "@clack/prompts";
7344
7401
  import { Command as Command11 } from "commander";
7345
7402
  function reportError(err) {
7346
7403
  const message = err instanceof Error ? err.message : String(err);
7347
- log17.error(message);
7404
+ log16.error(message);
7348
7405
  process.exitCode = 1;
7349
7406
  }
7350
7407
  var loginSub = new Command11("login").description("Set up (or rotate) Daytona credentials for cloud boxes").option("--status", "show what is currently configured (masked) and exit").action(async (opts) => {
@@ -7403,7 +7460,7 @@ var resyncSub = new Command11("resync").description(
7403
7460
  const sb = spinner6();
7404
7461
  sb.start(`provisioning throwaway sandbox to refresh: ${agents.join(", ")}`);
7405
7462
  const ensured = await ensureAgentVolumesForCloud(daytonaBackend, {
7406
- onLog: (line) => log17.info(line)
7463
+ onLog: (line) => log16.info(line)
7407
7464
  });
7408
7465
  if (ensured.agents.length === 0) {
7409
7466
  sb.stop("no agent volumes available \u2014 the daytona backend has no volume primitive");
@@ -7443,7 +7500,7 @@ var resyncSub = new Command11("resync").description(
7443
7500
  }
7444
7501
  sb3.stop("throwaway sandbox destroyed");
7445
7502
  }
7446
- log17.success(
7503
+ log16.success(
7447
7504
  `Daytona agent volumes refreshed: ${agents.join(", ")}. Next \`agentbox create --provider daytona\` will use the updated credentials.`
7448
7505
  );
7449
7506
  } catch (err) {
@@ -7463,11 +7520,11 @@ var dockerCommand = new Command12("docker").description(
7463
7520
  });
7464
7521
 
7465
7522
  // ../../packages/sandbox-hetzner/dist/cli.js
7466
- import { log as log18 } from "@clack/prompts";
7523
+ import { log as log17 } from "@clack/prompts";
7467
7524
  import { Command as Command13 } from "commander";
7468
7525
  function reportError2(err) {
7469
7526
  const message = err instanceof Error ? err.message : String(err);
7470
- log18.error(message);
7527
+ log17.error(message);
7471
7528
  process.exitCode = 1;
7472
7529
  }
7473
7530
  var loginSub2 = new Command13("login").description("Set up (or rotate) Hetzner Cloud credentials for VPS boxes").option("--status", "show what is currently configured (masked) and exit").action(async (opts) => {
@@ -7611,11 +7668,11 @@ var hetznerCommand = new Command13("hetzner").description(
7611
7668
  ).addCommand(loginSub2, { isDefault: true }).addCommand(firewallSub);
7612
7669
 
7613
7670
  // ../../packages/sandbox-vercel/dist/cli.js
7614
- import { log as log19 } from "@clack/prompts";
7671
+ import { log as log18 } from "@clack/prompts";
7615
7672
  import { Command as Command14 } from "commander";
7616
7673
  function reportError3(err) {
7617
7674
  const message = err instanceof Error ? err.message : String(err);
7618
- log19.error(message);
7675
+ log18.error(message);
7619
7676
  process.exitCode = 1;
7620
7677
  }
7621
7678
  function relativeExpiry(expiresAt) {
@@ -7686,7 +7743,7 @@ var vercelCommand = new Command14("vercel").description(
7686
7743
  ).addCommand(loginSub3, { isDefault: true });
7687
7744
 
7688
7745
  // src/commands/destroy.ts
7689
- import { confirm as confirm7, isCancel as isCancel8, log as log20 } from "@clack/prompts";
7746
+ import { confirm as confirm7, isCancel as isCancel8, log as log19 } from "@clack/prompts";
7690
7747
  import { Command as Command15 } from "commander";
7691
7748
  var destroyCommand = new Command15("destroy").alias("rm").description("Destroy a box and discard its container writable layer (where /workspace lived)").argument(
7692
7749
  "[box]",
@@ -7695,7 +7752,7 @@ var destroyCommand = new Command15("destroy").alias("rm").description("Destroy a
7695
7752
  try {
7696
7753
  const box = await resolveBoxOrExit(idOrName);
7697
7754
  if (!opts.yes) {
7698
- log20.warn("Will also wipe the box volume and agent work-in-progress");
7755
+ log19.warn("Will also wipe the box volume and agent work-in-progress");
7699
7756
  const rootBranch = box.gitWorktrees?.find((w) => w.kind === "root")?.branch;
7700
7757
  const lines = [box.name];
7701
7758
  if (rootBranch) lines.push(`branch: ${rootBranch}`);
@@ -7703,13 +7760,13 @@ var destroyCommand = new Command15("destroy").alias("rm").description("Destroy a
7703
7760
  if (box.snapshotDir) {
7704
7761
  lines.push(`snapshot: ${box.snapshotDir}${opts.keepSnapshot ? " (will be kept)" : ""}`);
7705
7762
  }
7706
- log20.info(lines.join("\n"));
7763
+ log19.info(lines.join("\n"));
7707
7764
  const ok = await confirm7({
7708
7765
  message: "Destroy this box?",
7709
7766
  initialValue: false
7710
7767
  });
7711
7768
  if (isCancel8(ok) || !ok) {
7712
- log20.info("cancelled");
7769
+ log19.info("cancelled");
7713
7770
  return;
7714
7771
  }
7715
7772
  }
@@ -7742,11 +7799,11 @@ var destroyCommand = new Command15("destroy").alias("rm").description("Destroy a
7742
7799
  });
7743
7800
 
7744
7801
  // src/commands/download.ts
7745
- import { confirm as confirm13, isCancel as isCancel14, log as log26 } from "@clack/prompts";
7802
+ import { confirm as confirm13, isCancel as isCancel14, log as log25 } from "@clack/prompts";
7746
7803
  import { Command as Command21 } from "commander";
7747
7804
 
7748
7805
  // src/commands/download-claude.ts
7749
- import { confirm as confirm8, isCancel as isCancel9, log as log21 } from "@clack/prompts";
7806
+ import { confirm as confirm8, isCancel as isCancel9, log as log20 } from "@clack/prompts";
7750
7807
  import { Command as Command16 } from "commander";
7751
7808
  function tag(item) {
7752
7809
  const noun = item.category === "plugins" ? "plugin" : item.category.replace(/s$/, "");
@@ -7762,7 +7819,7 @@ var downloadClaudeCommand = new Command16("claude").description(
7762
7819
  const box = await resolveBoxOrExit(idOrName);
7763
7820
  const volume = box.claudeConfigVolume ?? resolveClaudeVolume({ isolate: false, boxId: box.id }).volume;
7764
7821
  if (volume === SHARED_CLAUDE_VOLUME) {
7765
- log21.warn(
7822
+ log20.warn(
7766
7823
  `Reading the shared ${SHARED_CLAUDE_VOLUME} volume \u2014 it aggregates Claude extensions installed in ANY box, not just ${box.name}.`
7767
7824
  );
7768
7825
  }
@@ -7792,7 +7849,7 @@ var downloadClaudeCommand = new Command16("claude").description(
7792
7849
  initialValue: false
7793
7850
  });
7794
7851
  if (isCancel9(ok) || !ok) {
7795
- log21.info("cancelled");
7852
+ log20.info("cancelled");
7796
7853
  return;
7797
7854
  }
7798
7855
  }
@@ -7807,7 +7864,7 @@ var downloadClaudeCommand = new Command16("claude").description(
7807
7864
  });
7808
7865
 
7809
7866
  // src/commands/download-codex.ts
7810
- import { confirm as confirm9, isCancel as isCancel10, log as log22 } from "@clack/prompts";
7867
+ import { confirm as confirm9, isCancel as isCancel10, log as log21 } from "@clack/prompts";
7811
7868
  import { Command as Command17 } from "commander";
7812
7869
  var downloadCodexCommand = new Command17("codex").description(
7813
7870
  "Download box-side Codex config/auth (config.toml, auth.json, prompts) back to host ~/.codex (additive)"
@@ -7819,7 +7876,7 @@ var downloadCodexCommand = new Command17("codex").description(
7819
7876
  const box = await resolveBoxOrExit(idOrName);
7820
7877
  const volume = box.codexConfigVolume ?? resolveCodexVolume({ isolate: false, boxId: box.id }).volume;
7821
7878
  if (volume === SHARED_CODEX_VOLUME) {
7822
- log22.warn(
7879
+ log21.warn(
7823
7880
  `Reading the shared ${SHARED_CODEX_VOLUME} volume \u2014 it aggregates Codex config from ANY box, not just ${box.name}.`
7824
7881
  );
7825
7882
  }
@@ -7845,7 +7902,7 @@ var downloadCodexCommand = new Command17("codex").description(
7845
7902
  initialValue: false
7846
7903
  });
7847
7904
  if (isCancel10(ok) || !ok) {
7848
- log22.info("cancelled");
7905
+ log21.info("cancelled");
7849
7906
  return;
7850
7907
  }
7851
7908
  }
@@ -7858,7 +7915,7 @@ var downloadCodexCommand = new Command17("codex").description(
7858
7915
  });
7859
7916
 
7860
7917
  // src/commands/download-opencode.ts
7861
- import { confirm as confirm10, isCancel as isCancel11, log as log23 } from "@clack/prompts";
7918
+ import { confirm as confirm10, isCancel as isCancel11, log as log22 } from "@clack/prompts";
7862
7919
  import { Command as Command18 } from "commander";
7863
7920
  var downloadOpencodeCommand = new Command18("opencode").description(
7864
7921
  "Download box-side OpenCode config/auth (auth.json, opencode.json, agents, commands, themes) back to host ~/.config + ~/.local/share opencode (additive)"
@@ -7870,7 +7927,7 @@ var downloadOpencodeCommand = new Command18("opencode").description(
7870
7927
  const box = await resolveBoxOrExit(idOrName);
7871
7928
  const volume = box.opencodeConfigVolume ?? resolveOpencodeVolume({ isolate: false, boxId: box.id }).volume;
7872
7929
  if (volume === SHARED_OPENCODE_VOLUME) {
7873
- log23.warn(
7930
+ log22.warn(
7874
7931
  `Reading the shared ${SHARED_OPENCODE_VOLUME} volume \u2014 it aggregates OpenCode config from ANY box, not just ${box.name}.`
7875
7932
  );
7876
7933
  }
@@ -7896,7 +7953,7 @@ var downloadOpencodeCommand = new Command18("opencode").description(
7896
7953
  initialValue: false
7897
7954
  });
7898
7955
  if (isCancel11(ok) || !ok) {
7899
- log23.info("cancelled");
7956
+ log22.info("cancelled");
7900
7957
  return;
7901
7958
  }
7902
7959
  }
@@ -7909,7 +7966,7 @@ var downloadOpencodeCommand = new Command18("opencode").description(
7909
7966
  });
7910
7967
 
7911
7968
  // src/commands/download-config.ts
7912
- import { confirm as confirm11, isCancel as isCancel12, log as log24 } from "@clack/prompts";
7969
+ import { confirm as confirm11, isCancel as isCancel12, log as log23 } from "@clack/prompts";
7913
7970
  import { Command as Command19 } from "commander";
7914
7971
  function tagChange(line) {
7915
7972
  const sp = line.indexOf(" ");
@@ -7927,15 +7984,15 @@ var downloadConfigCommand = new Command19("config").description("Download agentb
7927
7984
  const box = await resolveBoxOrExit(idOrName);
7928
7985
  const insp = await inspectBox(box.id);
7929
7986
  if (insp.state === "paused") {
7930
- log24.info("box is paused; unpausing");
7987
+ log23.info("box is paused; unpausing");
7931
7988
  await unpauseBox(box.id);
7932
7989
  } else if (insp.state === "stopped") {
7933
- log24.info("box is stopped; starting");
7990
+ log23.info("box is stopped; starting");
7934
7991
  await startBox(box.id);
7935
7992
  } else if (insp.state === "missing") {
7936
7993
  throw new Error(`box ${box.name} has no container; was it destroyed?`);
7937
7994
  }
7938
- log24.info(`agentbox.yaml bypasses gitignore and copies directly into ${box.workspacePath}`);
7995
+ log23.info(`agentbox.yaml bypasses gitignore and copies directly into ${box.workspacePath}`);
7939
7996
  const preview = await pullToHost(box, {
7940
7997
  dryRun: true,
7941
7998
  respectGitignore: false,
@@ -7963,7 +8020,7 @@ var downloadConfigCommand = new Command19("config").description("Download agentb
7963
8020
  initialValue: false
7964
8021
  });
7965
8022
  if (isCancel12(ok) || !ok) {
7966
- log24.info("cancelled");
8023
+ log23.info("cancelled");
7967
8024
  return;
7968
8025
  }
7969
8026
  }
@@ -7985,7 +8042,7 @@ var downloadConfigCommand = new Command19("config").description("Download agentb
7985
8042
  });
7986
8043
 
7987
8044
  // src/commands/download-env.ts
7988
- import { confirm as confirm12, isCancel as isCancel13, log as log25 } from "@clack/prompts";
8045
+ import { confirm as confirm12, isCancel as isCancel13, log as log24 } from "@clack/prompts";
7989
8046
  import { Command as Command20 } from "commander";
7990
8047
  function tagChange2(line) {
7991
8048
  const sp = line.indexOf(" ");
@@ -8009,15 +8066,15 @@ var downloadEnvCommand = new Command20("env").description(
8009
8066
  const box = await resolveBoxOrExit(idOrName);
8010
8067
  const insp = await inspectBox(box.id);
8011
8068
  if (insp.state === "paused") {
8012
- log25.info("box is paused; unpausing");
8069
+ log24.info("box is paused; unpausing");
8013
8070
  await unpauseBox(box.id);
8014
8071
  } else if (insp.state === "stopped") {
8015
- log25.info("box is stopped; starting");
8072
+ log24.info("box is stopped; starting");
8016
8073
  await startBox(box.id);
8017
8074
  } else if (insp.state === "missing") {
8018
8075
  throw new Error(`box ${box.name} has no container; was it destroyed?`);
8019
8076
  }
8020
- log25.info(
8077
+ log24.info(
8021
8078
  `env/config files bypass gitignore and copy directly into ${box.workspacePath}`
8022
8079
  );
8023
8080
  const patterns = [...DEFAULT_ENV_PATTERNS, ...opts.pattern];
@@ -8048,7 +8105,7 @@ var downloadEnvCommand = new Command20("env").description(
8048
8105
  initialValue: false
8049
8106
  });
8050
8107
  if (isCancel13(ok) || !ok) {
8051
- log25.info("cancelled");
8108
+ log24.info("cancelled");
8052
8109
  return;
8053
8110
  }
8054
8111
  }
@@ -8096,7 +8153,7 @@ var downloadCommand = new Command21("download").enablePositionalOptions().descri
8096
8153
  throw new Error("cloud download does not yet support --dry-run; omit to bulk-pull /workspace.");
8097
8154
  }
8098
8155
  if (!opts.respectGitignore || opts.includeNodeModules || opts.withEnv || opts.pattern.length > 0) {
8099
- log26.warn(
8156
+ log25.warn(
8100
8157
  "cloud download ignores gitignore/--with-env/--pattern filters in v1 \u2014 pulling the whole /workspace tree (Phase 6 polish)."
8101
8158
  );
8102
8159
  }
@@ -8106,7 +8163,7 @@ var downloadCommand = new Command21("download").enablePositionalOptions().descri
8106
8163
  initialValue: false
8107
8164
  });
8108
8165
  if (isCancel14(ok) || !ok) {
8109
- log26.info("cancelled");
8166
+ log25.info("cancelled");
8110
8167
  return;
8111
8168
  }
8112
8169
  }
@@ -8125,17 +8182,17 @@ var downloadCommand = new Command21("download").enablePositionalOptions().descri
8125
8182
  }
8126
8183
  const insp = await inspectBox(box.id);
8127
8184
  if (insp.state === "paused") {
8128
- log26.info("box is paused; unpausing");
8185
+ log25.info("box is paused; unpausing");
8129
8186
  await unpauseBox(box.id);
8130
8187
  } else if (insp.state === "stopped") {
8131
- log26.info("box is stopped; starting");
8188
+ log25.info("box is stopped; starting");
8132
8189
  await startBox(box.id);
8133
8190
  } else if (insp.state === "missing") {
8134
8191
  throw new Error(`box ${box.name} has no container; was it destroyed?`);
8135
8192
  }
8136
8193
  const rootWorktree = box.gitWorktrees?.find((w) => w.kind === "root");
8137
8194
  if (rootWorktree) {
8138
- log26.warn(
8195
+ log25.warn(
8139
8196
  `This box has been committing to branch \`${rootWorktree.branch}\` in a separate worktree.
8140
8197
  For a git-aware merge instead of a file copy, run from your checkout:
8141
8198
  git merge ${rootWorktree.branch}
@@ -8171,7 +8228,7 @@ Continuing with rsync into ${box.workspacePath}`
8171
8228
  initialValue: false
8172
8229
  });
8173
8230
  if (isCancel14(ok) || !ok) {
8174
- log26.info("cancelled");
8231
+ log25.info("cancelled");
8175
8232
  return;
8176
8233
  }
8177
8234
  }
@@ -8199,7 +8256,7 @@ downloadCommand.addCommand(downloadOpencodeCommand);
8199
8256
  downloadCommand.addCommand(downloadConfigCommand);
8200
8257
 
8201
8258
  // src/commands/drive.ts
8202
- import { log as log27 } from "@clack/prompts";
8259
+ import { log as log26 } from "@clack/prompts";
8203
8260
  import { Command as Command22 } from "commander";
8204
8261
 
8205
8262
  // src/lib/drive/keys.ts
@@ -8485,7 +8542,7 @@ var driveWaitCommand = new Command22("wait").description("Block until --text app
8485
8542
  }) + "\n"
8486
8543
  );
8487
8544
  } else {
8488
- log27.error(`text not found within ${String(timeoutMs)}ms: ${opts.text}`);
8545
+ log26.error(`text not found within ${String(timeoutMs)}ms: ${opts.text}`);
8489
8546
  }
8490
8547
  process.exit(1);
8491
8548
  } catch (err) {
@@ -8512,8 +8569,8 @@ driveCommand.addCommand(driveWaitCommand);
8512
8569
  driveCommand.addCommand(driveResizeCommand);
8513
8570
  function handleDriveError(err) {
8514
8571
  if (err instanceof SessionNotFoundError) {
8515
- log27.error(err.message);
8516
- log27.info("start an agent first (e.g. `agentbox claude <box>`) or pass --session.");
8572
+ log26.error(err.message);
8573
+ log26.info("start an agent first (e.g. `agentbox claude <box>`) or pass --session.");
8517
8574
  process.exit(2);
8518
8575
  }
8519
8576
  handleLifecycleError(err);
@@ -8537,10 +8594,10 @@ function sleep2(ms) {
8537
8594
  }
8538
8595
 
8539
8596
  // src/commands/fork.ts
8540
- import { log as log28 } from "@clack/prompts";
8597
+ import { log as log27 } from "@clack/prompts";
8541
8598
  import { Command as Command23 } from "commander";
8542
8599
  import { existsSync as existsSync4, readdirSync, statSync } from "fs";
8543
- import { homedir as homedir10 } from "os";
8600
+ import { homedir as homedir11 } from "os";
8544
8601
  import { join as join12 } from "path";
8545
8602
  var FORK_AGENTS = ["claude", "codex", "opencode"];
8546
8603
  var AGENT_COMMAND = {
@@ -8561,7 +8618,7 @@ function resolveSessionArgs(agent, opts) {
8561
8618
  }
8562
8619
  if (opts.session) return ["--resume", opts.session];
8563
8620
  if (agent === "codex") return ["--continue"];
8564
- const dir = join12(homedir10(), ".claude", "projects", encodeClaudeProjectsDir(opts.workspace));
8621
+ const dir = join12(homedir11(), ".claude", "projects", encodeClaudeProjectsDir(opts.workspace));
8565
8622
  if (!existsSync4(dir)) return ["--continue"];
8566
8623
  const now = Date.now();
8567
8624
  const recent = readdirSync(dir).filter((f) => f.endsWith(".jsonl")).map((f) => {
@@ -8606,19 +8663,19 @@ var forkCommand = new Command23("fork").description(
8606
8663
  "auto-approve agentbox.yaml's carry: block (fork skips carry by default \u2014 it does not silently re-copy host files into the new box)"
8607
8664
  ).action(async (opts) => {
8608
8665
  if ((process.env.AGENTBOX_RELAY_URL ?? "").trim().length > 0) {
8609
- log28.error(
8666
+ log27.error(
8610
8667
  "agentbox fork runs on the host only: it teleports a host agent session into a new box. You appear to be inside a box (AGENTBOX_RELAY_URL is set) \u2014 box\u2192box fork is not supported yet."
8611
8668
  );
8612
8669
  process.exit(2);
8613
8670
  }
8614
8671
  const agent = opts.agent?.trim() || "claude";
8615
8672
  if (!FORK_AGENTS.includes(agent)) {
8616
- log28.error(`--agent: expected one of ${FORK_AGENTS.join(", ")}, got "${opts.agent ?? ""}"`);
8673
+ log27.error(`--agent: expected one of ${FORK_AGENTS.join(", ")}, got "${opts.agent ?? ""}"`);
8617
8674
  process.exit(2);
8618
8675
  }
8619
8676
  const attachIn = opts.attachIn ?? "tab";
8620
8677
  if (!FORK_ATTACH_VALUES.includes(attachIn)) {
8621
- log28.error(`--attach-in: expected one of ${FORK_ATTACH_VALUES.join(", ")}, got "${attachIn}"`);
8678
+ log27.error(`--attach-in: expected one of ${FORK_ATTACH_VALUES.join(", ")}, got "${attachIn}"`);
8622
8679
  process.exit(2);
8623
8680
  }
8624
8681
  const provider = opts.provider?.trim();
@@ -8626,7 +8683,7 @@ var forkCommand = new Command23("fork").description(
8626
8683
  try {
8627
8684
  sessionArgs = resolveSessionArgs(agent, opts);
8628
8685
  } catch (err) {
8629
- log28.error(err instanceof Error ? err.message : String(err));
8686
+ log27.error(err instanceof Error ? err.message : String(err));
8630
8687
  process.exit(2);
8631
8688
  }
8632
8689
  const subArgv = [
@@ -8644,16 +8701,16 @@ var forkCommand = new Command23("fork").description(
8644
8701
  });
8645
8702
 
8646
8703
  // src/commands/install.ts
8647
- import { confirm as confirm14, intro as intro6, isCancel as isCancel15, log as log30, note, outro as outro6, select as select2, spinner as spinner8 } from "@clack/prompts";
8704
+ import { confirm as confirm14, intro as intro6, isCancel as isCancel15, log as log29, note as note2, outro as outro5, select as select2, spinner as spinner8 } from "@clack/prompts";
8648
8705
  import { Command as Command25 } from "commander";
8649
8706
  import { existsSync as existsSync6, mkdirSync as mkdirSync5, readFileSync, writeFileSync as writeFileSync4 } from "fs";
8650
- import { homedir as homedir13 } from "os";
8707
+ import { homedir as homedir14 } from "os";
8651
8708
  import { dirname as dirname2, join as join15, resolve as resolve2 } from "path";
8652
8709
  import { fileURLToPath } from "url";
8653
8710
 
8654
8711
  // src/lib/doctor-checks.ts
8655
8712
  import { accessSync, constants as fsConstants, mkdirSync as mkdirSync3 } from "fs";
8656
- import { homedir as homedir11 } from "os";
8713
+ import { homedir as homedir12 } from "os";
8657
8714
  import { join as join13 } from "path";
8658
8715
  import { execa as execa2 } from "execa";
8659
8716
  var ALL_PROVIDERS = ["docker", "daytona", "hetzner", "vercel"];
@@ -8693,10 +8750,16 @@ function checkNode() {
8693
8750
  };
8694
8751
  }
8695
8752
  function checkPlatform() {
8696
- return { label: "platform", status: "ok", detail: `${process.platform}/${process.arch}` };
8753
+ const supported = process.platform === "darwin" || process.platform === "linux";
8754
+ return {
8755
+ label: "platform",
8756
+ status: supported ? "ok" : "warn",
8757
+ detail: `${process.platform}/${process.arch}`,
8758
+ hint: supported ? void 0 : "agentbox supports macOS and Linux hosts; this OS is untested"
8759
+ };
8697
8760
  }
8698
8761
  function checkAgentboxHome() {
8699
- const dir = join13(homedir11(), ".agentbox");
8762
+ const dir = join13(homedir12(), ".agentbox");
8700
8763
  try {
8701
8764
  mkdirSync3(dir, { recursive: true });
8702
8765
  accessSync(dir, fsConstants.W_OK);
@@ -8733,6 +8796,7 @@ async function runSystemChecks() {
8733
8796
  return [checkNode(), checkPlatform(), checkAgentboxHome(), git, ssh];
8734
8797
  }
8735
8798
  async function dockerChecks() {
8799
+ const linux = process.platform === "linux";
8736
8800
  const cli = await probeVersion("docker");
8737
8801
  if (!cli) {
8738
8802
  return [
@@ -8740,25 +8804,34 @@ async function dockerChecks() {
8740
8804
  label: "docker cli",
8741
8805
  status: "warn",
8742
8806
  detail: "not found",
8743
- hint: "install Docker Desktop, OrbStack, or docker engine"
8807
+ hint: linux ? "install docker engine: https://docs.docker.com/engine/install/" : "install Docker Desktop, OrbStack, or docker engine"
8744
8808
  }
8745
8809
  ];
8746
8810
  }
8747
8811
  const cliRes = { label: "docker cli", status: "ok", detail: cli };
8748
8812
  const info = await execa2("docker", ["info"], { reject: false });
8749
8813
  if (info.exitCode !== 0) {
8814
+ const permDenied = `${info.stderr ?? ""}`.toLowerCase().includes("permission denied");
8815
+ let hint;
8816
+ if (permDenied && linux) {
8817
+ hint = "add your user to the docker group: `sudo usermod -aG docker $USER`, then log out/in (or run `newgrp docker`)";
8818
+ } else if (linux) {
8819
+ hint = "start Docker: `sudo systemctl start docker` (install docker engine if missing)";
8820
+ } else {
8821
+ hint = "start Docker (Desktop / OrbStack)";
8822
+ }
8750
8823
  return [
8751
8824
  cliRes,
8752
8825
  {
8753
8826
  label: "docker daemon",
8754
8827
  status: "warn",
8755
- detail: "unreachable",
8756
- hint: "start Docker (Desktop / OrbStack / `systemctl start docker`)"
8828
+ detail: permDenied ? "permission denied" : "unreachable",
8829
+ hint
8757
8830
  }
8758
8831
  ];
8759
8832
  }
8760
8833
  const daemonRes = { label: "docker daemon", status: "ok", detail: "reachable" };
8761
- const mod = await import("./dist-SBCQVFCE.js");
8834
+ const mod = await import("./dist-ASLPRUQR.js");
8762
8835
  let imgRes;
8763
8836
  try {
8764
8837
  const img = await mod.imageInfo(mod.DEFAULT_BOX_IMAGE);
@@ -8789,7 +8862,7 @@ async function dockerChecks() {
8789
8862
  }
8790
8863
  async function daytonaChecks() {
8791
8864
  try {
8792
- const mod = await import("./dist-BD5QJRDC.js");
8865
+ const mod = await import("./dist-PTJ6CEQY.js");
8793
8866
  const status = await mod.getDaytonaStatus();
8794
8867
  if (!status.configured) {
8795
8868
  return [
@@ -8825,7 +8898,7 @@ async function daytonaChecks() {
8825
8898
  }
8826
8899
  async function hetznerChecks() {
8827
8900
  try {
8828
- const mod = await import("./dist-BNI5PQYK.js");
8901
+ const mod = await import("./dist-WMQDMTWS.js");
8829
8902
  const cred = mod.readHetznerCredStatus();
8830
8903
  const credRes = cred.source === "none" ? {
8831
8904
  label: "credentials",
@@ -8857,7 +8930,7 @@ async function hetznerChecks() {
8857
8930
  }
8858
8931
  async function vercelChecks() {
8859
8932
  try {
8860
- const mod = await import("./dist-SJHY3HYN.js");
8933
+ const mod = await import("./dist-RAZP76VX.js");
8861
8934
  const cred = mod.readVercelCredStatus();
8862
8935
  const credRes = cred.auth === "none" ? {
8863
8936
  label: "credentials",
@@ -8984,11 +9057,11 @@ function formatDetailed(groups) {
8984
9057
 
8985
9058
  // src/lib/first-run.ts
8986
9059
  import { existsSync as existsSync5, mkdirSync as mkdirSync4, writeFileSync as writeFileSync3 } from "fs";
8987
- import { homedir as homedir12 } from "os";
9060
+ import { homedir as homedir13 } from "os";
8988
9061
  import { dirname, join as join14 } from "path";
8989
9062
  var MARKER_VERSION = 1;
8990
9063
  function setupMarkerPath() {
8991
- return join14(homedir12(), ".agentbox", "setup-complete.json");
9064
+ return join14(homedir13(), ".agentbox", "setup-complete.json");
8992
9065
  }
8993
9066
  function isFirstRun() {
8994
9067
  return !existsSync5(setupMarkerPath());
@@ -9005,7 +9078,7 @@ function markSetupComplete(provider) {
9005
9078
  }
9006
9079
 
9007
9080
  // src/commands/prepare.ts
9008
- import { intro as intro5, log as log29, spinner as spinner7 } from "@clack/prompts";
9081
+ import { intro as intro5, log as log28, spinner as spinner7 } from "@clack/prompts";
9009
9082
  import { Command as Command24 } from "commander";
9010
9083
  async function dockerStatus() {
9011
9084
  let img;
@@ -9068,7 +9141,7 @@ async function renderDocker(status) {
9068
9141
  }
9069
9142
  async function daytonaStatus() {
9070
9143
  try {
9071
- const mod = await import("./dist-BD5QJRDC.js");
9144
+ const mod = await import("./dist-PTJ6CEQY.js");
9072
9145
  return await mod.getDaytonaStatus();
9073
9146
  } catch (err) {
9074
9147
  return {
@@ -9142,7 +9215,7 @@ async function runPrepare(providerName, opts = {}) {
9142
9215
  }
9143
9216
  const provider = await getProvider(providerName);
9144
9217
  if (typeof provider.prepare !== "function") {
9145
- log29.error(`provider '${providerName}' does not implement prepare`);
9218
+ log28.error(`provider '${providerName}' does not implement prepare`);
9146
9219
  process.exit(1);
9147
9220
  }
9148
9221
  const cwd = opts.cwd ?? process.cwd();
@@ -9162,10 +9235,10 @@ async function runPrepare(providerName, opts = {}) {
9162
9235
  sp.stop(`prepared ${providerName}: snapshot '${result.snapshotName}'`);
9163
9236
  try {
9164
9237
  const written = await setConfigValue("project", "box.image", result.snapshotName, cwd);
9165
- log29.success(`box.image = ${result.snapshotName} (written to ${written.path})`);
9238
+ log28.success(`box.image = ${result.snapshotName} (written to ${written.path})`);
9166
9239
  } catch (err) {
9167
9240
  const msg = err instanceof Error ? err.message : String(err);
9168
- log29.warn(
9241
+ log28.warn(
9169
9242
  `prepared snapshot '${result.snapshotName}', but failed to pin it into the project config: ${msg}
9170
9243
  Run \`agentbox config set --project box.image ${result.snapshotName}\` manually.`
9171
9244
  );
@@ -9178,7 +9251,7 @@ Run \`agentbox config set --project box.image ${result.snapshotName}\` manually.
9178
9251
  await showStatus({ onlyProvider: providerName });
9179
9252
  }
9180
9253
  if (!opts.suppressTip) {
9181
- log29.info(
9254
+ log28.info(
9182
9255
  "tip: install the agentbox host skill so Claude Code on this machine can drive AgentBox for you:\n npx skills add https://github.com/madarco/agentbox --skill agentbox"
9183
9256
  );
9184
9257
  }
@@ -9310,7 +9383,7 @@ ${LOGO_L2}\x1B[0m` + SYNC_END2);
9310
9383
  }
9311
9384
  var LEGACY_INFO_MARKER = "Drive AgentBox from the host:";
9312
9385
  function installTargets() {
9313
- const home = homedir13();
9386
+ const home = homedir14();
9314
9387
  const claudeSkills = join15(home, ".claude", "skills");
9315
9388
  return [
9316
9389
  { src: join15("agentbox", "SKILL.md"), dest: join15(claudeSkills, "agentbox", "SKILL.md") },
@@ -9361,20 +9434,20 @@ function installHostSkills(opts = {}) {
9361
9434
  for (const t of installTargets()) {
9362
9435
  const src = join15(srcDir, t.src);
9363
9436
  if (!existsSync6(src)) {
9364
- if (!quiet) log30.warn(`bundled file missing (skipped): ${src}`);
9437
+ if (!quiet) log29.warn(`bundled file missing (skipped): ${src}`);
9365
9438
  skipped++;
9366
9439
  continue;
9367
9440
  }
9368
9441
  if (t.gateDir && !existsSync6(t.gateDir)) continue;
9369
9442
  const reason = writableReason(t.dest, force);
9370
9443
  if (reason === "skip") {
9371
- if (!quiet) log30.warn(`user-modified file at ${t.dest}, skipping; pass --force to overwrite`);
9444
+ if (!quiet) log29.warn(`user-modified file at ${t.dest}, skipping; pass --force to overwrite`);
9372
9445
  blocked.push(t.dest);
9373
9446
  skipped++;
9374
9447
  continue;
9375
9448
  }
9376
9449
  if (dryRun) {
9377
- if (!quiet) log30.info(`would write ${t.dest} (${reason})`);
9450
+ if (!quiet) log29.info(`would write ${t.dest} (${reason})`);
9378
9451
  written.push(t.dest);
9379
9452
  continue;
9380
9453
  }
@@ -9406,10 +9479,10 @@ function ensureTty() {
9406
9479
  async function runProviderLogin(name) {
9407
9480
  if (name === "docker") return true;
9408
9481
  if (name === "daytona") {
9409
- const mod2 = await import("./dist-BD5QJRDC.js");
9482
+ const mod2 = await import("./dist-PTJ6CEQY.js");
9410
9483
  const status2 = await mod2.getDaytonaStatus();
9411
9484
  if (status2.configured) {
9412
- log30.info("daytona: already configured");
9485
+ log29.info("daytona: already configured");
9413
9486
  const rotate = await confirm14({ message: "Re-authenticate Daytona?", initialValue: false });
9414
9487
  if (isCancel15(rotate)) return false;
9415
9488
  if (rotate) await mod2.ensureDaytonaCredentials({ force: true });
@@ -9419,10 +9492,10 @@ async function runProviderLogin(name) {
9419
9492
  return true;
9420
9493
  }
9421
9494
  if (name === "hetzner") {
9422
- const mod2 = await import("./dist-BNI5PQYK.js");
9495
+ const mod2 = await import("./dist-WMQDMTWS.js");
9423
9496
  const status2 = mod2.readHetznerCredStatus();
9424
9497
  if (status2.source !== "none") {
9425
- log30.info("hetzner: already configured");
9498
+ log29.info("hetzner: already configured");
9426
9499
  const rotate = await confirm14({ message: "Re-authenticate Hetzner?", initialValue: false });
9427
9500
  if (isCancel15(rotate)) return false;
9428
9501
  if (rotate) await mod2.ensureHetznerCredentials({ force: true });
@@ -9431,10 +9504,10 @@ async function runProviderLogin(name) {
9431
9504
  await mod2.ensureHetznerCredentials();
9432
9505
  return true;
9433
9506
  }
9434
- const mod = await import("./dist-SJHY3HYN.js");
9507
+ const mod = await import("./dist-RAZP76VX.js");
9435
9508
  const status = mod.readVercelCredStatus();
9436
9509
  if (status.auth !== "none") {
9437
- log30.info(`vercel: already configured (${status.auth})`);
9510
+ log29.info(`vercel: already configured (${status.auth})`);
9438
9511
  const rotate = await confirm14({ message: "Re-authenticate Vercel?", initialValue: false });
9439
9512
  if (isCancel15(rotate)) return false;
9440
9513
  if (rotate) await mod.ensureVercelCredentials({ force: true });
@@ -9444,7 +9517,7 @@ async function runProviderLogin(name) {
9444
9517
  return true;
9445
9518
  }
9446
9519
  function tutorialBody(provider) {
9447
- const startCmd = provider === "docker" ? "agentbox claude" : `agentbox ${provider} claude`;
9520
+ const startCmd = provider === "docker" ? "agentbox claude " : `agentbox ${provider} claude`;
9448
9521
  return `Get started:
9449
9522
  ${startCmd} # for claude, codex, opencode
9450
9523
  -> Setup wizard? -> Yes # install dependencies and setup agentbox.yaml
@@ -9465,11 +9538,11 @@ async function runInstallWizard(opts = {}) {
9465
9538
  process.stdout.write(" " + formatCompact([sysGroup]) + "\n");
9466
9539
  const hardFail = sysResults.find((r) => r.status === "fail");
9467
9540
  if (hardFail) {
9468
- log30.error(`system check failed: ${hardFail.label} \u2014 ${hardFail.detail}`);
9469
- log30.info("run `agentbox doctor` for full detail");
9541
+ log29.error(`system check failed: ${hardFail.label} \u2014 ${hardFail.detail}`);
9542
+ log29.info("run `agentbox doctor` for full detail");
9470
9543
  const cont = await confirm14({ message: "Continue anyway?", initialValue: false });
9471
9544
  if (isCancel15(cont) || !cont) {
9472
- outro6("aborted");
9545
+ outro5("aborted");
9473
9546
  return false;
9474
9547
  }
9475
9548
  }
@@ -9477,7 +9550,7 @@ async function runInstallWizard(opts = {}) {
9477
9550
  if (opts.provider) {
9478
9551
  const candidate = opts.provider.trim();
9479
9552
  if (!isProviderName(candidate)) {
9480
- log30.error(`unknown --provider: ${candidate}`);
9553
+ log29.error(`unknown --provider: ${candidate}`);
9481
9554
  return false;
9482
9555
  }
9483
9556
  providerName = candidate;
@@ -9492,7 +9565,7 @@ async function runInstallWizard(opts = {}) {
9492
9565
  }))
9493
9566
  });
9494
9567
  if (isCancel15(picked)) {
9495
- outro6("cancelled");
9568
+ outro5("cancelled");
9496
9569
  return false;
9497
9570
  }
9498
9571
  providerName = picked;
@@ -9500,14 +9573,14 @@ async function runInstallWizard(opts = {}) {
9500
9573
  if (providerName !== "docker") {
9501
9574
  const loggedIn = await runProviderLogin(providerName);
9502
9575
  if (!loggedIn) {
9503
- outro6("cancelled");
9576
+ outro5("cancelled");
9504
9577
  return false;
9505
9578
  }
9506
9579
  }
9507
9580
  const prepareMsg = providerName === "docker" ? "Build the box image now? (~1GB, a few minutes)" : `Bake the ${providerName} base snapshot now? (a few minutes, uses cloud time)`;
9508
9581
  const wantPrepare = opts.yes ? true : await confirm14({ message: prepareMsg, initialValue: true });
9509
9582
  if (isCancel15(wantPrepare)) {
9510
- outro6("cancelled");
9583
+ outro5("cancelled");
9511
9584
  return false;
9512
9585
  }
9513
9586
  if (wantPrepare) {
@@ -9519,12 +9592,12 @@ async function runInstallWizard(opts = {}) {
9519
9592
  suppressTip: true
9520
9593
  });
9521
9594
  } catch (err) {
9522
- log30.warn(
9595
+ log29.warn(
9523
9596
  `prepare failed: ${err instanceof Error ? err.message : String(err)} \u2014 you can rerun \`agentbox prepare --provider ${providerName}\` later`
9524
9597
  );
9525
9598
  }
9526
9599
  } else {
9527
- log30.info(
9600
+ log29.info(
9528
9601
  `skipped \u2014 the ${providerName} base will build lazily on first \`agentbox ${providerName === "docker" ? "" : providerName + " "}create\``
9529
9602
  );
9530
9603
  }
@@ -9539,20 +9612,20 @@ async function runInstallWizard(opts = {}) {
9539
9612
  sp.stop(`Agentbox Skills: nothing to write (${String(skillRes.skipped)} skipped)`);
9540
9613
  }
9541
9614
  if (skillRes.blocked.length > 0) {
9542
- log30.warn(
9615
+ log29.warn(
9543
9616
  `user-modified host skill file(s) left in place: ${skillRes.blocked.join(", ")}
9544
9617
  pass \`agentbox install --skills-only --force\` to overwrite`
9545
9618
  );
9546
9619
  }
9547
9620
  } catch (err) {
9548
9621
  sp.stop("Agentbox Skills: failed");
9549
- log30.warn(err instanceof Error ? err.message : String(err));
9622
+ log29.warn(err instanceof Error ? err.message : String(err));
9550
9623
  }
9551
9624
  markSetupComplete(providerName);
9552
9625
  const providerGroup = await runProviderChecks(providerName);
9553
9626
  process.stdout.write(" " + formatCompact([sysGroup, providerGroup]) + "\n");
9554
- note(tutorialBody(providerName), "Next steps");
9555
- outro6(
9627
+ note2(tutorialBody(providerName), "Next steps");
9628
+ outro5(
9556
9629
  opts.fromAutoTrigger ? "\u2728 Setup complete \u2014 continuing with your command\u2026" : "\u2728 Setup complete"
9557
9630
  );
9558
9631
  return true;
@@ -9572,20 +9645,20 @@ var installCommand = new Command25("install").description(
9572
9645
  try {
9573
9646
  res = installHostSkills({ force: opts.force, dryRun: opts.dryRun });
9574
9647
  } catch (err) {
9575
- log30.error(err instanceof Error ? err.message : String(err));
9648
+ log29.error(err instanceof Error ? err.message : String(err));
9576
9649
  process.exit(1);
9577
9650
  }
9578
9651
  if (opts.dryRun) {
9579
- outro6(
9652
+ outro5(
9580
9653
  `dry-run: ${String(res.written.length)} file(s) would be written, ${String(res.skipped)} skipped`
9581
9654
  );
9582
9655
  return;
9583
9656
  }
9584
9657
  if (res.written.length === 0) {
9585
- outro6(`nothing installed (${String(res.skipped)} skipped)`);
9658
+ outro5(`nothing installed (${String(res.skipped)} skipped)`);
9586
9659
  return;
9587
9660
  }
9588
- outro6(`installed: ${res.written.join(", ")}`);
9661
+ outro5(`installed: ${res.written.join(", ")}`);
9589
9662
  return;
9590
9663
  }
9591
9664
  const ok = await runInstallWizard({
@@ -9777,7 +9850,7 @@ for (const op of GH_PR_OPS) {
9777
9850
  var gitCommand = new Command27("git").description("Run git / gh pr operations against a box from the host").addCommand(pushCommand).addCommand(fetchCommand).addCommand(pullCommand).addCommand(checkoutCommand).addCommand(statusCommand).addCommand(prCommand);
9778
9851
 
9779
9852
  // src/commands/list.ts
9780
- import { log as log31 } from "@clack/prompts";
9853
+ import { log as log30 } from "@clack/prompts";
9781
9854
  import { Command as Command28 } from "commander";
9782
9855
  import { pathToFileURL } from "url";
9783
9856
 
@@ -9992,7 +10065,7 @@ var listCommand2 = withWatchOptions(
9992
10065
  )
9993
10066
  ).action(async (opts) => {
9994
10067
  if (opts.json && opts.watch) {
9995
- log31.error("cannot combine --json with --watch");
10068
+ log30.error("cannot combine --json with --watch");
9996
10069
  process.exit(2);
9997
10070
  }
9998
10071
  const all = opts.global ?? false;
@@ -10010,7 +10083,7 @@ var listCommand2 = withWatchOptions(
10010
10083
  });
10011
10084
 
10012
10085
  // src/commands/logs.ts
10013
- import { log as log32 } from "@clack/prompts";
10086
+ import { log as log31 } from "@clack/prompts";
10014
10087
  import { Command as Command29 } from "commander";
10015
10088
  import { spawn as spawn3 } from "child_process";
10016
10089
  var DAEMON_LOG_PATH = "/var/log/agentbox/ctl-daemon.log";
@@ -10032,9 +10105,9 @@ var logsCommand = new Command29("logs").description("Print recent log lines from
10032
10105
  service = boxArg;
10033
10106
  }
10034
10107
  if (!service && !opts.daemon) {
10035
- log32.error("missing <service> argument");
10036
- log32.info("usage: agentbox logs [box] <service> [-n N] [-f]");
10037
- log32.info(" agentbox logs [box] --daemon [-n N] [-f]");
10108
+ log31.error("missing <service> argument");
10109
+ log31.info("usage: agentbox logs [box] <service> [-n N] [-f]");
10110
+ log31.info(" agentbox logs [box] --daemon [-n N] [-f]");
10038
10111
  process.exit(2);
10039
10112
  }
10040
10113
  const box = await resolveBoxOrExit(idOrName);
@@ -10045,7 +10118,7 @@ var logsCommand = new Command29("logs").description("Print recent log lines from
10045
10118
  if (!opts.follow) {
10046
10119
  const proc = await provider.exec(box, args, { user: "vscode" });
10047
10120
  if (proc.exitCode !== 0) {
10048
- log32.error(
10121
+ log31.error(
10049
10122
  `${opts.daemon ? "daemon log" : "agentbox-ctl logs"} failed: ${proc.stderr || proc.stdout}`
10050
10123
  );
10051
10124
  process.exit(1);
@@ -10101,10 +10174,10 @@ var logsCommand = new Command29("logs").description("Print recent log lines from
10101
10174
  });
10102
10175
 
10103
10176
  // src/commands/open.ts
10104
- import { log as log33 } from "@clack/prompts";
10177
+ import { log as log32 } from "@clack/prompts";
10105
10178
  import { execa as execa3 } from "execa";
10106
10179
  import { existsSync as existsSync7, mkdirSync as mkdirSync6 } from "fs";
10107
- import { homedir as homedir14 } from "os";
10180
+ import { homedir as homedir15 } from "os";
10108
10181
  import { join as join16 } from "path";
10109
10182
  import { Command as Command30 } from "commander";
10110
10183
 
@@ -10167,7 +10240,7 @@ var openCommand = new Command30("open").description("Open a box's /workspace in
10167
10240
  }
10168
10241
  });
10169
10242
  async function runCloudOpen(box, provider, opts) {
10170
- const mountRoot = join16(homedir14(), ".agentbox", "mounts", box.name);
10243
+ const mountRoot = join16(homedir15(), ".agentbox", "mounts", box.name);
10171
10244
  if (opts.unmount) {
10172
10245
  const ok = await tryUnmount(mountRoot);
10173
10246
  if (ok) process.stdout.write(`unmounted ${mountRoot}
@@ -10207,10 +10280,10 @@ async function runCloudOpen(box, provider, opts) {
10207
10280
  if (!existsSync7(mountRoot)) {
10208
10281
  mkdirSync6(mountRoot, { recursive: true, mode: 493 });
10209
10282
  } else if (await isMounted(mountRoot)) {
10210
- log33.info(`re-mounting (stale mount detected at ${mountRoot})`);
10283
+ log32.info(`re-mounting (stale mount detected at ${mountRoot})`);
10211
10284
  await tryUnmount(mountRoot);
10212
10285
  }
10213
- log33.info(`mounting ${alias}:/workspace at ${mountRoot}`);
10286
+ log32.info(`mounting ${alias}:/workspace at ${mountRoot}`);
10214
10287
  const mount = await execa3(
10215
10288
  sshfsBin,
10216
10289
  [
@@ -10230,7 +10303,7 @@ async function runCloudOpen(box, provider, opts) {
10230
10303
  if (mount.exitCode !== 0) {
10231
10304
  throw new Error(`sshfs mount failed (exit ${String(mount.exitCode)}): ${mount.stderr || mount.stdout}`);
10232
10305
  }
10233
- await execa3("open", [mountRoot], { reject: false });
10306
+ await execa3(hostOpenCommand(), [mountRoot], { reject: false });
10234
10307
  process.stdout.write(`opened ${mountRoot}
10235
10308
  `);
10236
10309
  process.stdout.write(`unmount later with: agentbox open ${box.name} --unmount
@@ -10281,7 +10354,7 @@ var pauseCommand = new Command31("pause").description(
10281
10354
  });
10282
10355
 
10283
10356
  // src/commands/prune.ts
10284
- import { confirm as confirm15, isCancel as isCancel16, log as log34 } from "@clack/prompts";
10357
+ import { confirm as confirm15, isCancel as isCancel16, log as log33 } from "@clack/prompts";
10285
10358
  import { Command as Command32 } from "commander";
10286
10359
  function totalRemovals(r, projectConfigs) {
10287
10360
  return r.removedRecords.length + r.removedContainers.length + r.removedVolumes.length + r.removedSnapshotDirs.length + r.removedBoxDirs.length + projectConfigs.length;
@@ -10341,7 +10414,7 @@ var pruneCommand = new Command32("prune").description("Clean up orphan state.jso
10341
10414
  return;
10342
10415
  }
10343
10416
  if (opts.provider !== void 0 && opts.provider !== "docker") {
10344
- log34.error(`unknown provider '${opts.provider}'; expected docker, daytona, hetzner, or vercel`);
10417
+ log33.error(`unknown provider '${opts.provider}'; expected docker, daytona, hetzner, or vercel`);
10345
10418
  process.exit(2);
10346
10419
  }
10347
10420
  const dryRun = opts.dryRun ?? false;
@@ -10354,13 +10427,13 @@ var pruneCommand = new Command32("prune").description("Clean up orphan state.jso
10354
10427
  process.stdout.write("nothing to prune\n");
10355
10428
  return;
10356
10429
  }
10357
- log34.info(`would remove:
10430
+ log33.info(`would remove:
10358
10431
  ${summary(preview, previewProjects)}`);
10359
10432
  if (dryRun) return;
10360
10433
  if (!opts.yes) {
10361
10434
  const ok = await confirm15({ message: "Proceed with prune?", initialValue: true });
10362
10435
  if (isCancel16(ok) || !ok) {
10363
- log34.info("cancelled");
10436
+ log33.info("cancelled");
10364
10437
  return;
10365
10438
  }
10366
10439
  }
@@ -10381,7 +10454,7 @@ async function pruneCloud(provider, opts) {
10381
10454
  const dryRun = opts.dryRun ?? false;
10382
10455
  const backend = await cloudBackendForProvider(provider);
10383
10456
  if (!backend.list) {
10384
- log34.error(`${provider} backend doesn't expose \`list()\`; cannot enumerate sandboxes for prune`);
10457
+ log33.error(`${provider} backend doesn't expose \`list()\`; cannot enumerate sandboxes for prune`);
10385
10458
  process.exit(2);
10386
10459
  }
10387
10460
  const [remote, state] = await Promise.all([backend.list(), readState()]);
@@ -10401,7 +10474,7 @@ async function pruneCloud(provider, opts) {
10401
10474
  `);
10402
10475
  return;
10403
10476
  }
10404
- log34.info(`found ${String(orphans.length)} ${provider} sandbox(es) not in this CLI's state:`);
10477
+ log33.info(`found ${String(orphans.length)} ${provider} sandbox(es) not in this CLI's state:`);
10405
10478
  for (const sb of orphans) {
10406
10479
  const parts = [sb.sandboxId];
10407
10480
  if (sb.name) parts.push(sb.name);
@@ -10417,7 +10490,7 @@ async function pruneCloud(provider, opts) {
10417
10490
  initialValue: false
10418
10491
  });
10419
10492
  if (isCancel16(ok) || !ok) {
10420
- log34.info("cancelled");
10493
+ log33.info("cancelled");
10421
10494
  return;
10422
10495
  }
10423
10496
  }
@@ -10429,7 +10502,7 @@ async function pruneCloud(provider, opts) {
10429
10502
  deleted++;
10430
10503
  } catch (err) {
10431
10504
  failed++;
10432
- log34.warn(
10505
+ log33.warn(
10433
10506
  `delete ${sb.sandboxId} failed: ${err instanceof Error ? err.message : String(err)}`
10434
10507
  );
10435
10508
  }
@@ -10442,7 +10515,7 @@ async function pruneCloud(provider, opts) {
10442
10515
 
10443
10516
  // src/commands/queue.ts
10444
10517
  import { readFile as readFile4, stat as stat5 } from "fs/promises";
10445
- import { intro as intro7, log as log35, outro as outro7 } from "@clack/prompts";
10518
+ import { intro as intro7, log as log34, outro as outro6 } from "@clack/prompts";
10446
10519
  import { Command as Command33 } from "commander";
10447
10520
  var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["done", "failed", "cancelled"]);
10448
10521
  var queueCommand = new Command33("queue").description("Inspect and manage background `agentbox claude|codex|opencode -i` jobs");
@@ -10451,8 +10524,8 @@ var queueListCommand = new Command33("list").description("List queued, running,
10451
10524
  const cfg = await loadQueueConfig();
10452
10525
  const visible = opts.all === true ? jobs : jobs.filter((j) => !TERMINAL_STATUSES.has(j.status));
10453
10526
  if (visible.length === 0) {
10454
- log35.info(opts.all ? "no queued jobs." : "no active queued jobs (--all to see terminal).");
10455
- log35.info(`queue.maxConcurrent = ${String(cfg.maxConcurrent)} (queue.enabled=${String(cfg.enabled)})`);
10527
+ log34.info(opts.all ? "no queued jobs." : "no active queued jobs (--all to see terminal).");
10528
+ log34.info(`queue.maxConcurrent = ${String(cfg.maxConcurrent)} (queue.enabled=${String(cfg.enabled)})`);
10456
10529
  return;
10457
10530
  }
10458
10531
  const rows = visible.map((j) => ({
@@ -10477,12 +10550,12 @@ var queueListCommand = new Command33("list").description("List queued, running,
10477
10550
  headers.map((h, i) => pad4(String(r[h]), widths[i])).join(" ") + "\n"
10478
10551
  );
10479
10552
  }
10480
- log35.info(`queue.maxConcurrent = ${String(cfg.maxConcurrent)} (queue.enabled=${String(cfg.enabled)})`);
10553
+ log34.info(`queue.maxConcurrent = ${String(cfg.maxConcurrent)} (queue.enabled=${String(cfg.enabled)})`);
10481
10554
  });
10482
10555
  var queueShowCommand = new Command33("show").description("Dump a job manifest and tail its log").argument("<id>", "queue job id (from `agentbox queue list`)").option("--tail <n>", "lines of log to print (default: 50)", "50").action(async (id, opts) => {
10483
10556
  const job = await readJob(id);
10484
10557
  if (!job) {
10485
- log35.error(`no job with id ${id}`);
10558
+ log34.error(`no job with id ${id}`);
10486
10559
  process.exit(1);
10487
10560
  }
10488
10561
  process.stdout.write(JSON.stringify(job, null, 2) + "\n");
@@ -10498,18 +10571,18 @@ var queueShowCommand = new Command33("show").description("Dump a job manifest an
10498
10571
  process.stdout.write(slice.join("\n"));
10499
10572
  if (!slice.join("\n").endsWith("\n")) process.stdout.write("\n");
10500
10573
  } catch {
10501
- log35.info(`(no log at ${job.logPath} yet)`);
10574
+ log34.info(`(no log at ${job.logPath} yet)`);
10502
10575
  }
10503
10576
  });
10504
10577
  var queueCancelCommand = new Command33("cancel").description("Cancel a queued job; running jobs are NOT killed \u2014 use `agentbox destroy` instead").argument("<id>", "queue job id (from `agentbox queue list`)").action(async (id) => {
10505
10578
  intro7(`Cancelling queue job ${id}...`);
10506
10579
  const job = await readJob(id);
10507
10580
  if (!job) {
10508
- log35.error(`no job with id ${id}`);
10581
+ log34.error(`no job with id ${id}`);
10509
10582
  process.exit(1);
10510
10583
  }
10511
10584
  if (job.status !== "queued") {
10512
- log35.error(
10585
+ log34.error(
10513
10586
  `job ${id} is ${job.status}; cancel only flips 'queued' \u2192 'cancelled'.` + (job.status === "running" ? ` Use 'agentbox destroy ${job.boxName || id}' to stop the box.` : "")
10514
10587
  );
10515
10588
  process.exit(1);
@@ -10521,7 +10594,7 @@ var queueCancelCommand = new Command33("cancel").description("Cancel a queued jo
10521
10594
  reason: "cancelled by user"
10522
10595
  };
10523
10596
  await writeJob(cancelled);
10524
- outro7(`job ${id} cancelled`);
10597
+ outro6(`job ${id} cancelled`);
10525
10598
  });
10526
10599
  var queueClearCommand = new Command33("clear").description("Sweep terminal-state manifests from ~/.agentbox/queue/").option("--done", "remove done jobs").option("--failed", "remove failed jobs").option("--cancelled", "remove cancelled jobs").option("--all", "remove every terminal-state job (done + failed + cancelled)").action(async (opts) => {
10527
10600
  const targets = /* @__PURE__ */ new Set();
@@ -10529,7 +10602,7 @@ var queueClearCommand = new Command33("clear").description("Sweep terminal-state
10529
10602
  if (opts.all === true || opts.failed === true) targets.add("failed");
10530
10603
  if (opts.all === true || opts.cancelled === true) targets.add("cancelled");
10531
10604
  if (targets.size === 0) {
10532
- log35.error("pick at least one of: --done, --failed, --cancelled, --all");
10605
+ log34.error("pick at least one of: --done, --failed, --cancelled, --all");
10533
10606
  process.exit(2);
10534
10607
  }
10535
10608
  const jobs = await loadQueue();
@@ -10539,7 +10612,7 @@ var queueClearCommand = new Command33("clear").description("Sweep terminal-state
10539
10612
  await deleteJob(j.id);
10540
10613
  removed += 1;
10541
10614
  }
10542
- log35.success(`removed ${String(removed)} manifest${removed === 1 ? "" : "s"}`);
10615
+ log34.success(`removed ${String(removed)} manifest${removed === 1 ? "" : "s"}`);
10543
10616
  });
10544
10617
  var QUEUE_WAIT_EVENTS = [
10545
10618
  "new-box",
@@ -10556,7 +10629,7 @@ var queueWaitForCommand = new Command33("wait-for").description(
10556
10629
  `Block until a queue / box event fires. <event> one of: ${QUEUE_WAIT_EVENTS.join(" | ")}.`
10557
10630
  ).argument("<event>", `target event: ${QUEUE_WAIT_EVENTS.join(" | ")}`).option("--box <ref>", "box ref (required for box-paused / box-running / box-stopped)").option("--job <id>", "queue job id (required for job-done)").option("--timeout <ms>", `wall-clock cap (default: ${String(DEFAULT_QUEUE_WAIT_TIMEOUT_MS)})`).option("--json", "emit a JSON envelope { matched, elapsedMs, ... }").action(async (eventRaw, opts) => {
10558
10631
  if (!QUEUE_WAIT_EVENTS.includes(eventRaw)) {
10559
- log35.error(`unknown event '${eventRaw}' (one of: ${QUEUE_WAIT_EVENTS.join(", ")})`);
10632
+ log34.error(`unknown event '${eventRaw}' (one of: ${QUEUE_WAIT_EVENTS.join(", ")})`);
10560
10633
  process.exit(2);
10561
10634
  }
10562
10635
  const event = eventRaw;
@@ -10576,11 +10649,11 @@ var queueWaitForCommand = new Command33("wait-for").description(
10576
10649
  if (opts.json === true) {
10577
10650
  process.stdout.write(JSON.stringify({ matched: false, event, elapsedMs }) + "\n");
10578
10651
  } else {
10579
- log35.error(`'${event}' did not occur within ${String(timeoutMs)}ms`);
10652
+ log34.error(`'${event}' did not occur within ${String(timeoutMs)}ms`);
10580
10653
  }
10581
10654
  process.exit(1);
10582
10655
  }
10583
- log35.error(err instanceof Error ? err.message : String(err));
10656
+ log34.error(err instanceof Error ? err.message : String(err));
10584
10657
  process.exit(1);
10585
10658
  }
10586
10659
  });
@@ -10677,7 +10750,7 @@ function truncate(s, max) {
10677
10750
  }
10678
10751
 
10679
10752
  // src/commands/relay.ts
10680
- import { log as log36, spinner as spinner9 } from "@clack/prompts";
10753
+ import { log as log35, spinner as spinner9 } from "@clack/prompts";
10681
10754
  import { Command as Command34 } from "commander";
10682
10755
  async function rehydrateFromState() {
10683
10756
  const state = await readState();
@@ -10771,7 +10844,7 @@ var restartSub = new Command34("restart").description("Stop then start the host
10771
10844
  s2.stop(`relay running on ${ep.hostUrl}`);
10772
10845
  } catch (err) {
10773
10846
  s2.stop("relay start failed");
10774
- log36.warn(err instanceof Error ? err.message : String(err));
10847
+ log35.warn(err instanceof Error ? err.message : String(err));
10775
10848
  throw err;
10776
10849
  }
10777
10850
  } catch (err) {
@@ -10783,17 +10856,17 @@ var relayCommand = new Command34("relay").description("Manage the host relay pro
10783
10856
  // src/commands/_run-queued-job.ts
10784
10857
  import { Command as Command35 } from "commander";
10785
10858
  var runQueuedJobCommand = new Command35("_run-queued-job").description("internal: run a queued background agent job (do not invoke directly)").argument("<id>", "queue job id (from ~/.agentbox/queue/<id>.json)").action(async (id) => {
10786
- const log45 = openCommandLog(`queue-${id}`);
10787
- log45.write(`worker pid=${String(process.pid)} starting for job ${id}`);
10859
+ const log44 = openCommandLog(`queue-${id}`);
10860
+ log44.write(`worker pid=${String(process.pid)} starting for job ${id}`);
10788
10861
  let job = null;
10789
10862
  try {
10790
10863
  job = await readJob(id);
10791
10864
  if (!job) {
10792
- log45.write(`FATAL: no manifest at id=${id}`);
10793
- log45.close();
10865
+ log44.write(`FATAL: no manifest at id=${id}`);
10866
+ log44.close();
10794
10867
  process.exit(64);
10795
10868
  }
10796
- await runDockerJob(job, log45, (boxId) => {
10869
+ await runDockerJob(job, log44, (boxId) => {
10797
10870
  if (job) job = { ...job, boxId };
10798
10871
  });
10799
10872
  const done = {
@@ -10803,12 +10876,12 @@ var runQueuedJobCommand = new Command35("_run-queued-job").description("internal
10803
10876
  exitCode: 0
10804
10877
  };
10805
10878
  await writeJob(done);
10806
- log45.write(`done`);
10807
- log45.close();
10879
+ log44.write(`done`);
10880
+ log44.close();
10808
10881
  process.exit(0);
10809
10882
  } catch (err) {
10810
10883
  const msg = err instanceof Error ? err.stack ?? err.message : String(err);
10811
- log45.write(`FAIL: ${msg}`);
10884
+ log44.write(`FAIL: ${msg}`);
10812
10885
  if (job) {
10813
10886
  try {
10814
10887
  const failed = {
@@ -10822,11 +10895,11 @@ var runQueuedJobCommand = new Command35("_run-queued-job").description("internal
10822
10895
  } catch {
10823
10896
  }
10824
10897
  }
10825
- log45.close();
10898
+ log44.close();
10826
10899
  process.exit(1);
10827
10900
  }
10828
10901
  });
10829
- async function runDockerJob(job, log45, onBoxCreated) {
10902
+ async function runDockerJob(job, log44, onBoxCreated) {
10830
10903
  const opts = job.createOpts;
10831
10904
  const cfg = await loadEffectiveConfig(opts.workspace, {
10832
10905
  cliOverrides: buildOverridesFromJob(job)
@@ -10841,7 +10914,7 @@ async function runDockerJob(job, log45, onBoxCreated) {
10841
10914
  const useSnapshot = opts.hostSnapshot === false ? false : opts.hostSnapshot === true ? true : cfg.effective.box.hostSnapshot ?? false;
10842
10915
  const resolved = job.agent === "claude-code" ? await resolveClaudeAuth(process.env) : null;
10843
10916
  const withPlaywright = cfg.effective.box.withPlaywright || cfg.effective.browser.default !== "agent-browser";
10844
- log45.write(`creating box for agent=${job.agent}`);
10917
+ log44.write(`creating box for agent=${job.agent}`);
10845
10918
  const result = await createBox({
10846
10919
  workspacePath: opts.workspace,
10847
10920
  name: opts.name && opts.name.length > 0 ? opts.name : void 0,
@@ -10863,19 +10936,19 @@ async function runDockerJob(job, log45, onBoxCreated) {
10863
10936
  portlessStateDir: cfg.effective.portless.stateDir || void 0,
10864
10937
  limits: resolveLimits(cfg.effective.box, opts),
10865
10938
  projectRoot,
10866
- onLog: (line) => log45.write(line)
10939
+ onLog: (line) => log44.write(line)
10867
10940
  });
10868
- log45.write(`box created: ${result.record.container}`);
10941
+ log44.write(`box created: ${result.record.container}`);
10869
10942
  onBoxCreated(result.record.id);
10870
10943
  await writeJob({ ...job, boxId: result.record.id });
10871
10944
  const promptedArgs = buildPromptArgs(job.agent, job.prompt, job.agentArgs);
10872
10945
  if (job.agent === "claude-code") {
10873
- log45.write(`checking plugin native deps`);
10946
+ log44.write(`checking plugin native deps`);
10874
10947
  await rebuildPluginNativeDeps(result.record.container, {
10875
10948
  volume: result.record.claudeConfigVolume ?? SHARED_CLAUDE_VOLUME,
10876
- onProgress: (line) => log45.write(line)
10949
+ onProgress: (line) => log44.write(line)
10877
10950
  });
10878
- log45.write(`starting claude session`);
10951
+ log44.write(`starting claude session`);
10879
10952
  await startClaudeSession({
10880
10953
  container: result.record.container,
10881
10954
  claudeArgs: applyClaudeSkipPermissions(promptedArgs, cfg.effective),
@@ -10883,22 +10956,22 @@ async function runDockerJob(job, log45, onBoxCreated) {
10883
10956
  boxName: result.record.name
10884
10957
  });
10885
10958
  } else if (job.agent === "codex") {
10886
- log45.write(`checking codex`);
10959
+ log44.write(`checking codex`);
10887
10960
  await ensureCodexInstalled(result.record.container, {
10888
- onProgress: (line) => log45.write(line)
10961
+ onProgress: (line) => log44.write(line)
10889
10962
  });
10890
- log45.write(`starting codex session`);
10963
+ log44.write(`starting codex session`);
10891
10964
  await startCodexSession({
10892
10965
  container: result.record.container,
10893
10966
  codexArgs: applyCodexSkipPermissions(promptedArgs, cfg.effective),
10894
10967
  sessionName: cfg.effective.codex.sessionName
10895
10968
  });
10896
10969
  } else if (job.agent === "opencode") {
10897
- log45.write(`checking opencode`);
10970
+ log44.write(`checking opencode`);
10898
10971
  await ensureOpencodeInstalled(result.record.container, {
10899
- onProgress: (line) => log45.write(line)
10972
+ onProgress: (line) => log44.write(line)
10900
10973
  });
10901
- log45.write(`starting opencode session`);
10974
+ log44.write(`starting opencode session`);
10902
10975
  await startOpencodeSession({
10903
10976
  container: result.record.container,
10904
10977
  opencodeArgs: promptedArgs,
@@ -10937,7 +11010,7 @@ function buildOverridesFromJob(job) {
10937
11010
 
10938
11011
  // src/commands/screen.ts
10939
11012
  import { spawnSync as spawnSync3 } from "child_process";
10940
- import { log as log37 } from "@clack/prompts";
11013
+ import { log as log36 } from "@clack/prompts";
10941
11014
  import { Command as Command36 } from "commander";
10942
11015
  var SIGNED_URL_TTL_MIN = 1;
10943
11016
  var SIGNED_URL_TTL_MAX = 86400;
@@ -10968,10 +11041,10 @@ var screenCommand = new Command36("screen").description("Open a box's VNC (noVNC
10968
11041
  if (provider === "docker") {
10969
11042
  const insp = await inspectBox(box.id);
10970
11043
  if (insp.state === "paused") {
10971
- log37.info("box is paused; unpausing");
11044
+ log36.info("box is paused; unpausing");
10972
11045
  await unpauseBox(box.id);
10973
11046
  } else if (insp.state === "stopped") {
10974
- log37.info("box is stopped; starting");
11047
+ log36.info("box is stopped; starting");
10975
11048
  await startBox(box.id);
10976
11049
  } else if (insp.state === "missing") {
10977
11050
  throw new Error(`box ${box.name} has no container; was it destroyed?`);
@@ -10981,13 +11054,13 @@ var screenCommand = new Command36("screen").description("Open a box's VNC (noVNC
10981
11054
  const inBoxUrl = exposePort !== void 0 ? box.portlessUrl ?? `http://localhost:${String(exposePort)}` : "about:blank";
10982
11055
  const br = await ensureBoxBrowser(box.container, void 0, inBoxUrl);
10983
11056
  if (br.up && !br.alreadyRunning) {
10984
- log37.info(
11057
+ log36.info(
10985
11058
  exposePort !== void 0 ? `opened ${inBoxUrl} in the in-box browser (visible in the VNC view)` : "started in-box browser"
10986
11059
  );
10987
11060
  } else if (br.alreadyRunning) {
10988
- log37.info("in-box browser already running; left it untouched");
11061
+ log36.info("in-box browser already running; left it untouched");
10989
11062
  } else {
10990
- log37.warn(`could not start in-box browser: ${br.reason ?? "unknown"}`);
11063
+ log36.warn(`could not start in-box browser: ${br.reason ?? "unknown"}`);
10991
11064
  }
10992
11065
  const engine = await detectEngine();
10993
11066
  const urls = buildVncUrls(box, engine);
@@ -11008,10 +11081,10 @@ var screenCommand = new Command36("screen").description("Open a box's VNC (noVNC
11008
11081
  const p = await providerForBox(box);
11009
11082
  const state = await p.probeState(box);
11010
11083
  if (state === "paused") {
11011
- log37.info("box is paused; resuming");
11084
+ log36.info("box is paused; resuming");
11012
11085
  await p.resume(box);
11013
11086
  } else if (state === "stopped") {
11014
- log37.info("box is stopped; starting");
11087
+ log36.info("box is stopped; starting");
11015
11088
  await p.start(box);
11016
11089
  } else if (state === "missing") {
11017
11090
  throw new Error(`cloud sandbox for ${box.name} is missing; was it deleted?`);
@@ -11026,14 +11099,14 @@ var screenCommand = new Command36("screen").description("Open a box's VNC (noVNC
11026
11099
  user: "vscode"
11027
11100
  });
11028
11101
  if (br.exitCode === 0) {
11029
- log37.info(`opened ${webUrl} in the in-box browser (visible in the VNC view)`);
11102
+ log36.info(`opened ${webUrl} in the in-box browser (visible in the VNC view)`);
11030
11103
  } else {
11031
- log37.warn(
11104
+ log36.warn(
11032
11105
  `could not open in-box browser (continuing): ${br.stderr.trim() || br.stdout.trim() || `exit ${String(br.exitCode)}`}`
11033
11106
  );
11034
11107
  }
11035
11108
  } catch (err) {
11036
- log37.warn(
11109
+ log36.warn(
11037
11110
  `in-box browser skipped: ${err instanceof Error ? err.message : String(err)}`
11038
11111
  );
11039
11112
  }
@@ -11046,7 +11119,7 @@ var screenCommand = new Command36("screen").description("Open a box's VNC (noVNC
11046
11119
  `);
11047
11120
  return;
11048
11121
  }
11049
- const opened = spawnSync3("open", [url], { stdio: "inherit" });
11122
+ const opened = spawnSync3(hostOpenCommand(), [url], { stdio: "inherit" });
11050
11123
  if (opened.status !== 0) {
11051
11124
  throw new Error(`open ${url} failed (exit ${String(opened.status ?? "n/a")})`);
11052
11125
  }
@@ -11059,18 +11132,18 @@ var screenCommand = new Command36("screen").description("Open a box's VNC (noVNC
11059
11132
 
11060
11133
  // src/commands/shell.ts
11061
11134
  import { spawnSync as spawnSync4 } from "child_process";
11062
- import { log as log39 } from "@clack/prompts";
11135
+ import { log as log38 } from "@clack/prompts";
11063
11136
  import { Command as Command37 } from "commander";
11064
11137
 
11065
11138
  // src/commands/_provider-guard.ts
11066
- import { log as log38 } from "@clack/prompts";
11139
+ import { log as log37 } from "@clack/prompts";
11067
11140
  function requireDockerProvider(box, commandName) {
11068
11141
  const provider = box.provider ?? "docker";
11069
11142
  if (provider === "docker") return;
11070
- log38.error(
11143
+ log37.error(
11071
11144
  `\`agentbox ${commandName}\` doesn't yet support cloud boxes (this box's provider is '${provider}').`
11072
11145
  );
11073
- log38.info(
11146
+ log37.info(
11074
11147
  "Cloud-provider routing for this command is on the Phase 3 backlog. For now: use `agentbox url` for web access, `agentbox-ctl git push` from inside the sandbox via SSH/web terminal, or fall back to the cloud provider's own console."
11075
11148
  );
11076
11149
  process.exit(2);
@@ -11110,10 +11183,10 @@ function fmtAgo2(iso) {
11110
11183
  async function ensureBoxRunning(box) {
11111
11184
  const insp = await inspectBox(box.id);
11112
11185
  if (insp.state === "paused") {
11113
- log39.info("box is paused; unpausing");
11186
+ log38.info("box is paused; unpausing");
11114
11187
  await unpauseBox(box.id);
11115
11188
  } else if (insp.state === "stopped") {
11116
- log39.info("box is stopped; starting");
11189
+ log38.info("box is stopped; starting");
11117
11190
  await startBox(box.id);
11118
11191
  } else if (insp.state === "missing") {
11119
11192
  throw new Error(`box ${box.name} has no container; was it destroyed?`);
@@ -11152,7 +11225,7 @@ async function startOrAttachShell(box, cfg) {
11152
11225
  const label = shellLabel(cfg.sessionName);
11153
11226
  const info = await shellSessionInfo(box.container, cfg.sessionName, cfg.user);
11154
11227
  if (info.running) {
11155
- log39.info(`reattaching to shell "${label}" \u2014 Control+a d to detach`);
11228
+ log38.info(`reattaching to shell "${label}" \u2014 Control+a d to detach`);
11156
11229
  } else {
11157
11230
  await startShellSession({
11158
11231
  container: box.container,
@@ -11160,7 +11233,7 @@ async function startOrAttachShell(box, cfg) {
11160
11233
  user: cfg.user,
11161
11234
  login: cfg.login
11162
11235
  });
11163
- log39.info(`shell "${label}" \u2014 Control+a d to detach, leaves it running`);
11236
+ log38.info(`shell "${label}" \u2014 Control+a d to detach, leaves it running`);
11164
11237
  }
11165
11238
  const code = await runWrappedAttach({
11166
11239
  container: box.container,
@@ -11313,11 +11386,11 @@ var shellLsCommand = new Command37("ls").description("List the shell tmux sessio
11313
11386
  requireDockerProvider(box, "shell");
11314
11387
  const insp = await inspectBox(box.id);
11315
11388
  if (insp.state !== "running") {
11316
- log39.info(`box ${box.name} is ${insp.state} \u2014 no live shell sessions`);
11389
+ log38.info(`box ${box.name} is ${insp.state} \u2014 no live shell sessions`);
11317
11390
  return;
11318
11391
  }
11319
11392
  if (insp.shellSessions.length === 0) {
11320
- log39.info(
11393
+ log38.info(
11321
11394
  `no shell sessions in ${box.name} \u2014 start one with: agentbox shell ${reattachRef4(box)}`
11322
11395
  );
11323
11396
  return;
@@ -11337,25 +11410,25 @@ var shellKillCommand = new Command37("kill").description("Kill a shell tmux sess
11337
11410
  requireDockerProvider(box, "shell");
11338
11411
  const insp = await inspectBox(box.id);
11339
11412
  if (insp.state !== "running") {
11340
- log39.info(`box ${box.name} is ${insp.state} \u2014 no shell sessions to kill`);
11413
+ log38.info(`box ${box.name} is ${insp.state} \u2014 no shell sessions to kill`);
11341
11414
  return;
11342
11415
  }
11343
11416
  if (opts.all) {
11344
11417
  if (insp.shellSessions.length === 0) {
11345
- log39.info(`no shell sessions in ${box.name}`);
11418
+ log38.info(`no shell sessions in ${box.name}`);
11346
11419
  return;
11347
11420
  }
11348
11421
  let killed = 0;
11349
11422
  for (const s of insp.shellSessions) {
11350
11423
  if (await killShellSession(box.container, s.sessionName)) killed++;
11351
11424
  }
11352
- log39.success(`killed ${String(killed)} shell session${killed === 1 ? "" : "s"} in ${box.name}`);
11425
+ log38.success(`killed ${String(killed)} shell session${killed === 1 ? "" : "s"} in ${box.name}`);
11353
11426
  return;
11354
11427
  }
11355
11428
  const target = shellSessionName(opts.name);
11356
11429
  const ok = await killShellSession(box.container, target);
11357
- if (ok) log39.success(`killed shell "${shellLabel(target)}" in ${box.name}`);
11358
- else log39.warn(`no shell "${shellLabel(target)}" in ${box.name} (already gone?)`);
11430
+ if (ok) log38.success(`killed shell "${shellLabel(target)}" in ${box.name}`);
11431
+ else log38.warn(`no shell "${shellLabel(target)}" in ${box.name} (already gone?)`);
11359
11432
  } catch (err) {
11360
11433
  handleLifecycleError(err);
11361
11434
  }
@@ -11389,7 +11462,7 @@ var startCommand = new Command38("start").description(
11389
11462
  });
11390
11463
 
11391
11464
  // src/commands/status.ts
11392
- import { log as log41 } from "@clack/prompts";
11465
+ import { log as log40 } from "@clack/prompts";
11393
11466
  import { Command as Command39 } from "commander";
11394
11467
 
11395
11468
  // src/endpoints-render.ts
@@ -11420,7 +11493,7 @@ function renderEndpointLines(endpoints, stream) {
11420
11493
  }
11421
11494
 
11422
11495
  // src/commands/inspect.ts
11423
- import { log as log40 } from "@clack/prompts";
11496
+ import { log as log39 } from "@clack/prompts";
11424
11497
  function fmtLimit(n, unit) {
11425
11498
  return n && n > 0 ? `${String(n)}${unit}` : "unlimited";
11426
11499
  }
@@ -11565,7 +11638,7 @@ function renderCodexActivityCloud(persisted) {
11565
11638
  async function runInspect(box, opts) {
11566
11639
  try {
11567
11640
  if (opts.json && opts.watch) {
11568
- log40.error("cannot combine --json with --watch");
11641
+ log39.error("cannot combine --json with --watch");
11569
11642
  process.exit(2);
11570
11643
  }
11571
11644
  const isCloud = (box.provider ?? "docker") !== "docker";
@@ -11609,7 +11682,7 @@ var statusCommand2 = withWatchOptions(
11609
11682
  ).action(async (idOrName, opts) => {
11610
11683
  try {
11611
11684
  if (opts.json && opts.watch) {
11612
- log41.error("cannot combine --json with --watch");
11685
+ log40.error("cannot combine --json with --watch");
11613
11686
  process.exit(2);
11614
11687
  }
11615
11688
  const box = await resolveBoxOrExit(idOrName);
@@ -11938,7 +12011,7 @@ var unpauseCommand = new Command42("unpause").description(
11938
12011
 
11939
12012
  // src/commands/update.ts
11940
12013
  import { spawn as spawn4 } from "child_process";
11941
- import { confirm as confirm16, intro as intro8, isCancel as isCancel17, log as log42, outro as outro8, spinner as spinner10 } from "@clack/prompts";
12014
+ import { confirm as confirm16, intro as intro8, isCancel as isCancel17, log as log41, outro as outro7, spinner as spinner10 } from "@clack/prompts";
11942
12015
  import { Command as Command43 } from "commander";
11943
12016
 
11944
12017
  // src/exec-method.ts
@@ -11993,7 +12066,7 @@ var updateCommand = new Command43("self-update").description(
11993
12066
  });
11994
12067
  intro8("agentbox self-update");
11995
12068
  const selfStep = opts.skipSelf ? "self-update: skipped (--skip-self)" : describeSelfUpdate(method);
11996
- log42.info(
12069
+ log41.info(
11997
12070
  [
11998
12071
  "plan:",
11999
12072
  ` ${selfStep}`,
@@ -12002,31 +12075,31 @@ var updateCommand = new Command43("self-update").description(
12002
12075
  ].join("\n")
12003
12076
  );
12004
12077
  if (opts.dryRun) {
12005
- outro8("dry run \u2014 nothing changed");
12078
+ outro7("dry run \u2014 nothing changed");
12006
12079
  return;
12007
12080
  }
12008
12081
  if (!opts.yes) {
12009
12082
  const ok = await confirm16({ message: "Proceed with update?", initialValue: true });
12010
12083
  if (isCancel17(ok) || !ok) {
12011
- log42.info("cancelled");
12084
+ log41.info("cancelled");
12012
12085
  return;
12013
12086
  }
12014
12087
  }
12015
12088
  let selfUpdated = false;
12016
12089
  if (opts.skipSelf) {
12017
- log42.info("skipping self-update (--skip-self)");
12090
+ log41.info("skipping self-update (--skip-self)");
12018
12091
  } else {
12019
12092
  const cmd = selfUpdateCommand(method);
12020
12093
  if (cmd === null) {
12021
- log42.info(describeSelfUpdate(method));
12094
+ log41.info(describeSelfUpdate(method));
12022
12095
  } else {
12023
- log42.info(`running: ${cmd.cmd} ${cmd.args.join(" ")}`);
12096
+ log41.info(`running: ${cmd.cmd} ${cmd.args.join(" ")}`);
12024
12097
  const code = await runInherit(cmd.cmd, cmd.args);
12025
12098
  if (code !== 0) {
12026
12099
  throw new Error(`${cmd.cmd} exited with code ${String(code)}`);
12027
12100
  }
12028
12101
  selfUpdated = true;
12029
- log42.success(`updated ${PKG} via ${cmd.cmd}`);
12102
+ log41.success(`updated ${PKG} via ${cmd.cmd}`);
12030
12103
  }
12031
12104
  }
12032
12105
  const s = spinner10();
@@ -12042,7 +12115,7 @@ var updateCommand = new Command43("self-update").description(
12042
12115
  stop.stopped ? `stopped relay (pid ${String(stop.pid)})` : "relay was not running"
12043
12116
  );
12044
12117
  if (selfUpdated) {
12045
- log42.info(
12118
+ log41.info(
12046
12119
  "relay will restart automatically (with the updated build) on your next `agentbox create` / `agentbox claude`"
12047
12120
  );
12048
12121
  } else {
@@ -12053,12 +12126,12 @@ var updateCommand = new Command43("self-update").description(
12053
12126
  sr2.stop(`relay back up on ${ep.hostUrl}`);
12054
12127
  } catch (err) {
12055
12128
  sr2.stop("relay restart failed");
12056
- log42.warn(
12129
+ log41.warn(
12057
12130
  `${err instanceof Error ? err.message : String(err)} \u2014 it will retry on the next box command`
12058
12131
  );
12059
12132
  }
12060
12133
  }
12061
- outro8("update complete");
12134
+ outro7("update complete");
12062
12135
  } catch (err) {
12063
12136
  handleLifecycleError(err);
12064
12137
  }
@@ -12066,7 +12139,7 @@ var updateCommand = new Command43("self-update").description(
12066
12139
 
12067
12140
  // src/commands/url.ts
12068
12141
  import { spawnSync as spawnSync5 } from "child_process";
12069
- import { log as log43 } from "@clack/prompts";
12142
+ import { log as log42 } from "@clack/prompts";
12070
12143
  import { Command as Command44 } from "commander";
12071
12144
  var SIGNED_URL_TTL_MIN2 = 1;
12072
12145
  var SIGNED_URL_TTL_MAX2 = 86400;
@@ -12099,10 +12172,10 @@ var urlCommand = new Command44("url").description(
12099
12172
  if (provider === "docker") {
12100
12173
  const insp = await inspectBox(box.id);
12101
12174
  if (insp.state === "paused") {
12102
- log43.info("box is paused; unpausing");
12175
+ log42.info("box is paused; unpausing");
12103
12176
  await unpauseBox(box.id);
12104
12177
  } else if (insp.state === "stopped") {
12105
- log43.info("box is stopped; starting");
12178
+ log42.info("box is stopped; starting");
12106
12179
  await startBox(box.id);
12107
12180
  } else if (insp.state === "missing") {
12108
12181
  throw new Error(`box ${box.name} has no container; was it destroyed?`);
@@ -12131,10 +12204,10 @@ var urlCommand = new Command44("url").description(
12131
12204
  const p = await providerForBox(box);
12132
12205
  const state = await p.probeState(box);
12133
12206
  if (state === "paused") {
12134
- log43.info("box is paused; resuming");
12207
+ log42.info("box is paused; resuming");
12135
12208
  await p.resume(box);
12136
12209
  } else if (state === "stopped") {
12137
- log43.info("box is stopped; starting");
12210
+ log42.info("box is stopped; starting");
12138
12211
  await p.start(box);
12139
12212
  } else if (state === "missing") {
12140
12213
  throw new Error(`cloud sandbox for ${box.name} is missing; was it deleted?`);
@@ -12146,7 +12219,7 @@ var urlCommand = new Command44("url").description(
12146
12219
  `);
12147
12220
  return;
12148
12221
  }
12149
- const opened = spawnSync5("open", [url], { stdio: "inherit" });
12222
+ const opened = spawnSync5(hostOpenCommand(), [url], { stdio: "inherit" });
12150
12223
  if (opened.status !== 0) {
12151
12224
  throw new Error(`open ${url} failed (exit ${String(opened.status ?? "n/a")})`);
12152
12225
  }
@@ -12158,7 +12231,7 @@ var urlCommand = new Command44("url").description(
12158
12231
  });
12159
12232
 
12160
12233
  // src/commands/wait.ts
12161
- import { log as log44 } from "@clack/prompts";
12234
+ import { log as log43 } from "@clack/prompts";
12162
12235
  import { Command as Command45 } from "commander";
12163
12236
  var waitCommand = new Command45("wait").description("Block until the box reports all autostart units ready").argument(
12164
12237
  "[box]",
@@ -12176,7 +12249,7 @@ var waitCommand = new Command45("wait").description("Block until the box reports
12176
12249
  try {
12177
12250
  parsed = JSON.parse(proc.stdout);
12178
12251
  } catch {
12179
- log44.error(`agentbox-ctl wait-ready failed: ${proc.stderr || proc.stdout}`);
12252
+ log43.error(`agentbox-ctl wait-ready failed: ${proc.stderr || proc.stdout}`);
12180
12253
  process.exit(1);
12181
12254
  }
12182
12255
  if (opts.json) {