@zeroxyz/cli 1.14.0 → 1.14.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 (2) hide show
  1. package/dist/index.js +101 -43
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -78576,7 +78576,7 @@ init_esm_shims();
78576
78576
 
78577
78577
  // package.json
78578
78578
  var package_default = {
78579
- version: "1.14.0"};
78579
+ version: "1.14.1"};
78580
78580
 
78581
78581
  // src/app.ts
78582
78582
  init_esm_shims();
@@ -149881,6 +149881,7 @@ var SKILL_DIRS = [".claude/skills", ".agents/skills"];
149881
149881
  var CLAUDE_SETTINGS_PATH = ".claude/settings.json";
149882
149882
  var CODEX_HOOKS_PATH = ".codex/hooks.json";
149883
149883
  var CLI_VERSION = package_default.version;
149884
+ var installStepTimeoutMs = () => Number(process.env.ZERO_INIT_STEP_TIMEOUT_MS ?? 12e4);
149884
149885
  var STANDALONE = "standalone";
149885
149886
  var unique = (items) => [...new Set(items)];
149886
149887
  var buildSelection = (standalone, matrixIds) => {
@@ -149903,7 +149904,13 @@ var commandOutput = (result) => {
149903
149904
  return chunks.join("\n").trim();
149904
149905
  };
149905
149906
  var commandErrorDetail = (result, fallback2) => {
149906
- if (result.error) return result.error.message;
149907
+ if (result.error) {
149908
+ const code = result.error.code;
149909
+ if (code === "ETIMEDOUT") {
149910
+ return `${fallback2} timed out after ${installStepTimeoutMs() / 1e3}s (is it waiting for interactive input?)`;
149911
+ }
149912
+ return result.error.message;
149913
+ }
149907
149914
  const output = commandOutput(result);
149908
149915
  if (output.length > 0) return truncateError(output);
149909
149916
  if (result.signal) return `${fallback2} exited via signal ${result.signal}`;
@@ -149945,7 +149952,8 @@ var installAgentPlugin = (entry, method, options) => {
149945
149952
  const result = spawnSync(step.command, step.args, {
149946
149953
  encoding: "utf8",
149947
149954
  stdio: "pipe",
149948
- env: process.env
149955
+ env: process.env,
149956
+ timeout: installStepTimeoutMs()
149949
149957
  });
149950
149958
  if (result.status === 0) continue;
149951
149959
  const detail = commandErrorDetail(result, step.label);
@@ -150083,9 +150091,13 @@ var buildHookTargets = (entries) => {
150083
150091
  };
150084
150092
  var runStandaloneInit = async (appContext, options = {}) => {
150085
150093
  const verbose = options.verbose ?? false;
150094
+ const includeDefaultSkillDirs = options.includeDefaultSkillDirs ?? true;
150095
+ const requireHookScripts = options.requireHookScripts ?? true;
150086
150096
  options.onStep?.("fetch");
150087
150097
  console.log("");
150088
- console.log(` ${color.boldCyan("Installing standalone Zero fallback")}`);
150098
+ console.log(
150099
+ ` ${color.boldCyan(options.title ?? "Installing standalone Zero fallback")}`
150100
+ );
150089
150101
  console.log("");
150090
150102
  console.log(color.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
150091
150103
  console.log("");
@@ -150095,33 +150107,39 @@ var runStandaloneInit = async (appContext, options = {}) => {
150095
150107
  const hookScriptNames = unique(
150096
150108
  hookTargets.flatMap((target) => fragmentScriptNames(target.fragment))
150097
150109
  );
150098
- if (hookScriptNames.length === 0) {
150110
+ if (hookScriptNames.length === 0 && requireHookScripts) {
150099
150111
  throw new Error(
150100
150112
  "the agent matrix declared no standalone hook scripts to install"
150101
150113
  );
150102
150114
  }
150103
- const skillMd = await fetchText(`${webBase}/SKILL.md`);
150104
- if (verbose) {
150105
- stepInfo(`fetched ${webBase}/SKILL.md`);
150106
- }
150107
- options.onStep?.("skill");
150108
150115
  const skillsDirs = unique([
150109
- ...SKILL_DIRS.map((dir) => join(home, dir)),
150116
+ ...includeDefaultSkillDirs ? SKILL_DIRS.map((dir) => join(home, dir)) : [],
150110
150117
  ...(options.skillsDir ?? []).map((dir) => expandHome(dir, home))
150111
150118
  ]);
150112
- const skillsInstalled = installSkill(skillsDirs, skillMd, verbose);
150113
- if (skillsInstalled.length === 0) {
150114
- throw new Error("could not write the Zero skill to any skills directory");
150119
+ let skillsInstalled = [];
150120
+ if (skillsDirs.length > 0) {
150121
+ const skillMd = await fetchText(`${webBase}/SKILL.md`);
150122
+ if (verbose) {
150123
+ stepInfo(`fetched ${webBase}/SKILL.md`);
150124
+ }
150125
+ options.onStep?.("skill");
150126
+ skillsInstalled = installSkill(skillsDirs, skillMd, verbose);
150127
+ if (skillsInstalled.length === 0) {
150128
+ throw new Error("could not write the Zero skill to any skills directory");
150129
+ }
150130
+ stepSuccess("Skill installed", `${skillsInstalled.length} locations`);
150115
150131
  }
150116
- stepSuccess("Skill installed", `${skillsInstalled.length} locations`);
150117
150132
  options.onStep?.("hooks");
150118
- const hookScriptsInstalled = await installHookScripts(
150119
- home,
150120
- hookScriptNames,
150121
- webBase,
150122
- verbose
150123
- );
150124
- stepSuccess("Hook scripts installed", "~/.zero/hooks");
150133
+ let hookScriptsInstalled = [];
150134
+ if (hookScriptNames.length > 0) {
150135
+ hookScriptsInstalled = await installHookScripts(
150136
+ home,
150137
+ hookScriptNames,
150138
+ webBase,
150139
+ verbose
150140
+ );
150141
+ stepSuccess("Hook scripts installed", "~/.zero/hooks");
150142
+ }
150125
150143
  options.onStep?.("settings");
150126
150144
  const registeredFiles = /* @__PURE__ */ new Set();
150127
150145
  for (const target of hookTargets) {
@@ -150183,7 +150201,6 @@ var runInit = async (appContext, options = {}) => {
150183
150201
  entries.map((entry) => entry.id)
150184
150202
  );
150185
150203
  const requestedAgents = selection.requestedAgents;
150186
- console.log(` Requested agents: ${requestedAgents.join(", ")}`);
150187
150204
  if (dryRun) stepInfo("dry run: no plugin commands or file writes will run");
150188
150205
  const detections = selection.kind === "standalone" ? [] : selection.pluginAgents.flatMap((id) => {
150189
150206
  const entry = entryById.get(id);
@@ -150198,7 +150215,10 @@ var runInit = async (appContext, options = {}) => {
150198
150215
  console.log("");
150199
150216
  const fallbackSkillDirs = [];
150200
150217
  const standaloneOnlyAgents = [];
150218
+ const standaloneNeedAgents = [];
150219
+ const hasStandaloneBits = (entry) => (entry.standalone?.skills ?? []).length > 0 || Boolean(entry.standalone?.hooks?.merge);
150201
150220
  const pluginResults = [];
150221
+ let undetectedCount = 0;
150202
150222
  for (const detection of detections) {
150203
150223
  const { entry, present, exeCallable, method } = detection;
150204
150224
  if (present && exeCallable && method) {
@@ -150210,12 +150230,14 @@ var runInit = async (appContext, options = {}) => {
150210
150230
  stepSkip(`${entry.name}: ${statusLabel(result2)}`, result2.detail);
150211
150231
  } else {
150212
150232
  stepWarn(`${entry.name}: ${statusLabel(result2)}`, result2.detail);
150233
+ if (hasStandaloneBits(entry)) standaloneNeedAgents.push(entry);
150213
150234
  }
150214
150235
  continue;
150215
150236
  }
150216
150237
  if (present && !method) {
150217
- if ((entry.standalone?.skills ?? []).length > 0) {
150238
+ if (hasStandaloneBits(entry)) {
150218
150239
  standaloneOnlyAgents.push(entry);
150240
+ standaloneNeedAgents.push(entry);
150219
150241
  } else {
150220
150242
  const result2 = {
150221
150243
  agent: entry.id,
@@ -150236,13 +150258,26 @@ var runInit = async (appContext, options = {}) => {
150236
150258
  detail
150237
150259
  };
150238
150260
  pluginResults.push(result);
150239
- stepSkip(`${entry.name}: ${statusLabel(result)}`, result.detail);
150261
+ if (present) {
150262
+ stepSkip(`${entry.name}: ${statusLabel(result)}`, result.detail);
150263
+ } else if (verbose) {
150264
+ stepSkip(`${entry.name}: not detected`, result.detail);
150265
+ } else {
150266
+ undetectedCount += 1;
150267
+ }
150240
150268
  if (present && !exeCallable) {
150241
150269
  for (const dir of entry.standalone?.skills ?? []) {
150242
150270
  fallbackSkillDirs.push(join(home, dir));
150243
150271
  }
150272
+ if (hasStandaloneBits(entry)) standaloneNeedAgents.push(entry);
150244
150273
  }
150245
150274
  }
150275
+ if (undetectedCount > 0) {
150276
+ stepSkip(
150277
+ `${undetectedCount} other supported ${undetectedCount === 1 ? "harness" : "harnesses"} not detected`,
150278
+ "run with --verbose to list them"
150279
+ );
150280
+ }
150246
150281
  const standaloneOnlyDirs = unique(
150247
150282
  standaloneOnlyAgents.flatMap(
150248
150283
  (entry) => (entry.standalone?.skills ?? []).map((dir) => join(home, dir))
@@ -150304,39 +150339,55 @@ var runInit = async (appContext, options = {}) => {
150304
150339
  console.log(
150305
150340
  " Standalone fallback not used: at least one harness plugin install succeeded."
150306
150341
  );
150307
- if (standaloneOnlyDirs.length > 0) {
150308
- currentStep = "skill";
150309
- if (dryRun) {
150310
- for (const dir of standaloneOnlyDirs) {
150342
+ if (standaloneNeedAgents.length > 0) {
150343
+ const needNames = standaloneNeedAgents.map((entry) => entry.id).join(", ");
150344
+ const needDirs = unique(
150345
+ standaloneNeedAgents.flatMap(
150346
+ (entry) => (entry.standalone?.skills ?? []).map((dir) => join(home, dir))
150347
+ )
150348
+ );
150349
+ const needTargets = buildHookTargets(standaloneNeedAgents);
150350
+ if (!fallbackAllowed) {
150351
+ stepSkip(
150352
+ `--no-fallback: skipping standalone install for ${needNames}`
150353
+ );
150354
+ } else if (dryRun) {
150355
+ for (const dir of needDirs) {
150311
150356
  stepInfo(`would install/update ${join(dir, "zero")}`);
150312
150357
  }
150358
+ for (const target of needTargets) {
150359
+ stepInfo(
150360
+ `would register standalone hooks in ~/${target.relativePath}`
150361
+ );
150362
+ }
150313
150363
  } else {
150314
- const skillMd = await fetchText(
150315
- `${appContext.env.ZERO_WEB_URL}/SKILL.md`
150316
- );
150317
- const installed = installSkill(standaloneOnlyDirs, skillMd, verbose);
150318
- standaloneResult = {
150319
- ...standaloneResult,
150320
- skillsInstalled: installed
150321
- };
150364
+ standaloneResult = await runStandaloneInit(appContext, {
150365
+ verbose,
150366
+ skillsDir: unique([...options.skillsDir ?? [], ...needDirs]),
150367
+ includeDefaultSkillDirs: false,
150368
+ hookTargets: needTargets,
150369
+ requireHookScripts: false,
150370
+ title: `Installing standalone Zero for: ${needNames}`,
150371
+ onStep: (step) => {
150372
+ currentStep = step;
150373
+ }
150374
+ });
150322
150375
  }
150323
150376
  }
150324
150377
  }
150325
150378
  for (const entry of standaloneOnlyAgents) {
150379
+ const what = entry.standalone?.hooks?.merge ? "standalone skill + hooks" : "standalone skill";
150326
150380
  const result = {
150327
150381
  agent: entry.id,
150328
150382
  displayName: entry.name,
150329
150383
  status: dryRun ? "would_install" : "installed",
150330
- detail: "standalone skill (no plugin for this harness)"
150384
+ detail: `${what} (no plugin for this harness)`
150331
150385
  };
150332
150386
  pluginResults.push(result);
150333
150387
  if (dryRun) {
150334
- stepSkip(
150335
- `${entry.name}: would install standalone skill`,
150336
- result.detail
150337
- );
150388
+ stepSkip(`${entry.name}: would install ${what}`, result.detail);
150338
150389
  } else {
150339
- stepSuccess(`${entry.name}: standalone skill installed`, result.detail);
150390
+ stepSuccess(`${entry.name}: ${what} installed`, result.detail);
150340
150391
  }
150341
150392
  }
150342
150393
  currentStep = "complete";
@@ -150369,6 +150420,13 @@ var runInit = async (appContext, options = {}) => {
150369
150420
  });
150370
150421
  sectionDivider();
150371
150422
  console.log(` ${color.boldGreen("Zero init complete.")}`);
150423
+ const skillPath = standaloneResult.skillsInstalled[0];
150424
+ if (skillPath) {
150425
+ console.log(` ${color.dim(`Skill installed at: ${skillPath}`)}`);
150426
+ console.log(
150427
+ ` ${color.dim("Agents: read that file now to use Zero in this session \u2014 future sessions load it automatically.")}`
150428
+ );
150429
+ }
150372
150430
  console.log(
150373
150431
  ` ${color.dim("Next: sign in with `zero auth login` \u2014 it prints a URL to approve in your browser.")}`
150374
150432
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeroxyz/cli",
3
- "version": "1.14.0",
3
+ "version": "1.14.1",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "zero": "dist/index.js",