@craftspace/cli 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1201,7 +1201,7 @@ var require_command = __commonJS({
1201
1201
  var childProcess = __require("node:child_process");
1202
1202
  var path5 = __require("node:path");
1203
1203
  var fs = __require("node:fs");
1204
- var process5 = __require("node:process");
1204
+ var process6 = __require("node:process");
1205
1205
  var { Argument: Argument2, humanReadableArgName } = require_argument();
1206
1206
  var { CommanderError: CommanderError2 } = require_error();
1207
1207
  var { Help: Help2, stripColor } = require_help();
@@ -1248,13 +1248,13 @@ var require_command = __commonJS({
1248
1248
  this._showSuggestionAfterError = true;
1249
1249
  this._savedState = null;
1250
1250
  this._outputConfiguration = {
1251
- writeOut: (str) => process5.stdout.write(str),
1252
- writeErr: (str) => process5.stderr.write(str),
1251
+ writeOut: (str) => process6.stdout.write(str),
1252
+ writeErr: (str) => process6.stderr.write(str),
1253
1253
  outputError: (str, write) => write(str),
1254
- getOutHelpWidth: () => process5.stdout.isTTY ? process5.stdout.columns : void 0,
1255
- getErrHelpWidth: () => process5.stderr.isTTY ? process5.stderr.columns : void 0,
1256
- getOutHasColors: () => useColor() ?? (process5.stdout.isTTY && process5.stdout.hasColors?.()),
1257
- getErrHasColors: () => useColor() ?? (process5.stderr.isTTY && process5.stderr.hasColors?.()),
1254
+ getOutHelpWidth: () => process6.stdout.isTTY ? process6.stdout.columns : void 0,
1255
+ getErrHelpWidth: () => process6.stderr.isTTY ? process6.stderr.columns : void 0,
1256
+ getOutHasColors: () => useColor() ?? (process6.stdout.isTTY && process6.stdout.hasColors?.()),
1257
+ getErrHasColors: () => useColor() ?? (process6.stderr.isTTY && process6.stderr.hasColors?.()),
1258
1258
  stripColor: (str) => stripColor(str)
1259
1259
  };
1260
1260
  this._hidden = false;
@@ -1648,7 +1648,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1648
1648
  if (this._exitCallback) {
1649
1649
  this._exitCallback(new CommanderError2(exitCode, code, message));
1650
1650
  }
1651
- process5.exit(exitCode);
1651
+ process6.exit(exitCode);
1652
1652
  }
1653
1653
  /**
1654
1654
  * Register callback `fn` for the command.
@@ -2048,16 +2048,16 @@ Expecting one of '${allowedValues.join("', '")}'`);
2048
2048
  }
2049
2049
  parseOptions = parseOptions || {};
2050
2050
  if (argv === void 0 && parseOptions.from === void 0) {
2051
- if (process5.versions?.electron) {
2051
+ if (process6.versions?.electron) {
2052
2052
  parseOptions.from = "electron";
2053
2053
  }
2054
- const execArgv = process5.execArgv ?? [];
2054
+ const execArgv = process6.execArgv ?? [];
2055
2055
  if (execArgv.includes("-e") || execArgv.includes("--eval") || execArgv.includes("-p") || execArgv.includes("--print")) {
2056
2056
  parseOptions.from = "eval";
2057
2057
  }
2058
2058
  }
2059
2059
  if (argv === void 0) {
2060
- argv = process5.argv;
2060
+ argv = process6.argv;
2061
2061
  }
2062
2062
  this.rawArgs = argv.slice();
2063
2063
  let userArgs;
@@ -2068,7 +2068,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2068
2068
  userArgs = argv.slice(2);
2069
2069
  break;
2070
2070
  case "electron":
2071
- if (process5.defaultApp) {
2071
+ if (process6.defaultApp) {
2072
2072
  this._scriptPath = argv[1];
2073
2073
  userArgs = argv.slice(2);
2074
2074
  } else {
@@ -2255,11 +2255,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
2255
2255
  }
2256
2256
  launchWithNode = sourceExt.includes(path5.extname(executableFile));
2257
2257
  let proc;
2258
- if (process5.platform !== "win32") {
2258
+ if (process6.platform !== "win32") {
2259
2259
  if (launchWithNode) {
2260
2260
  args.unshift(executableFile);
2261
- args = incrementNodeInspectorPort(process5.execArgv).concat(args);
2262
- proc = childProcess.spawn(process5.argv[0], args, { stdio: "inherit" });
2261
+ args = incrementNodeInspectorPort(process6.execArgv).concat(args);
2262
+ proc = childProcess.spawn(process6.argv[0], args, { stdio: "inherit" });
2263
2263
  } else {
2264
2264
  proc = childProcess.spawn(executableFile, args, { stdio: "inherit" });
2265
2265
  }
@@ -2270,13 +2270,13 @@ Expecting one of '${allowedValues.join("', '")}'`);
2270
2270
  subcommand._name
2271
2271
  );
2272
2272
  args.unshift(executableFile);
2273
- args = incrementNodeInspectorPort(process5.execArgv).concat(args);
2274
- proc = childProcess.spawn(process5.execPath, args, { stdio: "inherit" });
2273
+ args = incrementNodeInspectorPort(process6.execArgv).concat(args);
2274
+ proc = childProcess.spawn(process6.execPath, args, { stdio: "inherit" });
2275
2275
  }
2276
2276
  if (!proc.killed) {
2277
2277
  const signals2 = ["SIGUSR1", "SIGUSR2", "SIGTERM", "SIGINT", "SIGHUP"];
2278
2278
  signals2.forEach((signal) => {
2279
- process5.on(signal, () => {
2279
+ process6.on(signal, () => {
2280
2280
  if (proc.killed === false && proc.exitCode === null) {
2281
2281
  proc.kill(signal);
2282
2282
  }
@@ -2287,7 +2287,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2287
2287
  proc.on("close", (code) => {
2288
2288
  code = code ?? 1;
2289
2289
  if (!exitCallback) {
2290
- process5.exit(code);
2290
+ process6.exit(code);
2291
2291
  } else {
2292
2292
  exitCallback(
2293
2293
  new CommanderError2(
@@ -2309,7 +2309,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2309
2309
  throw new Error(`'${executableFile}' not executable`);
2310
2310
  }
2311
2311
  if (!exitCallback) {
2312
- process5.exit(1);
2312
+ process6.exit(1);
2313
2313
  } else {
2314
2314
  const wrappedError = new CommanderError2(
2315
2315
  1,
@@ -2809,13 +2809,13 @@ Expecting one of '${allowedValues.join("', '")}'`);
2809
2809
  */
2810
2810
  _parseOptionsEnv() {
2811
2811
  this.options.forEach((option) => {
2812
- if (option.envVar && option.envVar in process5.env) {
2812
+ if (option.envVar && option.envVar in process6.env) {
2813
2813
  const optionKey = option.attributeName();
2814
2814
  if (this.getOptionValue(optionKey) === void 0 || ["default", "config", "env"].includes(
2815
2815
  this.getOptionValueSource(optionKey)
2816
2816
  )) {
2817
2817
  if (option.required || option.optional) {
2818
- this.emit(`optionEnv:${option.name()}`, process5.env[option.envVar]);
2818
+ this.emit(`optionEnv:${option.name()}`, process6.env[option.envVar]);
2819
2819
  } else {
2820
2820
  this.emit(`optionEnv:${option.name()}`);
2821
2821
  }
@@ -3339,7 +3339,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
3339
3339
  */
3340
3340
  help(contextOptions) {
3341
3341
  this.outputHelp(contextOptions);
3342
- let exitCode = Number(process5.exitCode ?? 0);
3342
+ let exitCode = Number(process6.exitCode ?? 0);
3343
3343
  if (exitCode === 0 && contextOptions && typeof contextOptions !== "function" && contextOptions.error) {
3344
3344
  exitCode = 1;
3345
3345
  }
@@ -3429,9 +3429,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
3429
3429
  });
3430
3430
  }
3431
3431
  function useColor() {
3432
- if (process5.env.NO_COLOR || process5.env.FORCE_COLOR === "0" || process5.env.FORCE_COLOR === "false")
3432
+ if (process6.env.NO_COLOR || process6.env.FORCE_COLOR === "0" || process6.env.FORCE_COLOR === "false")
3433
3433
  return false;
3434
- if (process5.env.FORCE_COLOR || process5.env.CLICOLOR_FORCE !== void 0)
3434
+ if (process6.env.FORCE_COLOR || process6.env.CLICOLOR_FORCE !== void 0)
3435
3435
  return true;
3436
3436
  return void 0;
3437
3437
  }
@@ -4189,12 +4189,12 @@ function $constructor(name, initializer3, params) {
4189
4189
  }
4190
4190
  inst._zod.traits.add(name);
4191
4191
  initializer3(inst, def);
4192
- const proto = _.prototype;
4193
- const keys = Object.keys(proto);
4192
+ const proto2 = _.prototype;
4193
+ const keys = Object.keys(proto2);
4194
4194
  for (let i = 0; i < keys.length; i++) {
4195
4195
  const k = keys[i];
4196
4196
  if (!(k in inst)) {
4197
- inst[k] = proto[k].bind(inst);
4197
+ inst[k] = proto2[k].bind(inst);
4198
4198
  }
4199
4199
  }
4200
4200
  }
@@ -6224,11 +6224,11 @@ var $ZodCIDRv6 = /* @__PURE__ */ $constructor("$ZodCIDRv6", (inst, def) => {
6224
6224
  def.pattern ?? (def.pattern = cidrv6);
6225
6225
  $ZodStringFormat.init(inst, def);
6226
6226
  inst._zod.check = (payload) => {
6227
- const parts = payload.value.split("/");
6227
+ const parts2 = payload.value.split("/");
6228
6228
  try {
6229
- if (parts.length !== 2)
6229
+ if (parts2.length !== 2)
6230
6230
  throw new Error();
6231
- const [address, prefix] = parts;
6231
+ const [address, prefix] = parts2;
6232
6232
  if (!prefix)
6233
6233
  throw new Error();
6234
6234
  const prefixNum = Number(prefix);
@@ -14885,10 +14885,10 @@ function _readonly(Class2, innerType) {
14885
14885
  });
14886
14886
  }
14887
14887
  // @__NO_SIDE_EFFECTS__
14888
- function _templateLiteral(Class2, parts, params) {
14888
+ function _templateLiteral(Class2, parts2, params) {
14889
14889
  return new Class2({
14890
14890
  type: "template_literal",
14891
- parts,
14891
+ parts: parts2,
14892
14892
  ...normalizeParams(params)
14893
14893
  });
14894
14894
  }
@@ -16337,18 +16337,18 @@ var safeDecodeAsync2 = /* @__PURE__ */ _safeDecodeAsync(ZodRealError);
16337
16337
  // ../../../node_modules/zod/v4/classic/schemas.js
16338
16338
  var _installedGroups = /* @__PURE__ */ new WeakMap();
16339
16339
  function _installLazyMethods(inst, group, methods) {
16340
- const proto = Object.getPrototypeOf(inst);
16341
- let installed = _installedGroups.get(proto);
16340
+ const proto2 = Object.getPrototypeOf(inst);
16341
+ let installed = _installedGroups.get(proto2);
16342
16342
  if (!installed) {
16343
16343
  installed = /* @__PURE__ */ new Set();
16344
- _installedGroups.set(proto, installed);
16344
+ _installedGroups.set(proto2, installed);
16345
16345
  }
16346
16346
  if (installed.has(group))
16347
16347
  return;
16348
16348
  installed.add(group);
16349
16349
  for (const key in methods) {
16350
16350
  const fn = methods[key];
16351
- Object.defineProperty(proto, key, {
16351
+ Object.defineProperty(proto2, key, {
16352
16352
  configurable: true,
16353
16353
  enumerable: false,
16354
16354
  get() {
@@ -17516,10 +17516,10 @@ var ZodTemplateLiteral = /* @__PURE__ */ $constructor("ZodTemplateLiteral", (ins
17516
17516
  ZodType.init(inst, def);
17517
17517
  inst._zod.processJSONSchema = (ctx, json2, params) => templateLiteralProcessor(inst, ctx, json2, params);
17518
17518
  });
17519
- function templateLiteral(parts, params) {
17519
+ function templateLiteral(parts2, params) {
17520
17520
  return new ZodTemplateLiteral({
17521
17521
  type: "template_literal",
17522
- parts,
17522
+ parts: parts2,
17523
17523
  ...util_exports.normalizeParams(params)
17524
17524
  });
17525
17525
  }
@@ -19782,7 +19782,9 @@ var SaveWorkstationBodySchema = external_exports.object({
19782
19782
  var WorkstationResponseSchema = external_exports.object({ workstation: WorkstationSchema });
19783
19783
 
19784
19784
  // ../../shared/dist/machines/machine.js
19785
- var CLI_VERSION = "0.2.2";
19785
+ var CLI_VERSION = "0.3.0";
19786
+ var CLI_PACKAGE = "@craftspace/cli";
19787
+ var CLI_INSTALL = `npm i -g ${CLI_PACKAGE}`;
19786
19788
  var MACHINE_BEAT_INTERVAL_MS = 15e3;
19787
19789
  var MACHINE_BEAT_BUSY_INTERVAL_MS = 3e3;
19788
19790
  var MACHINE_RUN_OUTPUT_MAX = 32e3;
@@ -20248,11 +20250,11 @@ var MemberActivityListResponse = external_exports.object({
20248
20250
  });
20249
20251
 
20250
20252
  // dist/machine.js
20251
- import { execFile as execFile3 } from "node:child_process";
20253
+ import { execFile as execFile4 } from "node:child_process";
20252
20254
  import { mkdir, readFile as readFile2, readdir, rm, writeFile } from "node:fs/promises";
20253
- import os4 from "node:os";
20255
+ import os5 from "node:os";
20254
20256
  import path4 from "node:path";
20255
- import { promisify as promisify3 } from "node:util";
20257
+ import { promisify as promisify4 } from "node:util";
20256
20258
 
20257
20259
  // ../../../node_modules/@inquirer/core/dist/lib/key.js
20258
20260
  var keybindings = ["emacs", "vim"];
@@ -20261,10 +20263,10 @@ function isKeybinding(value) {
20261
20263
  return keybindingLookup.has(value);
20262
20264
  }
20263
20265
  function getDefaultKeybindings() {
20264
- const env = process.env["INQUIRER_KEYBINDINGS"];
20265
- if (!env)
20266
+ const env2 = process.env["INQUIRER_KEYBINDINGS"];
20267
+ if (!env2)
20266
20268
  return [];
20267
- return Array.from(new Set(env.toLowerCase().split(/[\s,]+/).filter(isKeybinding)));
20269
+ return Array.from(new Set(env2.toLowerCase().split(/[\s,]+/).filter(isKeybinding)));
20268
20270
  }
20269
20271
  var isUpKey = (key, keybindings2 = []) => (
20270
20272
  // The up key
@@ -20781,11 +20783,11 @@ function getDefaultTheme() {
20781
20783
  function isPlainObject2(value) {
20782
20784
  if (typeof value !== "object" || value === null)
20783
20785
  return false;
20784
- let proto = value;
20785
- while (Object.getPrototypeOf(proto) !== null) {
20786
- proto = Object.getPrototypeOf(proto);
20786
+ let proto2 = value;
20787
+ while (Object.getPrototypeOf(proto2) !== null) {
20788
+ proto2 = Object.getPrototypeOf(proto2);
20787
20789
  }
20788
- return Object.getPrototypeOf(value) === proto;
20790
+ return Object.getPrototypeOf(value) === proto2;
20789
20791
  }
20790
20792
  function deepMerge(...objects) {
20791
20793
  const output = {};
@@ -21339,7 +21341,7 @@ if (process.platform === "linux") {
21339
21341
  }
21340
21342
 
21341
21343
  // ../../../node_modules/signal-exit/dist/mjs/index.js
21342
- var processOk = (process5) => !!process5 && typeof process5 === "object" && typeof process5.removeListener === "function" && typeof process5.emit === "function" && typeof process5.reallyExit === "function" && typeof process5.listeners === "function" && typeof process5.kill === "function" && typeof process5.pid === "number" && typeof process5.on === "function";
21344
+ var processOk = (process6) => !!process6 && typeof process6 === "object" && typeof process6.removeListener === "function" && typeof process6.emit === "function" && typeof process6.reallyExit === "function" && typeof process6.listeners === "function" && typeof process6.kill === "function" && typeof process6.pid === "number" && typeof process6.on === "function";
21343
21345
  var kExitEmitter = /* @__PURE__ */ Symbol.for("signal-exit emitter");
21344
21346
  var global = globalThis;
21345
21347
  var ObjectDefineProperty = Object.defineProperty.bind(Object);
@@ -21432,15 +21434,15 @@ var SignalExit = class extends SignalExitBase {
21432
21434
  #originalProcessReallyExit;
21433
21435
  #sigListeners = {};
21434
21436
  #loaded = false;
21435
- constructor(process5) {
21437
+ constructor(process6) {
21436
21438
  super();
21437
- this.#process = process5;
21439
+ this.#process = process6;
21438
21440
  this.#sigListeners = {};
21439
21441
  for (const sig of signals) {
21440
21442
  this.#sigListeners[sig] = () => {
21441
21443
  const listeners = this.#process.listeners(sig);
21442
21444
  let { count } = this.#emitter;
21443
- const p = process5;
21445
+ const p = process6;
21444
21446
  if (typeof p.__signal_exit_emitter__ === "object" && typeof p.__signal_exit_emitter__.count === "number") {
21445
21447
  count += p.__signal_exit_emitter__.count;
21446
21448
  }
@@ -21449,12 +21451,12 @@ var SignalExit = class extends SignalExitBase {
21449
21451
  const ret = this.#emitter.emit("exit", null, sig);
21450
21452
  const s = sig === "SIGHUP" ? this.#hupSig : sig;
21451
21453
  if (!ret)
21452
- process5.kill(process5.pid, s);
21454
+ process6.kill(process6.pid, s);
21453
21455
  }
21454
21456
  };
21455
21457
  }
21456
- this.#originalProcessReallyExit = process5.reallyExit;
21457
- this.#originalProcessEmit = process5.emit;
21458
+ this.#originalProcessReallyExit = process6.reallyExit;
21459
+ this.#originalProcessEmit = process6.emit;
21458
21460
  }
21459
21461
  onExit(cb, opts) {
21460
21462
  if (!processOk(this.#process)) {
@@ -22257,7 +22259,7 @@ function parseJson(line) {
22257
22259
 
22258
22260
  // dist/setup.js
22259
22261
  import { execFile as execFile2 } from "node:child_process";
22260
- import os3 from "node:os";
22262
+ import os4 from "node:os";
22261
22263
  import path3 from "node:path";
22262
22264
  import { promisify as promisify2 } from "node:util";
22263
22265
 
@@ -22363,6 +22365,568 @@ var LINUX_CHROME = ["google-chrome", "google-chrome-stable", "chromium"];
22363
22365
  var PROBE_TIMEOUT_MS = 5e3;
22364
22366
  var SSH_PROBE_TIMEOUT_MS = 1500;
22365
22367
 
22368
+ // node_modules/chalk/source/vendor/ansi-styles/index.js
22369
+ var ANSI_BACKGROUND_OFFSET = 10;
22370
+ var wrapAnsi16 = (offset = 0) => (code) => `\x1B[${code + offset}m`;
22371
+ var wrapAnsi256 = (offset = 0) => (code) => `\x1B[${38 + offset};5;${code}m`;
22372
+ var wrapAnsi16m = (offset = 0) => (red, green, blue) => `\x1B[${38 + offset};2;${red};${green};${blue}m`;
22373
+ var styles = {
22374
+ modifier: {
22375
+ reset: [0, 0],
22376
+ // 21 isn't widely supported and 22 does the same thing
22377
+ bold: [1, 22],
22378
+ dim: [2, 22],
22379
+ italic: [3, 23],
22380
+ underline: [4, 24],
22381
+ overline: [53, 55],
22382
+ inverse: [7, 27],
22383
+ hidden: [8, 28],
22384
+ strikethrough: [9, 29]
22385
+ },
22386
+ color: {
22387
+ black: [30, 39],
22388
+ red: [31, 39],
22389
+ green: [32, 39],
22390
+ yellow: [33, 39],
22391
+ blue: [34, 39],
22392
+ magenta: [35, 39],
22393
+ cyan: [36, 39],
22394
+ white: [37, 39],
22395
+ // Bright color
22396
+ blackBright: [90, 39],
22397
+ gray: [90, 39],
22398
+ // Alias of `blackBright`
22399
+ grey: [90, 39],
22400
+ // Alias of `blackBright`
22401
+ redBright: [91, 39],
22402
+ greenBright: [92, 39],
22403
+ yellowBright: [93, 39],
22404
+ blueBright: [94, 39],
22405
+ magentaBright: [95, 39],
22406
+ cyanBright: [96, 39],
22407
+ whiteBright: [97, 39]
22408
+ },
22409
+ bgColor: {
22410
+ bgBlack: [40, 49],
22411
+ bgRed: [41, 49],
22412
+ bgGreen: [42, 49],
22413
+ bgYellow: [43, 49],
22414
+ bgBlue: [44, 49],
22415
+ bgMagenta: [45, 49],
22416
+ bgCyan: [46, 49],
22417
+ bgWhite: [47, 49],
22418
+ // Bright color
22419
+ bgBlackBright: [100, 49],
22420
+ bgGray: [100, 49],
22421
+ // Alias of `bgBlackBright`
22422
+ bgGrey: [100, 49],
22423
+ // Alias of `bgBlackBright`
22424
+ bgRedBright: [101, 49],
22425
+ bgGreenBright: [102, 49],
22426
+ bgYellowBright: [103, 49],
22427
+ bgBlueBright: [104, 49],
22428
+ bgMagentaBright: [105, 49],
22429
+ bgCyanBright: [106, 49],
22430
+ bgWhiteBright: [107, 49]
22431
+ }
22432
+ };
22433
+ var modifierNames = Object.keys(styles.modifier);
22434
+ var foregroundColorNames = Object.keys(styles.color);
22435
+ var backgroundColorNames = Object.keys(styles.bgColor);
22436
+ var colorNames = [...foregroundColorNames, ...backgroundColorNames];
22437
+ function assembleStyles() {
22438
+ const codes = /* @__PURE__ */ new Map();
22439
+ for (const [groupName, group] of Object.entries(styles)) {
22440
+ for (const [styleName, style] of Object.entries(group)) {
22441
+ styles[styleName] = {
22442
+ open: `\x1B[${style[0]}m`,
22443
+ close: `\x1B[${style[1]}m`
22444
+ };
22445
+ group[styleName] = styles[styleName];
22446
+ codes.set(style[0], style[1]);
22447
+ }
22448
+ Object.defineProperty(styles, groupName, {
22449
+ value: group,
22450
+ enumerable: false
22451
+ });
22452
+ }
22453
+ Object.defineProperty(styles, "codes", {
22454
+ value: codes,
22455
+ enumerable: false
22456
+ });
22457
+ styles.color.close = "\x1B[39m";
22458
+ styles.bgColor.close = "\x1B[49m";
22459
+ styles.color.ansi = wrapAnsi16();
22460
+ styles.color.ansi256 = wrapAnsi256();
22461
+ styles.color.ansi16m = wrapAnsi16m();
22462
+ styles.bgColor.ansi = wrapAnsi16(ANSI_BACKGROUND_OFFSET);
22463
+ styles.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET);
22464
+ styles.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);
22465
+ Object.defineProperties(styles, {
22466
+ rgbToAnsi256: {
22467
+ value(red, green, blue) {
22468
+ if (red === green && green === blue) {
22469
+ if (red < 8) {
22470
+ return 16;
22471
+ }
22472
+ if (red > 248) {
22473
+ return 231;
22474
+ }
22475
+ return Math.round((red - 8) / 247 * 24) + 232;
22476
+ }
22477
+ return 16 + 36 * Math.round(red / 255 * 5) + 6 * Math.round(green / 255 * 5) + Math.round(blue / 255 * 5);
22478
+ },
22479
+ enumerable: false
22480
+ },
22481
+ hexToRgb: {
22482
+ value(hex3) {
22483
+ const matches = /[a-f\d]{6}|[a-f\d]{3}/i.exec(hex3.toString(16));
22484
+ if (!matches) {
22485
+ return [0, 0, 0];
22486
+ }
22487
+ let [colorString] = matches;
22488
+ if (colorString.length === 3) {
22489
+ colorString = [...colorString].map((character) => character + character).join("");
22490
+ }
22491
+ const integer2 = Number.parseInt(colorString, 16);
22492
+ return [
22493
+ /* eslint-disable no-bitwise */
22494
+ integer2 >> 16 & 255,
22495
+ integer2 >> 8 & 255,
22496
+ integer2 & 255
22497
+ /* eslint-enable no-bitwise */
22498
+ ];
22499
+ },
22500
+ enumerable: false
22501
+ },
22502
+ hexToAnsi256: {
22503
+ value: (hex3) => styles.rgbToAnsi256(...styles.hexToRgb(hex3)),
22504
+ enumerable: false
22505
+ },
22506
+ ansi256ToAnsi: {
22507
+ value(code) {
22508
+ if (code < 8) {
22509
+ return 30 + code;
22510
+ }
22511
+ if (code < 16) {
22512
+ return 90 + (code - 8);
22513
+ }
22514
+ let red;
22515
+ let green;
22516
+ let blue;
22517
+ if (code >= 232) {
22518
+ red = ((code - 232) * 10 + 8) / 255;
22519
+ green = red;
22520
+ blue = red;
22521
+ } else {
22522
+ code -= 16;
22523
+ const remainder = code % 36;
22524
+ red = Math.floor(code / 36) / 5;
22525
+ green = Math.floor(remainder / 6) / 5;
22526
+ blue = remainder % 6 / 5;
22527
+ }
22528
+ const value = Math.max(red, green, blue) * 2;
22529
+ if (value === 0) {
22530
+ return 30;
22531
+ }
22532
+ let result = 30 + (Math.round(blue) << 2 | Math.round(green) << 1 | Math.round(red));
22533
+ if (value === 2) {
22534
+ result += 60;
22535
+ }
22536
+ return result;
22537
+ },
22538
+ enumerable: false
22539
+ },
22540
+ rgbToAnsi: {
22541
+ value: (red, green, blue) => styles.ansi256ToAnsi(styles.rgbToAnsi256(red, green, blue)),
22542
+ enumerable: false
22543
+ },
22544
+ hexToAnsi: {
22545
+ value: (hex3) => styles.ansi256ToAnsi(styles.hexToAnsi256(hex3)),
22546
+ enumerable: false
22547
+ }
22548
+ });
22549
+ return styles;
22550
+ }
22551
+ var ansiStyles = assembleStyles();
22552
+ var ansi_styles_default = ansiStyles;
22553
+
22554
+ // node_modules/chalk/source/vendor/supports-color/index.js
22555
+ import process5 from "node:process";
22556
+ import os3 from "node:os";
22557
+ import tty from "node:tty";
22558
+ function hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : process5.argv) {
22559
+ const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
22560
+ const position = argv.indexOf(prefix + flag);
22561
+ const terminatorPosition = argv.indexOf("--");
22562
+ return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
22563
+ }
22564
+ var { env } = process5;
22565
+ var flagForceColor;
22566
+ if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) {
22567
+ flagForceColor = 0;
22568
+ } else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) {
22569
+ flagForceColor = 1;
22570
+ }
22571
+ function envForceColor() {
22572
+ if ("FORCE_COLOR" in env) {
22573
+ if (env.FORCE_COLOR === "true") {
22574
+ return 1;
22575
+ }
22576
+ if (env.FORCE_COLOR === "false") {
22577
+ return 0;
22578
+ }
22579
+ return env.FORCE_COLOR.length === 0 ? 1 : Math.min(Number.parseInt(env.FORCE_COLOR, 10), 3);
22580
+ }
22581
+ }
22582
+ function translateLevel(level) {
22583
+ if (level === 0) {
22584
+ return false;
22585
+ }
22586
+ return {
22587
+ level,
22588
+ hasBasic: true,
22589
+ has256: level >= 2,
22590
+ has16m: level >= 3
22591
+ };
22592
+ }
22593
+ function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
22594
+ const noFlagForceColor = envForceColor();
22595
+ if (noFlagForceColor !== void 0) {
22596
+ flagForceColor = noFlagForceColor;
22597
+ }
22598
+ const forceColor = sniffFlags ? flagForceColor : noFlagForceColor;
22599
+ if (forceColor === 0) {
22600
+ return 0;
22601
+ }
22602
+ if (sniffFlags) {
22603
+ if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) {
22604
+ return 3;
22605
+ }
22606
+ if (hasFlag("color=256")) {
22607
+ return 2;
22608
+ }
22609
+ }
22610
+ if ("TF_BUILD" in env && "AGENT_NAME" in env) {
22611
+ return 1;
22612
+ }
22613
+ if (haveStream && !streamIsTTY && forceColor === void 0) {
22614
+ return 0;
22615
+ }
22616
+ const min = forceColor || 0;
22617
+ if (env.TERM === "dumb") {
22618
+ return min;
22619
+ }
22620
+ if (process5.platform === "win32") {
22621
+ const osRelease = os3.release().split(".");
22622
+ if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
22623
+ return Number(osRelease[2]) >= 14931 ? 3 : 2;
22624
+ }
22625
+ return 1;
22626
+ }
22627
+ if ("CI" in env) {
22628
+ if (["GITHUB_ACTIONS", "GITEA_ACTIONS", "CIRCLECI"].some((key) => key in env)) {
22629
+ return 3;
22630
+ }
22631
+ if (["TRAVIS", "APPVEYOR", "GITLAB_CI", "BUILDKITE", "DRONE"].some((sign) => sign in env) || env.CI_NAME === "codeship") {
22632
+ return 1;
22633
+ }
22634
+ return min;
22635
+ }
22636
+ if ("TEAMCITY_VERSION" in env) {
22637
+ return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
22638
+ }
22639
+ if (env.COLORTERM === "truecolor") {
22640
+ return 3;
22641
+ }
22642
+ if (env.TERM === "xterm-kitty") {
22643
+ return 3;
22644
+ }
22645
+ if (env.TERM === "xterm-ghostty") {
22646
+ return 3;
22647
+ }
22648
+ if (env.TERM === "wezterm") {
22649
+ return 3;
22650
+ }
22651
+ if ("TERM_PROGRAM" in env) {
22652
+ const version3 = Number.parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
22653
+ switch (env.TERM_PROGRAM) {
22654
+ case "iTerm.app": {
22655
+ return version3 >= 3 ? 3 : 2;
22656
+ }
22657
+ case "Apple_Terminal": {
22658
+ return 2;
22659
+ }
22660
+ }
22661
+ }
22662
+ if (/-256(color)?$/i.test(env.TERM)) {
22663
+ return 2;
22664
+ }
22665
+ if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
22666
+ return 1;
22667
+ }
22668
+ if ("COLORTERM" in env) {
22669
+ return 1;
22670
+ }
22671
+ return min;
22672
+ }
22673
+ function createSupportsColor(stream, options = {}) {
22674
+ const level = _supportsColor(stream, {
22675
+ streamIsTTY: stream && stream.isTTY,
22676
+ ...options
22677
+ });
22678
+ return translateLevel(level);
22679
+ }
22680
+ var supportsColor = {
22681
+ stdout: createSupportsColor({ isTTY: tty.isatty(1) }),
22682
+ stderr: createSupportsColor({ isTTY: tty.isatty(2) })
22683
+ };
22684
+ var supports_color_default = supportsColor;
22685
+
22686
+ // node_modules/chalk/source/utilities.js
22687
+ function stringReplaceAll(string4, substring, replacer) {
22688
+ let index = string4.indexOf(substring);
22689
+ if (index === -1) {
22690
+ return string4;
22691
+ }
22692
+ const substringLength = substring.length;
22693
+ let endIndex = 0;
22694
+ let returnValue = "";
22695
+ do {
22696
+ returnValue += string4.slice(endIndex, index) + substring + replacer;
22697
+ endIndex = index + substringLength;
22698
+ index = string4.indexOf(substring, endIndex);
22699
+ } while (index !== -1);
22700
+ returnValue += string4.slice(endIndex);
22701
+ return returnValue;
22702
+ }
22703
+ function stringEncaseCRLFWithFirstIndex(string4, prefix, postfix, index) {
22704
+ let endIndex = 0;
22705
+ let returnValue = "";
22706
+ do {
22707
+ const gotCR = string4[index - 1] === "\r";
22708
+ returnValue += string4.slice(endIndex, gotCR ? index - 1 : index) + prefix + (gotCR ? "\r\n" : "\n") + postfix;
22709
+ endIndex = index + 1;
22710
+ index = string4.indexOf("\n", endIndex);
22711
+ } while (index !== -1);
22712
+ returnValue += string4.slice(endIndex);
22713
+ return returnValue;
22714
+ }
22715
+
22716
+ // node_modules/chalk/source/index.js
22717
+ var { stdout: stdoutColor, stderr: stderrColor } = supports_color_default;
22718
+ var GENERATOR = /* @__PURE__ */ Symbol("GENERATOR");
22719
+ var STYLER = /* @__PURE__ */ Symbol("STYLER");
22720
+ var IS_EMPTY = /* @__PURE__ */ Symbol("IS_EMPTY");
22721
+ var levelMapping = [
22722
+ "ansi",
22723
+ "ansi",
22724
+ "ansi256",
22725
+ "ansi16m"
22726
+ ];
22727
+ var styles2 = /* @__PURE__ */ Object.create(null);
22728
+ var applyOptions = (object2, options = {}) => {
22729
+ if (options.level && !(Number.isInteger(options.level) && options.level >= 0 && options.level <= 3)) {
22730
+ throw new Error("The `level` option should be an integer from 0 to 3");
22731
+ }
22732
+ const colorLevel = stdoutColor ? stdoutColor.level : 0;
22733
+ object2.level = options.level === void 0 ? colorLevel : options.level;
22734
+ };
22735
+ var chalkFactory = (options) => {
22736
+ const chalk2 = (...strings) => strings.join(" ");
22737
+ applyOptions(chalk2, options);
22738
+ Object.setPrototypeOf(chalk2, createChalk.prototype);
22739
+ return chalk2;
22740
+ };
22741
+ function createChalk(options) {
22742
+ return chalkFactory(options);
22743
+ }
22744
+ Object.setPrototypeOf(createChalk.prototype, Function.prototype);
22745
+ for (const [styleName, style] of Object.entries(ansi_styles_default)) {
22746
+ styles2[styleName] = {
22747
+ get() {
22748
+ const builder = createBuilder(this, createStyler(style.open, style.close, this[STYLER]), this[IS_EMPTY]);
22749
+ Object.defineProperty(this, styleName, { value: builder });
22750
+ return builder;
22751
+ }
22752
+ };
22753
+ }
22754
+ styles2.visible = {
22755
+ get() {
22756
+ const builder = createBuilder(this, this[STYLER], true);
22757
+ Object.defineProperty(this, "visible", { value: builder });
22758
+ return builder;
22759
+ }
22760
+ };
22761
+ var getModelAnsi = (model, level, type, ...arguments_) => {
22762
+ if (model === "rgb") {
22763
+ if (level === "ansi16m") {
22764
+ return ansi_styles_default[type].ansi16m(...arguments_);
22765
+ }
22766
+ if (level === "ansi256") {
22767
+ return ansi_styles_default[type].ansi256(ansi_styles_default.rgbToAnsi256(...arguments_));
22768
+ }
22769
+ return ansi_styles_default[type].ansi(ansi_styles_default.rgbToAnsi(...arguments_));
22770
+ }
22771
+ if (model === "hex") {
22772
+ return getModelAnsi("rgb", level, type, ...ansi_styles_default.hexToRgb(...arguments_));
22773
+ }
22774
+ return ansi_styles_default[type][model](...arguments_);
22775
+ };
22776
+ var usedModels = ["rgb", "hex", "ansi256"];
22777
+ for (const model of usedModels) {
22778
+ styles2[model] = {
22779
+ get() {
22780
+ const { level } = this;
22781
+ return function(...arguments_) {
22782
+ const styler = createStyler(getModelAnsi(model, levelMapping[level], "color", ...arguments_), ansi_styles_default.color.close, this[STYLER]);
22783
+ return createBuilder(this, styler, this[IS_EMPTY]);
22784
+ };
22785
+ }
22786
+ };
22787
+ const bgModel = "bg" + model[0].toUpperCase() + model.slice(1);
22788
+ styles2[bgModel] = {
22789
+ get() {
22790
+ const { level } = this;
22791
+ return function(...arguments_) {
22792
+ const styler = createStyler(getModelAnsi(model, levelMapping[level], "bgColor", ...arguments_), ansi_styles_default.bgColor.close, this[STYLER]);
22793
+ return createBuilder(this, styler, this[IS_EMPTY]);
22794
+ };
22795
+ }
22796
+ };
22797
+ }
22798
+ var proto = Object.defineProperties(() => {
22799
+ }, {
22800
+ ...styles2,
22801
+ level: {
22802
+ enumerable: true,
22803
+ get() {
22804
+ return this[GENERATOR].level;
22805
+ },
22806
+ set(level) {
22807
+ this[GENERATOR].level = level;
22808
+ }
22809
+ }
22810
+ });
22811
+ var createStyler = (open, close, parent) => {
22812
+ let openAll;
22813
+ let closeAll;
22814
+ if (parent === void 0) {
22815
+ openAll = open;
22816
+ closeAll = close;
22817
+ } else {
22818
+ openAll = parent.openAll + open;
22819
+ closeAll = close + parent.closeAll;
22820
+ }
22821
+ return {
22822
+ open,
22823
+ close,
22824
+ openAll,
22825
+ closeAll,
22826
+ parent
22827
+ };
22828
+ };
22829
+ var createBuilder = (self, _styler, _isEmpty) => {
22830
+ const builder = (...arguments_) => applyStyle(builder, arguments_.length === 1 ? "" + arguments_[0] : arguments_.join(" "));
22831
+ Object.setPrototypeOf(builder, proto);
22832
+ builder[GENERATOR] = self;
22833
+ builder[STYLER] = _styler;
22834
+ builder[IS_EMPTY] = _isEmpty;
22835
+ return builder;
22836
+ };
22837
+ var applyStyle = (self, string4) => {
22838
+ if (self.level <= 0 || !string4) {
22839
+ return self[IS_EMPTY] ? "" : string4;
22840
+ }
22841
+ let styler = self[STYLER];
22842
+ if (styler === void 0) {
22843
+ return string4;
22844
+ }
22845
+ const { openAll, closeAll } = styler;
22846
+ if (string4.includes("\x1B")) {
22847
+ while (styler !== void 0) {
22848
+ string4 = stringReplaceAll(string4, styler.close, styler.open);
22849
+ styler = styler.parent;
22850
+ }
22851
+ }
22852
+ const lfIndex = string4.indexOf("\n");
22853
+ if (lfIndex !== -1) {
22854
+ string4 = stringEncaseCRLFWithFirstIndex(string4, closeAll, openAll, lfIndex);
22855
+ }
22856
+ return openAll + string4 + closeAll;
22857
+ };
22858
+ Object.defineProperties(createChalk.prototype, styles2);
22859
+ var chalk = createChalk();
22860
+ var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
22861
+ var source_default = chalk;
22862
+
22863
+ // dist/ui.js
22864
+ var ui = {
22865
+ say(text) {
22866
+ process.stdout.write(text);
22867
+ },
22868
+ heading(text) {
22869
+ return `
22870
+ ${source_default.bold(text)}
22871
+ `;
22872
+ },
22873
+ field(label, value) {
22874
+ return ` ${source_default.dim(label.padEnd(LABEL_WIDTH))}${value}
22875
+ `;
22876
+ },
22877
+ ok(text) {
22878
+ return ` ${source_default.green("\u2714")} ${text}
22879
+ `;
22880
+ },
22881
+ bad(text, why) {
22882
+ return ` ${source_default.red("\u2716")} ${text}${why === void 0 ? "" : source_default.dim(` \xB7 ${why}`)}
22883
+ `;
22884
+ },
22885
+ note(text) {
22886
+ return ` ${source_default.dim(text)}
22887
+ `;
22888
+ },
22889
+ waiting(text) {
22890
+ return fancy ? `\r\x1B[K ${source_default.dim(`\u2026 ${text}`)}` : ` ${source_default.dim(`\u2026 ${text}`)}
22891
+ `;
22892
+ },
22893
+ clear() {
22894
+ return fancy ? "\r\x1B[K" : "";
22895
+ },
22896
+ progress({ name, done, total }) {
22897
+ if (!fancy)
22898
+ return ` ${source_default.dim(`\u2026 ${name}`)}
22899
+ `;
22900
+ return `\r\x1B[K ${ui.bar({ done, total })} ${source_default.dim(`${name}\u2026`)}`;
22901
+ },
22902
+ bar({ done, total }) {
22903
+ const filled = Math.round(done / Math.max(total, 1) * BAR_CELLS);
22904
+ return `${source_default.green("\u2588".repeat(filled))}${source_default.dim("\u2591".repeat(BAR_CELLS - filled))}`;
22905
+ },
22906
+ tally({ done, total, noun }) {
22907
+ return ` ${ui.bar({ done, total })} ${source_default.bold(`${done}/${total}`)} ${source_default.dim(noun)}
22908
+ `;
22909
+ },
22910
+ name(text) {
22911
+ return source_default.cyan(text);
22912
+ },
22913
+ link(text) {
22914
+ return source_default.underline(source_default.dim(text));
22915
+ },
22916
+ command(text) {
22917
+ return source_default.yellow(text);
22918
+ },
22919
+ dim(text) {
22920
+ return source_default.dim(text);
22921
+ },
22922
+ attention(text) {
22923
+ return source_default.yellow(text);
22924
+ }
22925
+ };
22926
+ var fancy = process.stdout.isTTY === true;
22927
+ var LABEL_WIDTH = 13;
22928
+ var BAR_CELLS = 10;
22929
+
22366
22930
  // dist/setup.js
22367
22931
  var run2 = promisify2(execFile2);
22368
22932
  var setup = {
@@ -22380,19 +22944,23 @@ var setup = {
22380
22944
  const broken = found.filter((tool) => !tool.ok && repairs[tool.id] !== void 0 && isDue(tool.id));
22381
22945
  if (broken.length === 0)
22382
22946
  return withReasons(found);
22383
- for (const tool of broken) {
22947
+ let ready = 0;
22948
+ for (const [index, tool] of broken.entries()) {
22384
22949
  const repair = repairs[tool.id];
22385
22950
  if (repair === void 0)
22386
22951
  continue;
22387
- say?.(`Setting up ${repair.name}`);
22952
+ say?.(ui.progress({ name: repair.name, done: index, total: broken.length }));
22388
22953
  tried.set(tool.id, Date.now());
22389
22954
  const failed = await repair.fix().then(() => null, (error51) => firstLine2(error51.message));
22390
22955
  if (failed === null)
22391
22956
  reasons.delete(tool.id);
22392
22957
  else
22393
22958
  reasons.set(tool.id, failed);
22394
- say?.(failed === null ? ` ${repair.name} is ready` : ` could not set up ${repair.name}: ${failed}`);
22959
+ if (failed === null)
22960
+ ready += 1;
22961
+ say?.(`${ui.clear()}${failed === null ? ui.ok(repair.name) : ui.bad(repair.name, failed)}`);
22395
22962
  }
22963
+ say?.(ui.tally({ done: ready, total: broken.length, noun: "ready" }));
22396
22964
  return withReasons(await probe.tools());
22397
22965
  }
22398
22966
  };
@@ -22411,8 +22979,8 @@ function toolDirs() {
22411
22979
  return [
22412
22980
  path3.dirname(process.execPath),
22413
22981
  ...prefix === void 0 ? [] : [path3.join(prefix, "bin")],
22414
- path3.join(os3.homedir(), ".local", "bin"),
22415
- path3.join(os3.homedir(), ".npm-global", "bin"),
22982
+ path3.join(os4.homedir(), ".local", "bin"),
22983
+ path3.join(os4.homedir(), ".npm-global", "bin"),
22416
22984
  "/opt/homebrew/bin",
22417
22985
  "/usr/local/bin"
22418
22986
  ];
@@ -22463,11 +23031,58 @@ var reasons = /* @__PURE__ */ new Map();
22463
23031
  var INSTALL_TIMEOUT_MS = 18e4;
22464
23032
  var RETRY_AFTER_MS = 216e5;
22465
23033
 
22466
- // dist/machine.js
23034
+ // dist/update.js
23035
+ import { execFile as execFile3 } from "node:child_process";
23036
+ import { promisify as promisify3 } from "node:util";
22467
23037
  var run3 = promisify3(execFile3);
23038
+ var update = {
23039
+ async latest() {
23040
+ const answer = await fetch(`${REGISTRY}/${CLI_PACKAGE}/latest`, {
23041
+ headers: { accept: "application/json" },
23042
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
23043
+ }).catch(() => null);
23044
+ if (answer === null || !answer.ok)
23045
+ return null;
23046
+ const body = await answer.json().catch(() => null);
23047
+ const version3 = isRecord(body) ? body.version : void 0;
23048
+ return typeof version3 === "string" && isNewer(version3) ? version3 : null;
23049
+ },
23050
+ async toLatest() {
23051
+ const version3 = await update.latest();
23052
+ if (version3 === null)
23053
+ return null;
23054
+ const installed = await run3("npm", ["install", "--global", "--no-fund", `${CLI_PACKAGE}@${version3}`], {
23055
+ timeout: INSTALL_TIMEOUT_MS2
23056
+ }).then(() => true, () => false);
23057
+ return installed ? version3 : null;
23058
+ }
23059
+ };
23060
+ function isNewer(candidate, current = CLI_VERSION) {
23061
+ const mine = parts(current);
23062
+ const theirs = parts(candidate);
23063
+ for (let at = 0; at < 3; at += 1) {
23064
+ const here2 = mine[at] ?? 0;
23065
+ const there = theirs[at] ?? 0;
23066
+ if (there !== here2)
23067
+ return there > here2;
23068
+ }
23069
+ return false;
23070
+ }
23071
+ function parts(version3) {
23072
+ return (/^\d+\.\d+\.\d+/.exec(version3.trim())?.[0] ?? "").split(".").map(Number);
23073
+ }
23074
+ function isRecord(value) {
23075
+ return typeof value === "object" && value !== null;
23076
+ }
23077
+ var REGISTRY = "https://registry.npmjs.org";
23078
+ var REQUEST_TIMEOUT_MS = 1e4;
23079
+ var INSTALL_TIMEOUT_MS2 = 18e4;
23080
+
23081
+ // dist/machine.js
23082
+ var run4 = promisify4(execFile4);
22468
23083
  var machine = {
22469
23084
  home() {
22470
- return process.env.CRAFTSPACE_CLI_HOME ?? path4.join(os4.homedir(), ".craftspace");
23085
+ return process.env.CRAFTSPACE_CLI_HOME ?? path4.join(os5.homedir(), ".craftspace");
22471
23086
  },
22472
23087
  async login({ token, url: url2, install }) {
22473
23088
  const answer = await call({
@@ -22476,11 +23091,11 @@ var machine = {
22476
23091
  method: "POST",
22477
23092
  path: "/api/machines/login",
22478
23093
  body: {
22479
- name: os4.hostname().split(".")[0] ?? "machine",
23094
+ name: os5.hostname().split(".")[0] ?? "machine",
22480
23095
  platform: `${process.platform}-${process.arch}`,
22481
- sshUser: os4.userInfo().username,
22482
- cores: os4.cpus().length,
22483
- memoryGb: Math.max(1, Math.round(os4.totalmem() / 1024 ** 3)),
23096
+ sshUser: os5.userInfo().username,
23097
+ cores: os5.cpus().length,
23098
+ memoryGb: Math.max(1, Math.round(os5.totalmem() / 1024 ** 3)),
22484
23099
  cli: CLI_VERSION,
22485
23100
  publicKey: await ensureKey()
22486
23101
  },
@@ -22493,7 +23108,7 @@ var machine = {
22493
23108
  await installService();
22494
23109
  probed = {
22495
23110
  at: Date.now(),
22496
- tools: await setup.run({ install, rewire, say: (text) => process.stdout.write(text) })
23111
+ tools: await setup.run({ install, rewire, say: ui.say })
22497
23112
  };
22498
23113
  return answer.machine;
22499
23114
  },
@@ -22502,16 +23117,15 @@ var machine = {
22502
23117
  if (!process.stdin.isTTY)
22503
23118
  throw new Error(`${why} Run: craftspace login --token <token>`);
22504
23119
  const page = `${where}/workstations`;
22505
- process.stdout.write(`
22506
- ${why}
23120
+ ui.say(`
23121
+ ${ui.attention(why)}
22507
23122
 
22508
23123
  `);
22509
23124
  if (await dist_default4({ message: `Open ${page} for a key?`, default: true })) {
22510
23125
  await openInBrowser(page);
22511
- process.stdout.write(' Click "Add a workstation" there, then copy the line it gives you.\n');
23126
+ ui.say(ui.note('Click "Add a workstation" there, then copy the line it gives you.'));
22512
23127
  } else {
22513
- process.stdout.write(` Get one at ${page} under "Add a workstation".
22514
- `);
23128
+ ui.say(ui.note(`Get one at ${ui.link(page)} under "Add a workstation".`));
22515
23129
  }
22516
23130
  const token = tokenIn(await dist_default5({
22517
23131
  message: "Paste it here",
@@ -22520,9 +23134,8 @@ ${why}
22520
23134
  if (token === void 0)
22521
23135
  throw new Error("That line carries no key.");
22522
23136
  const signed = await machine.login({ token, url: where, install });
22523
- process.stdout.write(`
22524
- Signed in as ${signed.ownerName}. This machine is ${signed.name}.
22525
- `);
23137
+ ui.say(`
23138
+ ${ui.ok(`Signed in as ${signed.ownerName}. This machine is ${ui.name(signed.name)}.`)}`);
22526
23139
  return { url: where, token, machine: signed };
22527
23140
  },
22528
23141
  async status() {
@@ -22542,7 +23155,7 @@ Signed in as ${signed.ownerName}. This machine is ${signed.name}.
22542
23155
  sessions: await readSessions(),
22543
23156
  runs: drainReports(),
22544
23157
  tools: await tools(),
22545
- sshUser: os4.userInfo().username
23158
+ sshUser: os5.userInfo().username
22546
23159
  },
22547
23160
  schema: MachineBeatResponseSchema
22548
23161
  });
@@ -22558,7 +23171,17 @@ Signed in as ${signed.ownerName}. This machine is ${signed.name}.
22558
23171
  async beatForever() {
22559
23172
  let failures = 0;
22560
23173
  let busy = false;
23174
+ let checkedAt = 0;
22561
23175
  for (; ; ) {
23176
+ if (!busy && Date.now() - checkedAt > UPDATE_EVERY_MS) {
23177
+ checkedAt = Date.now();
23178
+ const moved = await update.toLatest();
23179
+ if (moved !== null) {
23180
+ process.stderr.write(`craftspace ${CLI_VERSION} -> ${moved}, restarting
23181
+ `);
23182
+ return;
23183
+ }
23184
+ }
22562
23185
  try {
22563
23186
  busy = await machine.beatOnce();
22564
23187
  failures = 0;
@@ -22570,21 +23193,32 @@ Signed in as ${signed.ownerName}. This machine is ${signed.name}.
22570
23193
  await new Promise((resolve) => setTimeout(resolve, nextDelayMs(failures, busy)));
22571
23194
  }
22572
23195
  },
23196
+ async update() {
23197
+ ui.say(ui.waiting(`checking ${CLI_PACKAGE}`));
23198
+ const moved = await update.latest();
23199
+ if (moved === null) {
23200
+ ui.say(`${ui.clear()}${ui.ok(`craftspace ${ui.name(CLI_VERSION)}, nothing newer on npm`)}`);
23201
+ return;
23202
+ }
23203
+ ui.say(`${ui.clear()}${ui.waiting(`installing ${moved}`)}`);
23204
+ const done = await update.toLatest();
23205
+ ui.say(`${ui.clear()}${done === null ? ui.bad(`could not install ${moved}`, `run it yourself: ${CLI_INSTALL}@latest`) : ui.ok(`craftspace ${ui.name(CLI_VERSION)} -> ${ui.name(done)}`)}`);
23206
+ },
22573
23207
  async run({ argv, on }) {
22574
23208
  if (on === void 0)
22575
23209
  return runHere(argv);
22576
23210
  return runThere({ argv, on });
22577
23211
  },
22578
- async daemonLine() {
23212
+ async daemon() {
22579
23213
  if (process.env.CRAFTSPACE_NO_SERVICE === "1")
22580
- return `not installed. Start it with: ${here()} daemon`;
23214
+ return { text: `not installed. Start it with: ${here()} daemon`, ok: false };
22581
23215
  if (process.platform !== "linux")
22582
- return BEATING;
23216
+ return { text: BEATING, ok: true };
22583
23217
  if (!await serviceRunning())
22584
- return `not running. Start it with: ${here()} daemon`;
23218
+ return { text: `not running. Start it with: ${here()} daemon`, ok: false };
22585
23219
  if (!await userLingers())
22586
- return `beating, but it stops when you log out. Run: ${LINGER_LINE}`;
22587
- return BEATING;
23220
+ return { text: `beating, but it stops when you log out. Run: ${LINGER_LINE}`, ok: false };
23221
+ return { text: BEATING, ok: true };
22588
23222
  },
22589
23223
  async logout() {
22590
23224
  const config2 = await readConfig();
@@ -22617,7 +23251,7 @@ async function runThere({ argv, on }) {
22617
23251
  const first = await signedInOrAsk();
22618
23252
  const { auth, value: target } = await withAuth(first, (live) => machineNamed({ ...live, name: on }));
22619
23253
  const { url: url2, token } = auth;
22620
- let run4 = await call({
23254
+ let run5 = await call({
22621
23255
  url: url2,
22622
23256
  token,
22623
23257
  method: "POST",
@@ -22625,39 +23259,39 @@ async function runThere({ argv, on }) {
22625
23259
  body: { argv },
22626
23260
  schema: MachineRunSchema
22627
23261
  });
22628
- process.stdout.write(`${target.name} \xB7 queued ${run4.id}
23262
+ ui.say(`${ui.name(target.name)} ${ui.dim(`\xB7 queued ${run5.id}`)}
22629
23263
 
22630
23264
  `);
22631
23265
  let printed = 0;
22632
23266
  for (; ; ) {
22633
- if (run4.output.length > printed) {
22634
- process.stdout.write(run4.output.slice(printed));
22635
- printed = run4.output.length;
23267
+ if (run5.output.length > printed) {
23268
+ process.stdout.write(run5.output.slice(printed));
23269
+ printed = run5.output.length;
22636
23270
  }
22637
- if (run4.state === "done")
23271
+ if (run5.state === "done")
22638
23272
  return 0;
22639
- if (run4.state === "failed")
22640
- return run4.exitCode ?? 1;
22641
- if (run4.state === "needs_input") {
22642
- process.stdout.write(`
22643
- ${target.name} is asking: ${run4.question ?? "it needs a decision"}
23273
+ if (run5.state === "failed")
23274
+ return run5.exitCode ?? 1;
23275
+ if (run5.state === "needs_input") {
23276
+ ui.say(`
23277
+ ${ui.attention(`${target.name} is asking:`)} ${run5.question ?? "it needs a decision"}
22644
23278
  > `);
22645
23279
  const reply = await readStdinLine();
22646
23280
  if (reply === null)
22647
23281
  return 130;
22648
- run4 = await call({
23282
+ run5 = await call({
22649
23283
  url: url2,
22650
23284
  token,
22651
23285
  method: "POST",
22652
- path: `/api/machines/runs/${run4.id}/answer`,
23286
+ path: `/api/machines/runs/${run5.id}/answer`,
22653
23287
  body: { text: reply },
22654
23288
  schema: MachineRunSchema
22655
23289
  });
22656
- printed = run4.output.length;
23290
+ printed = run5.output.length;
22657
23291
  continue;
22658
23292
  }
22659
23293
  await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
22660
- run4 = await readRun({ url: url2, token, machineId: target.id, runId: run4.id });
23294
+ run5 = await readRun({ url: url2, token, machineId: target.id, runId: run5.id });
22661
23295
  }
22662
23296
  }
22663
23297
  async function readRun({ url: url2, token, machineId, runId }) {
@@ -22683,8 +23317,8 @@ async function machineNamed({ url: url2, token, name }) {
22683
23317
  if (!process.stdin.isTTY) {
22684
23318
  throw new Error(`No workstation called ${name}. This team has: ${answer.machines.map((m) => m.name).join(", ")}`);
22685
23319
  }
22686
- process.stdout.write(`
22687
- No workstation called ${name}.
23320
+ ui.say(`
23321
+ ${ui.attention(`No workstation called ${name}.`)}
22688
23322
 
22689
23323
  `);
22690
23324
  return dist_default6({
@@ -22746,7 +23380,7 @@ async function call({ url: url2, token, method, path: route, body, schema }) {
22746
23380
  ...body === void 0 ? {} : { "content-type": "application/json" }
22747
23381
  },
22748
23382
  ...body === void 0 ? {} : { body: JSON.stringify(body) },
22749
- signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
23383
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS2)
22750
23384
  });
22751
23385
  if (response.status === 401)
22752
23386
  throw new Unauthorized();
@@ -22776,13 +23410,15 @@ async function withAuth(auth, work) {
22776
23410
  url: auth.url,
22777
23411
  why: "Craftspace does not know this machine any more. Its key was revoked, which is what forgetting the workstation, or signing the same box in somewhere else, does."
22778
23412
  });
22779
- process.stdout.write("\nPicking up where you left off.\n\n");
23413
+ ui.say(`
23414
+ ${ui.note("Picking up where you left off.")}
23415
+ `);
22780
23416
  return { auth: next, value: await work(next) };
22781
23417
  }
22782
23418
  }
22783
23419
  async function openInBrowser(url2) {
22784
23420
  const opener = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
22785
- await run3(opener, [url2]).catch(() => void 0);
23421
+ await run4(opener, [url2]).catch(() => void 0);
22786
23422
  }
22787
23423
  function tokenIn(line) {
22788
23424
  return /cst_[A-Za-z0-9_-]+/.exec(line)?.[0];
@@ -22794,7 +23430,7 @@ async function ensureKey() {
22794
23430
  if (existing !== null)
22795
23431
  return existing.trim();
22796
23432
  await mkdir(machine.home(), { recursive: true, mode: 448 });
22797
- await run3("ssh-keygen", ["-t", "ed25519", "-N", "", "-q", "-f", priv, "-C", `craftspace-${os4.hostname()}`]);
23433
+ await run4("ssh-keygen", ["-t", "ed25519", "-N", "", "-q", "-f", priv, "-C", `craftspace-${os5.hostname()}`]);
22798
23434
  return (await readFile2(pub, "utf8")).trim();
22799
23435
  }
22800
23436
  async function readConfig() {
@@ -22822,7 +23458,7 @@ async function readSessions() {
22822
23458
  return sessions.slice(0, MAX_REPORTED_SESSIONS);
22823
23459
  }
22824
23460
  async function writeAuthorizedKeys(keys) {
22825
- const target = path4.join(os4.homedir(), ".ssh", "authorized_keys");
23461
+ const target = path4.join(os5.homedir(), ".ssh", "authorized_keys");
22826
23462
  const current = await readFile2(target, "utf8").catch(() => "");
22827
23463
  const before = current.split(KEYS_BEGIN)[0] ?? "";
22828
23464
  const after = current.includes(KEYS_END) ? current.split(KEYS_END)[1] ?? "" : "";
@@ -22868,20 +23504,20 @@ function serversIn(writes) {
22868
23504
  return writes.flatMap((write) => isPlainObject3(write.contents.mcpServers) ? Object.keys(write.contents.mcpServers) : []);
22869
23505
  }
22870
23506
  async function acceptClaudeGates(servers) {
22871
- const target = path4.join(os4.homedir(), ".claude.json");
23507
+ const target = path4.join(os5.homedir(), ".claude.json");
22872
23508
  const raw = await readFile2(target, "utf8").catch(() => null);
22873
23509
  if (raw === null)
22874
23510
  return;
22875
23511
  const parsed = JSON.parse(raw);
22876
23512
  const projects = isPlainObject3(parsed.projects) ? parsed.projects : {};
22877
- const found = projects[os4.homedir()];
23513
+ const found = projects[os5.homedir()];
22878
23514
  const here2 = isPlainObject3(found) ? { ...found } : {};
22879
23515
  const enabled = /* @__PURE__ */ new Set([...Array.isArray(here2.enabledMcpjsonServers) ? here2.enabledMcpjsonServers : [], ...servers]);
22880
23516
  if (here2.hasTrustDialogAccepted === true && enabled.size === asArray(here2.enabledMcpjsonServers).length)
22881
23517
  return;
22882
23518
  here2.hasTrustDialogAccepted = true;
22883
23519
  here2.enabledMcpjsonServers = [...enabled];
22884
- const next = { ...parsed, projects: { ...projects, [os4.homedir()]: here2 } };
23520
+ const next = { ...parsed, projects: { ...projects, [os5.homedir()]: here2 } };
22885
23521
  await writeFile(target, `${JSON.stringify(next, null, 2)}
22886
23522
  `, { mode: 384 });
22887
23523
  }
@@ -22932,31 +23568,31 @@ async function installService() {
22932
23568
  if (process.env.CRAFTSPACE_NO_SERVICE === "1")
22933
23569
  return;
22934
23570
  if (process.platform === "linux") {
22935
- const dir = path4.join(os4.homedir(), ".config", "systemd", "user");
23571
+ const dir = path4.join(os5.homedir(), ".config", "systemd", "user");
22936
23572
  await mkdir(dir, { recursive: true });
22937
23573
  await writeFile(path4.join(dir, `${SERVICE_NAME}.service`), systemdUnit());
22938
- await run3("loginctl", ["enable-linger", os4.userInfo().username]).catch(() => void 0);
22939
- await run3("systemctl", ["--user", "daemon-reload"]).catch(() => void 0);
22940
- await run3("systemctl", ["--user", "enable", "--now", SERVICE_NAME]).catch(() => void 0);
23574
+ await run4("loginctl", ["enable-linger", os5.userInfo().username]).catch(() => void 0);
23575
+ await run4("systemctl", ["--user", "daemon-reload"]).catch(() => void 0);
23576
+ await run4("systemctl", ["--user", "enable", "--now", SERVICE_NAME]).catch(() => void 0);
22941
23577
  return;
22942
23578
  }
22943
23579
  if (process.platform === "darwin") {
22944
- const target = path4.join(os4.homedir(), "Library", "LaunchAgents", `${LAUNCH_LABEL}.plist`);
23580
+ const target = path4.join(os5.homedir(), "Library", "LaunchAgents", `${LAUNCH_LABEL}.plist`);
22945
23581
  await mkdir(path4.dirname(target), { recursive: true });
22946
23582
  await writeFile(target, launchdPlist());
22947
- await run3("launchctl", ["unload", target]).catch(() => void 0);
22948
- await run3("launchctl", ["load", target]).catch(() => void 0);
23583
+ await run4("launchctl", ["unload", target]).catch(() => void 0);
23584
+ await run4("launchctl", ["load", target]).catch(() => void 0);
22949
23585
  }
22950
23586
  }
22951
23587
  async function uninstallService() {
22952
23588
  if (process.platform === "linux") {
22953
- await run3("systemctl", ["--user", "disable", "--now", SERVICE_NAME]).catch(() => void 0);
22954
- await rm(path4.join(os4.homedir(), ".config", "systemd", "user", `${SERVICE_NAME}.service`), { force: true });
23589
+ await run4("systemctl", ["--user", "disable", "--now", SERVICE_NAME]).catch(() => void 0);
23590
+ await rm(path4.join(os5.homedir(), ".config", "systemd", "user", `${SERVICE_NAME}.service`), { force: true });
22955
23591
  return;
22956
23592
  }
22957
23593
  if (process.platform === "darwin") {
22958
- const target = path4.join(os4.homedir(), "Library", "LaunchAgents", `${LAUNCH_LABEL}.plist`);
22959
- await run3("launchctl", ["unload", target]).catch(() => void 0);
23594
+ const target = path4.join(os5.homedir(), "Library", "LaunchAgents", `${LAUNCH_LABEL}.plist`);
23595
+ await run4("launchctl", ["unload", target]).catch(() => void 0);
22960
23596
  await rm(target, { force: true });
22961
23597
  }
22962
23598
  }
@@ -22993,17 +23629,17 @@ function here() {
22993
23629
  return `${process.execPath} ${entryPath()}`;
22994
23630
  }
22995
23631
  async function serviceRunning() {
22996
- return await run3("systemctl", ["--user", "is-active", SERVICE_NAME]).catch(() => null) !== null;
23632
+ return await run4("systemctl", ["--user", "is-active", SERVICE_NAME]).catch(() => null) !== null;
22997
23633
  }
22998
23634
  async function userLingers() {
22999
- const shown = await run3("loginctl", ["show-user", os4.userInfo().username, "-p", "Linger"]).catch(() => null);
23635
+ const shown = await run4("loginctl", ["show-user", os5.userInfo().username, "-p", "Linger"]).catch(() => null);
23000
23636
  return shown?.stdout.includes("Linger=yes") === true;
23001
23637
  }
23002
23638
  function entryPath() {
23003
23639
  return path4.join(path4.dirname(new URL(import.meta.url).pathname), "index.js");
23004
23640
  }
23005
23641
  function expand(target) {
23006
- return target.startsWith("~/") ? path4.join(os4.homedir(), target.slice(2)) : target;
23642
+ return target.startsWith("~/") ? path4.join(os5.homedir(), target.slice(2)) : target;
23007
23643
  }
23008
23644
  function configPath() {
23009
23645
  return path4.join(machine.home(), "config.json");
@@ -23015,9 +23651,9 @@ function ownedPath() {
23015
23651
  return path4.join(machine.home(), "owned.json");
23016
23652
  }
23017
23653
  function load2() {
23018
- const cores = Math.max(1, os4.cpus().length);
23019
- const busy = Math.min(100, (os4.loadavg()[0] ?? 0) / cores * 100);
23020
- const used = (os4.totalmem() - os4.freemem()) / os4.totalmem() * 100;
23654
+ const cores = Math.max(1, os5.cpus().length);
23655
+ const busy = Math.min(100, (os5.loadavg()[0] ?? 0) / cores * 100);
23656
+ const used = (os5.totalmem() - os5.freemem()) / os5.totalmem() * 100;
23021
23657
  return { cpuPercent: Math.round(busy), memoryPercent: Math.round(used) };
23022
23658
  }
23023
23659
  function nextDelayMs(failures, busy = false) {
@@ -23035,14 +23671,15 @@ var ConfigSchema = external_exports.object({ url: external_exports.string(), mac
23035
23671
  var OwnedSchema = external_exports.object({ paths: external_exports.array(external_exports.string()) });
23036
23672
  var SERVICE_NAME = "craftspace";
23037
23673
  var LAUNCH_LABEL = "app.craftspace.machine";
23038
- var REQUEST_TIMEOUT_MS = 15e3;
23674
+ var REQUEST_TIMEOUT_MS2 = 15e3;
23039
23675
  var MAX_REPORTED_SESSIONS = 50;
23040
23676
  var MAX_BACKOFF_MS = 12e4;
23041
23677
  var KEYS_BEGIN = "# craftspace begin";
23042
23678
  var KEYS_END = "# craftspace end";
23043
23679
  var POLL_INTERVAL_MS = 1e3;
23680
+ var UPDATE_EVERY_MS = 6 * 60 * 60 * 1e3;
23044
23681
  var BEATING = "beating every 15s, outbound only, and keeps this set up";
23045
- var LINGER_LINE = `sudo loginctl enable-linger ${os4.userInfo().username}`;
23682
+ var LINGER_LINE = `sudo loginctl enable-linger ${os5.userInfo().username}`;
23046
23683
  var DEFAULT_URL = process.env.CRAFTSPACE_URL ?? "https://craftspace.app";
23047
23684
  var PROBE_EVERY_MS = 3e5;
23048
23685
  var probed = null;
@@ -23056,15 +23693,14 @@ program2.enablePositionalOptions().name("craftspace").description("Sign this mac
23056
23693
  program2.command("login").description("sign this machine in").option("--token <token>", "the login token from your team", process.env.CRAFTSPACE_TOKEN).option("--url <url>", "your control plane", process.env.CRAFTSPACE_URL ?? "https://craftspace.app").option("--no-install", "do not install anything this machine is missing").action(async ({ token, url: url2, install }) => {
23057
23694
  const where = url2.replace(/\/$/, "");
23058
23695
  const signed = token === void 0 ? (await machine.signIn({ url: where, why: "Signing this machine in.", install })).machine : await machine.login({ token, url: where, install });
23059
- process.stdout.write([
23060
- `Signed in as ${signed.ownerName}`,
23061
- `Machine ${signed.name} \xB7 ${signed.platform} \xB7 ${signed.cores ?? "?"} vCPU`,
23062
- "MCP wired ~/.mcp.json",
23063
- `Daemon ${await machine.daemonLine()}`,
23064
- "",
23065
- `Listed at ${url2.replace(/\/$/, "")}/workstations`,
23066
- ""
23067
- ].join("\n"));
23696
+ const daemon = await machine.daemon();
23697
+ ui.say(ui.heading(`Signed in as ${signed.ownerName}`));
23698
+ ui.say(ui.field("Machine", `${ui.name(signed.name)} ${ui.dim(machineSpecs(signed))}`));
23699
+ ui.say(ui.field("MCP wired", "~/.mcp.json"));
23700
+ ui.say(ui.field("Daemon", daemon.ok ? daemon.text : ui.attention(daemon.text)));
23701
+ ui.say(`
23702
+ ${ui.note(`Listed at ${ui.link(`${where}/workstations`)}`)}
23703
+ `);
23068
23704
  });
23069
23705
  program2.command("run").description("run a command here, or on another workstation with --on").argument("<command...>", "the command line to run").option("--on <machine>", "run it on that workstation instead of this one").allowUnknownOption().passThroughOptions().action(async (command, { on }) => {
23070
23706
  process.exitCode = await machine.run({ argv: command, ...on === void 0 ? {} : { on } });
@@ -23072,26 +23708,31 @@ program2.command("run").description("run a command here, or on another workstati
23072
23708
  program2.command("status").description("what this machine is and what it is doing").action(async () => {
23073
23709
  const { machine: found } = await machine.status();
23074
23710
  const since = found.lastBeatAt === null ? "never" : `${secondsSince(found.lastBeatAt)}s ago`;
23075
- process.stdout.write([
23076
- `${found.name} ${found.state} cli ${found.cli} beat ${since}`,
23077
- ` owner ${found.ownerName}`,
23078
- ` machine ${found.platform} \xB7 ${found.cores ?? "?"} vCPU \xB7 ${found.memoryGb ?? "?"} GB`,
23079
- ...found.sessions.map((session) => ` session ${session.state} ${session.title ?? session.id}`),
23080
- ""
23081
- ].join("\n"));
23711
+ ui.say(ui.heading(`${found.name} ${found.state}`));
23712
+ ui.say(ui.field("Owner", found.ownerName));
23713
+ ui.say(ui.field("Machine", ui.dim(machineSpecs(found))));
23714
+ ui.say(ui.field("CLI", `${found.cli}, beat ${since}`));
23715
+ for (const session of found.sessions)
23716
+ ui.say(ui.field("Session", `${session.state} ${session.title ?? session.id}`));
23717
+ ui.say("\n");
23718
+ });
23719
+ program2.command("update").description("move this machine to the latest craftspace CLI").action(async () => {
23720
+ await machine.update();
23082
23721
  });
23083
23722
  program2.command("logout").description("leave the team, and undo what login wrote").action(async () => {
23084
23723
  await machine.logout();
23085
- process.stdout.write("Left the team. Nothing of ours is running here.\n");
23724
+ ui.say(ui.ok("Left the team. Nothing of ours is running here."));
23086
23725
  });
23087
23726
  program2.command("daemon", { hidden: true }).action(async () => machine.beatForever());
23088
23727
  try {
23089
23728
  await program2.parseAsync(process.argv);
23090
23729
  } catch (error51) {
23091
- process.stderr.write(`${error51 instanceof Error ? error51.message : String(error51)}
23092
- `);
23730
+ ui.say(ui.bad(error51 instanceof Error ? error51.message : String(error51)));
23093
23731
  process.exit(1);
23094
23732
  }
23733
+ function machineSpecs({ platform, cores, memoryGb }) {
23734
+ return [platform, cores === null ? null : `${cores} vCPU`, memoryGb == null ? null : `${memoryGb} GB`].filter((part) => part !== null).join(" \xB7 ");
23735
+ }
23095
23736
  function secondsSince(at) {
23096
23737
  return Math.round((Date.now() - new Date(at).getTime()) / 1e3);
23097
23738
  }