@zeroxyz/cli 1.4.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +299 -43
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import * as nc from 'crypto';
6
6
  import nc__default, { randomUUID, randomBytes as randomBytes$1, createHash } from 'crypto';
7
7
  import os, { homedir } from 'os';
8
8
  import y2, { stdin, stdout } from 'process';
9
- import childProcess, { execFile as execFile$1 } from 'child_process';
9
+ import childProcess, { execFile as execFile$1, spawnSync } from 'child_process';
10
10
  import fs5, { constants } from 'fs/promises';
11
11
  import util2, { promisify } from 'util';
12
12
  import fs3, { createReadStream, existsSync, readFileSync, mkdirSync, writeFileSync, chmodSync, lstatSync, readlinkSync, rmSync, readdirSync } from 'fs';
@@ -76582,7 +76582,7 @@ init_esm_shims();
76582
76582
 
76583
76583
  // package.json
76584
76584
  var package_default = {
76585
- version: "1.4.0"};
76585
+ version: "1.6.0"};
76586
76586
 
76587
76587
  // src/app.ts
76588
76588
  init_esm_shims();
@@ -77563,6 +77563,18 @@ var authExchangeCommand = (appContext) => new Command("exchange").description(
77563
77563
  process.exitCode = 1;
77564
77564
  }
77565
77565
  });
77566
+ var ensureAuthenticated = async (client, shouldOpen = true) => {
77567
+ const session4 = readConfig(getConfigPath()).session;
77568
+ if (session4) return;
77569
+ process.stdout.write(
77570
+ "\nZero requires authentication before handing off to Claude.\n\n"
77571
+ );
77572
+ await runInteractive(client, shouldOpen);
77573
+ if (!readConfig(getConfigPath()).session) {
77574
+ process.exitCode = 1;
77575
+ process.exit(1);
77576
+ }
77577
+ };
77566
77578
  var authCommand = (appContext) => {
77567
77579
  const cmd = new Command("auth").description("Authentication commands");
77568
77580
  cmd.addCommand(authLoginCommand(appContext));
@@ -77578,7 +77590,7 @@ init_esm_shims();
77578
77590
  // ../sdk/dist/index.js
77579
77591
  init_esm_shims();
77580
77592
 
77581
- // ../sdk/dist/chunk-RPL7VC32.js
77593
+ // ../sdk/dist/chunk-RY3VFSIE.js
77582
77594
  init_esm_shims();
77583
77595
 
77584
77596
  // ../../node_modules/.pnpm/viem@2.52.2_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@6.0.6_zod@4.3.6/node_modules/viem/_esm/index.js
@@ -144080,7 +144092,7 @@ var Payments = class {
144080
144092
  };
144081
144093
  };
144082
144094
  var package_default2 = {
144083
- version: "0.4.0"
144095
+ version: "0.5.0"
144084
144096
  };
144085
144097
  var SDK_VERSION2 = package_default2.version;
144086
144098
  var userWalletDtoSchema = external_exports3.object({
@@ -144726,6 +144738,11 @@ var capabilityResponseSchema = external_exports3.object({
144726
144738
  lastUsedAt: external_exports3.string().nullable().optional(),
144727
144739
  lastSuccessfullyRanAt: external_exports3.string().nullable().optional()
144728
144740
  });
144741
+ var resolveCapabilityResponseSchema = external_exports3.object({
144742
+ capabilityId: external_exports3.string(),
144743
+ capabilitySlug: external_exports3.string(),
144744
+ matchedVia: external_exports3.enum(["exact", "template"])
144745
+ });
144729
144746
  var Capabilities = class {
144730
144747
  constructor(client) {
144731
144748
  this.client = client;
@@ -144740,6 +144757,31 @@ var Capabilities = class {
144740
144757
  },
144741
144758
  capabilityResponseSchema
144742
144759
  );
144760
+ // Resolve a raw endpoint URL + method back to the capability that owns it,
144761
+ // for the `zero fetch <url>` case where the client has no local search
144762
+ // context to match against (a memoized/cross-session URL). Returns null on
144763
+ // 404 — i.e. no match or an ambiguous multi-match, both of which the server
144764
+ // reports as 404 (resolveByUrl fails closed rather than mis-attribute).
144765
+ // The URL travels in the POST body so it stays out of access logs and is
144766
+ // never stored; the caller uses the returned capabilityId to record an
144767
+ // attributed run without the URL ever touching the run row (ZERO-335).
144768
+ resolveByUrl = async (url4, method, opts = {}) => {
144769
+ try {
144770
+ return await request2(
144771
+ this.client,
144772
+ {
144773
+ method: "POST",
144774
+ path: "/v1/capabilities/resolve",
144775
+ body: { url: url4, method },
144776
+ signal: opts.signal
144777
+ },
144778
+ resolveCapabilityResponseSchema
144779
+ );
144780
+ } catch (err) {
144781
+ if (err instanceof ZeroApiError && err.status === 404) return null;
144782
+ throw err;
144783
+ }
144784
+ };
144743
144785
  };
144744
144786
  var createRunResponseSchema = external_exports3.object({
144745
144787
  runId: external_exports3.string()
@@ -145312,14 +145354,17 @@ var resolveRecordingClient = (client, opts) => {
145312
145354
  const canRecord = opts.account !== void 0 || credentials.kind === "account" || credentials.kind === "session";
145313
145355
  return { recordingClient, canRecord };
145314
145356
  };
145315
- var recordErrorFetchRun = async (client, opts, result) => {
145316
- if (opts.capabilityId === void 0) return;
145357
+ var recordErrorFetchRun = async (client, opts, result, capabilityIdOverride) => {
145358
+ const effectiveCapId = opts.capabilityId;
145359
+ if (effectiveCapId === void 0) return;
145317
145360
  const { recordingClient, canRecord } = resolveRecordingClient(client, opts);
145318
145361
  if (!canRecord) return;
145362
+ const fetchOriginForRecord = opts.capabilityId === void 0 ? "direct_url" : opts.fetchOrigin;
145319
145363
  try {
145320
145364
  const created = await recordingClient.runs.create({
145321
- capabilityId: opts.capabilityId,
145365
+ capabilityId: effectiveCapId,
145322
145366
  ...opts.searchId && { searchId: opts.searchId },
145367
+ ...fetchOriginForRecord && { fetchOrigin: fetchOriginForRecord },
145323
145368
  ...result.status !== null && { status: result.status },
145324
145369
  latencyMs: result.latencyMs,
145325
145370
  ...opts.requestSchema && { requestSchema: opts.requestSchema }
@@ -145329,7 +145374,7 @@ var recordErrorFetchRun = async (client, opts, result) => {
145329
145374
  } catch {
145330
145375
  }
145331
145376
  };
145332
- var recordTimeoutRun = async (client, opts, err, startedAt, capabilityIdRequested) => {
145377
+ var recordTimeoutRun = async (client, opts, err, startedAt, capabilityIdRequested, capabilityIdOverride) => {
145333
145378
  const result = errorFetchResult(
145334
145379
  startedAt,
145335
145380
  err.message,
@@ -145366,6 +145411,11 @@ var clientFetch = async (client, url4, opts = {}) => {
145366
145411
  const startedAt = Date.now();
145367
145412
  const capabilityIdRequested = opts.capabilityId !== void 0;
145368
145413
  const method = opts.method ?? (opts.body !== void 0 ? "POST" : "GET");
145414
+ const { canRecord: canRecordForResolve } = resolveRecordingClient(
145415
+ client,
145416
+ opts
145417
+ );
145418
+ const resolvePromise = !capabilityIdRequested && canRecordForResolve ? client.capabilities.resolveByUrl(redactUrl2(url4), method).catch(() => null) : Promise.resolve(null);
145369
145419
  const probeHeaders = withDefaultContentType(opts.headers, opts.body);
145370
145420
  const requestInit = {
145371
145421
  method,
@@ -145557,7 +145607,15 @@ var clientFetch = async (client, url4, opts = {}) => {
145557
145607
  else if (closeFailed)
145558
145608
  skipReasons.push(FETCH_SKIP_REASONS.mppSessionCloseFailedNotRecorded);
145559
145609
  }
145560
- if (opts.capabilityId !== void 0 && !paidButStill402 && !closeFailed) {
145610
+ const resolvedCap = await resolvePromise;
145611
+ const effectiveCapabilityId = opts.capabilityId ?? resolvedCap?.capabilityId;
145612
+ const capabilityResolution = !capabilityIdRequested && canRecordForResolve ? resolvedCap !== null ? {
145613
+ resolved: true,
145614
+ capabilityId: resolvedCap.capabilityId,
145615
+ capabilitySlug: resolvedCap.capabilitySlug,
145616
+ matchedVia: resolvedCap.matchedVia
145617
+ } : { resolved: false } : void 0;
145618
+ if (effectiveCapabilityId !== void 0 && !paidButStill402 && !closeFailed) {
145561
145619
  const { recordingClient, canRecord } = resolveRecordingClient(client, opts);
145562
145620
  if (!canRecord) {
145563
145621
  skipReasons.push("no_credentials");
@@ -145577,8 +145635,11 @@ var clientFetch = async (client, url4, opts = {}) => {
145577
145635
  }
145578
145636
  }
145579
145637
  const result2 = await recordingClient.runs.create({
145580
- capabilityId: opts.capabilityId,
145638
+ capabilityId: effectiveCapabilityId,
145581
145639
  searchId: opts.searchId,
145640
+ // Auto-resolved runs are always direct_url — they only fire when
145641
+ // no capabilityId was supplied (the direct_url path by definition).
145642
+ ...opts.capabilityId === void 0 ? { fetchOrigin: "direct_url" } : opts.fetchOrigin && { fetchOrigin: opts.fetchOrigin },
145582
145643
  status: response.status,
145583
145644
  latencyMs,
145584
145645
  ...opts.requestSchema && { requestSchema: opts.requestSchema },
@@ -145611,7 +145672,7 @@ var clientFetch = async (client, url4, opts = {}) => {
145611
145672
  message: "Failed to record run for fetch",
145612
145673
  meta: {
145613
145674
  url: redactUrl2(url4),
145614
- capabilityId: opts.capabilityId,
145675
+ capabilityId: effectiveCapabilityId,
145615
145676
  error: errorMessage22,
145616
145677
  errorCode: code
145617
145678
  }
@@ -145639,6 +145700,8 @@ var clientFetch = async (client, url4, opts = {}) => {
145639
145700
  result.runTrackingSkipped = skipReasons;
145640
145701
  }
145641
145702
  if (warnings.length > 0) result.warnings = warnings;
145703
+ if (capabilityResolution !== void 0)
145704
+ result.capabilityResolution = capabilityResolution;
145642
145705
  return result;
145643
145706
  };
145644
145707
  var searchResultSchema = external_exports3.object({
@@ -146595,8 +146658,8 @@ var fetchCommand = (appContext) => new Command("fetch").description(
146595
146658
  });
146596
146659
  const matchCtx = explicitCapabilityCtx ?? urlCtx;
146597
146660
  const capabilityId = options.capability ?? matchCtx?.capabilityId ?? null;
146598
- const capabilityUid = matchCtx?.capabilityUid ?? null;
146599
- const capabilitySlug = matchCtx?.capabilitySlug ?? null;
146661
+ let capabilityUid = matchCtx?.capabilityUid ?? null;
146662
+ let capabilitySlug = matchCtx?.capabilitySlug ?? null;
146600
146663
  const searchId = matchCtx?.searchId;
146601
146664
  const resultRank = matchCtx?.resultRank;
146602
146665
  const fetchOrigin = matchCtx ? "from_search" : options.capability ? "direct_slug" : "direct_url";
@@ -146607,23 +146670,10 @@ var fetchCommand = (appContext) => new Command("fetch").description(
146607
146670
  "no wallet configured (run `zero auth login`, or `zero wallet set <key>` / set ZERO_PRIVATE_KEY)"
146608
146671
  );
146609
146672
  }
146610
- if (!capabilityId) {
146673
+ if (!capabilityId && !walletAddress) {
146611
146674
  cliSkipReasons.push(
146612
146675
  "no capability resolved \u2014 pass --capability <uid|slug> or run `zero search` first so the URL can be matched"
146613
146676
  );
146614
- if (!options.capability) {
146615
- const lastSearch = stateService.loadLastSearch();
146616
- const cached2 = lastSearch?.capabilities ?? [];
146617
- analyticsService.capture("capability_resolution_missed", {
146618
- url: redactUrl(resolvedUrl),
146619
- method,
146620
- hasLastSearch: lastSearch !== null,
146621
- lastSearchSize: cached2.length,
146622
- lastSearchHasTemplates: cached2.some(
146623
- (c) => Boolean(c.urlTemplate)
146624
- )
146625
- });
146626
- }
146627
146677
  }
146628
146678
  let requestSchema;
146629
146679
  if (typeof resolvedBody === "string") {
@@ -146659,6 +146709,11 @@ var fetchCommand = (appContext) => new Command("fetch").description(
146659
146709
  // and omitting here keeps result.runTrackingSkipped clean.
146660
146710
  ...capabilityId && walletAddress && { capabilityId },
146661
146711
  ...searchId && { searchId },
146712
+ // Stamp how the agent arrived (from_search | direct_slug |
146713
+ // direct_url) onto the run's metadata so direct execution is
146714
+ // distinguishable from search-driven runs server-side. Only
146715
+ // when a run is actually recorded (capabilityId + wallet).
146716
+ ...capabilityId && walletAddress && { fetchOrigin },
146662
146717
  ...requestSchema && { requestSchema },
146663
146718
  deriveRunMetadata: ({ bodyRaw: bodyRaw2, bodyEncoding: bodyEncoding2 }) => {
146664
146719
  if (bodyRaw2 && bodyEncoding2 !== "base64") {
@@ -146693,7 +146748,8 @@ var fetchCommand = (appContext) => new Command("fetch").description(
146693
146748
  upstreamError,
146694
146749
  warnings: sdkWarnings,
146695
146750
  runTrackingSkipped: sdkSkipReasons,
146696
- error: resultError
146751
+ error: resultError,
146752
+ capabilityResolution
146697
146753
  } = result;
146698
146754
  const isBinary = bodyEncoding === "base64";
146699
146755
  const bodyBytes = isBinary && bodyRaw ? Buffer.from(bodyRaw, "base64") : void 0;
@@ -146765,6 +146821,36 @@ var fetchCommand = (appContext) => new Command("fetch").description(
146765
146821
  log2(`Warning: ${w2}`);
146766
146822
  }
146767
146823
  }
146824
+ if (fetchOrigin === "direct_url") {
146825
+ if (capabilityResolution?.resolved) {
146826
+ capabilityUid = capabilityResolution.capabilityId ?? capabilityUid;
146827
+ capabilitySlug = capabilityResolution.capabilitySlug ?? capabilitySlug;
146828
+ analyticsService.capture("capability_resolution_recovered", {
146829
+ url: redactUrl(resolvedUrl),
146830
+ method,
146831
+ capabilityUid: capabilityResolution.capabilityId,
146832
+ capabilitySlug: capabilityResolution.capabilitySlug,
146833
+ matchedVia: capabilityResolution.matchedVia
146834
+ });
146835
+ } else {
146836
+ if (walletAddress && !runId) {
146837
+ cliSkipReasons.push(
146838
+ "no capability resolved \u2014 pass --capability <uid|slug> or run `zero search` first so the URL can be matched"
146839
+ );
146840
+ }
146841
+ const lastSearch = stateService.loadLastSearch();
146842
+ const cached2 = lastSearch?.capabilities ?? [];
146843
+ analyticsService.capture("capability_resolution_missed", {
146844
+ url: redactUrl(resolvedUrl),
146845
+ method,
146846
+ hasLastSearch: lastSearch !== null,
146847
+ lastSearchSize: cached2.length,
146848
+ lastSearchHasTemplates: cached2.some(
146849
+ (c) => Boolean(c.urlTemplate)
146850
+ )
146851
+ });
146852
+ }
146853
+ }
146768
146854
  analyticsService.capture("fetch_executed", {
146769
146855
  url: redactUrl(resolvedUrl),
146770
146856
  status: status ?? void 0,
@@ -146897,6 +146983,8 @@ var fetchCommand = (appContext) => new Command("fetch").description(
146897
146983
  ` --value 1-5 Was it worth the price? (1 = overpriced, 5 = great deal)`,
146898
146984
  ` --reliability 1-5 Did it respond quickly and without errors? (1 = flaky, 5 = rock solid)`,
146899
146985
  ` --content Free-text is optional but helps other agents pick the best capability.`,
146986
+ ` Published publicly \u2014 do not include personal or identifying`,
146987
+ ` information (names, emails, phone numbers, addresses, keys, SSNs).`,
146900
146988
  ``
146901
146989
  ].join("\n")
146902
146990
  );
@@ -147012,12 +147100,27 @@ var coerceToType = (value, type2) => {
147012
147100
  }
147013
147101
  return value;
147014
147102
  };
147015
- var sampleValueFor = (fieldName, propSchema) => {
147103
+ var sampleValueFor = (fieldName, propSchema, depth = 0) => {
147016
147104
  const node = asNode(propSchema);
147017
147105
  const type2 = schemaType(node);
147018
- const example = node?.example ?? node?.default;
147019
- if (example !== void 0 && example !== null) {
147020
- return coerceToType(example, type2);
147106
+ const enumFirst = Array.isArray(node?.enum) && node.enum.length > 0 ? node.enum[0] : void 0;
147107
+ const fixed = node?.const ?? node?.example ?? node?.default ?? enumFirst;
147108
+ if (fixed !== void 0 && fixed !== null) {
147109
+ return coerceToType(fixed, type2);
147110
+ }
147111
+ if (node && depth < MAX_SCHEMA_DEPTH) {
147112
+ const props = asNode(node.properties);
147113
+ if (props && (type2 === "object" || type2 === void 0)) {
147114
+ const obj = {};
147115
+ for (const [k3, sub] of Object.entries(props)) {
147116
+ obj[k3] = sampleValueFor(k3, sub, depth + 1);
147117
+ }
147118
+ return obj;
147119
+ }
147120
+ if (type2 === "array") {
147121
+ const items = asNode(node.items);
147122
+ return items ? [sampleValueFor(fieldName, items, depth + 1)] : [];
147123
+ }
147021
147124
  }
147022
147125
  switch (type2) {
147023
147126
  case "number":
@@ -147061,18 +147164,31 @@ var schemaTypeLabel = (node) => {
147061
147164
  };
147062
147165
  var constraintHint = (node) => {
147063
147166
  const num2 = (k3) => typeof node[k3] === "number" ? node[k3] : void 0;
147167
+ const hints = [];
147064
147168
  const min = num2("minimum");
147065
147169
  const max = num2("maximum");
147066
- if (min !== void 0 && max !== void 0) return `range: ${min}..${max}`;
147067
- if (min !== void 0) return `min: ${min}`;
147068
- if (max !== void 0) return `max: ${max}`;
147170
+ if (min !== void 0 && max !== void 0)
147171
+ hints.push(`range: ${min}..${max}`);
147172
+ else if (min !== void 0) hints.push(`min: ${min}`);
147173
+ else if (max !== void 0) hints.push(`max: ${max}`);
147174
+ const exMin = num2("exclusiveMinimum");
147175
+ const exMax = num2("exclusiveMaximum");
147176
+ if (exMin !== void 0) hints.push(`> ${exMin}`);
147177
+ if (exMax !== void 0) hints.push(`< ${exMax}`);
147069
147178
  const minLen = num2("minLength");
147070
147179
  const maxLen = num2("maxLength");
147071
147180
  if (minLen !== void 0 && maxLen !== void 0)
147072
- return `length: ${minLen}..${maxLen}`;
147073
- if (maxLen !== void 0) return `maxLength: ${maxLen}`;
147074
- if (minLen !== void 0) return `minLength: ${minLen}`;
147075
- return null;
147181
+ hints.push(`length: ${minLen}..${maxLen}`);
147182
+ else if (maxLen !== void 0) hints.push(`maxLength: ${maxLen}`);
147183
+ else if (minLen !== void 0) hints.push(`minLength: ${minLen}`);
147184
+ const minItems = num2("minItems");
147185
+ const maxItems = num2("maxItems");
147186
+ if (minItems !== void 0 && maxItems !== void 0)
147187
+ hints.push(`items: ${minItems}..${maxItems}`);
147188
+ else if (maxItems !== void 0) hints.push(`maxItems: ${maxItems}`);
147189
+ else if (minItems !== void 0) hints.push(`minItems: ${minItems}`);
147190
+ if (typeof node.pattern === "string") hints.push(`pattern: ${node.pattern}`);
147191
+ return hints.length > 0 ? hints.join(", ") : null;
147076
147192
  };
147077
147193
  var MAX_SCHEMA_DEPTH = 5;
147078
147194
  var paramAttrs = (node, required3) => {
@@ -147115,6 +147231,17 @@ var renderParam = (name, propSchema, required3, depth = 0) => {
147115
147231
  lines.push(...renderParam(`option ${i + 1}`, v, false, depth + 2));
147116
147232
  });
147117
147233
  }
147234
+ if (Array.isArray(node.allOf) && node.allOf.length > 0) {
147235
+ lines.push(`${pad9} must satisfy all of:`);
147236
+ node.allOf.forEach((v, i) => {
147237
+ lines.push(...renderParam(`part ${i + 1}`, v, false, depth + 2));
147238
+ });
147239
+ }
147240
+ if (typeof node.$ref === "string") {
147241
+ lines.push(
147242
+ `${pad9} \u26A0 schema reference not inlined (${node.$ref}) \u2014 shape incomplete, see provider docs`
147243
+ );
147244
+ }
147118
147245
  return lines;
147119
147246
  };
147120
147247
  var renderProps = (node, depth = 0) => {
@@ -147134,7 +147261,17 @@ var buildSchemaSection = (capability) => {
147134
147261
  capability.bodySchema,
147135
147262
  capability.method
147136
147263
  );
147137
- return [...renderProps(queryParams), ...renderProps(body)];
147264
+ const lines = [...renderProps(queryParams), ...renderProps(body)];
147265
+ if (lines.length === 0) {
147266
+ const root = asNode(capability.bodySchema);
147267
+ const unresolved = (n) => !!n && (n.$ref !== void 0 || Array.isArray(n.allOf));
147268
+ if (unresolved(root ?? void 0) || unresolved(queryParams) || unresolved(body)) {
147269
+ return [
147270
+ " \u26A0 input schema could not be expanded ($ref/allOf not inlined) \u2014 use the verified example below or the provider's docs"
147271
+ ];
147272
+ }
147273
+ }
147274
+ return lines;
147138
147275
  };
147139
147276
  var buildResponseSection = (capability) => {
147140
147277
  const rs = asNode(capability.responseSchema);
@@ -147154,10 +147291,22 @@ var buildResponseSection = (capability) => {
147154
147291
  }
147155
147292
  return [];
147156
147293
  };
147294
+ var unwrapTransportEnvelope = (req) => {
147295
+ const input = asNode(asNode(req)?.input);
147296
+ if (!input || input.type !== "http") return req;
147297
+ const body = input.body;
147298
+ const hasBody = body !== void 0 && body !== null && !(typeof body === "object" && Object.keys(body).length === 0);
147299
+ if (hasBody) return body;
147300
+ const qp = asNode(input.queryParams);
147301
+ if (qp && Object.keys(qp).length > 0) return qp;
147302
+ return null;
147303
+ };
147157
147304
  var buildVerifiedExampleSection = (capability) => {
147158
147305
  const req = capability.example?.request;
147159
147306
  if (req === void 0 || req === null) return [];
147160
- const json3 = typeof req === "string" ? req : JSON.stringify(req);
147307
+ const shown = unwrapTransportEnvelope(req);
147308
+ if (shown === void 0 || shown === null) return [];
147309
+ const json3 = typeof shown === "string" ? shown : JSON.stringify(shown);
147161
147310
  const truncated = json3.length > 600 ? `${json3.slice(0, 600)}\u2026` : json3;
147162
147311
  return ["", "Verified example (request):", ` ${truncated}`];
147163
147312
  };
@@ -147244,7 +147393,7 @@ var getCommand = (appContext) => new Command("get").description(
147244
147393
  ).argument(
147245
147394
  "<identifier>",
147246
147395
  "Position number from search results, or a capability slug"
147247
- ).option("--formatted", "Output formatted capability details").option(
147396
+ ).option("--formatted", "Output formatted capability details").option("--json", "Output raw JSON to stdout (default)").option(
147248
147397
  "--agent <name>",
147249
147398
  "Identify your agent host for this invocation. Overrides auto-detect for this call only."
147250
147399
  ).action(async (identifier, options) => {
@@ -147281,7 +147430,7 @@ var getCommand = (appContext) => new Command("get").description(
147281
147430
  const capability = await client.capabilities.get(capabilityId, {
147282
147431
  searchId
147283
147432
  });
147284
- if (options.formatted) {
147433
+ if (options.formatted && !options.json) {
147285
147434
  console.log(formatCapability(capability));
147286
147435
  } else {
147287
147436
  console.log(JSON.stringify(capability, null, 2));
@@ -147616,6 +147765,8 @@ Tips for a great review:
147616
147765
  --value 1-5 Was it worth the price? (1 = overpriced, 5 = great deal)
147617
147766
  --reliability 1-5 Did it respond quickly and without errors? (1 = flaky, 5 = rock solid)
147618
147767
  --content Free-text is optional but helps other agents pick the best capability.
147768
+ Published publicly \u2014 do not include personal or identifying information
147769
+ (names, emails, phone numbers, addresses, keys, SSNs).
147619
147770
 
147620
147771
  Examples:
147621
147772
  zero review run_abc123 --success --accuracy 5 --value 4 --reliability 5 --content "Fast, accurate translation"
@@ -147785,6 +147936,109 @@ Bulk review complete: ${ok} ok, ${failed} failed`);
147785
147936
  }
147786
147937
  );
147787
147938
 
147939
+ // src/commands/run-command.ts
147940
+ init_esm_shims();
147941
+ var readSkillMd = async (webBase) => {
147942
+ const home = homedir();
147943
+ for (const dir of SKILL_DIRS) {
147944
+ const path3 = join(home, dir, "zero", "SKILL.md");
147945
+ if (existsSync(path3)) return readFileSync(path3, "utf8");
147946
+ }
147947
+ const res = await fetch(`${webBase}/SKILL.md`);
147948
+ if (!res.ok) throw new Error(`Failed to fetch SKILL.md: ${res.status}`);
147949
+ return res.text();
147950
+ };
147951
+ var installCodexSkill = (skill) => {
147952
+ const dir = join(homedir(), ".codex", "skills", "zero");
147953
+ mkdirSync(dir, { recursive: true });
147954
+ writeFileSync(join(dir, "SKILL.md"), skill, "utf8");
147955
+ };
147956
+ var resolveZeroBinary = () => {
147957
+ const runner = process.env.ZERO_RUNNER;
147958
+ if (runner && existsSync(runner)) return runner;
147959
+ const fallback2 = join(homedir(), ".zero", "runtime", "bin", "zero");
147960
+ if (existsSync(fallback2)) return fallback2;
147961
+ return "zero";
147962
+ };
147963
+ var prepareHandoff = async (appContext, opts) => {
147964
+ const { client } = appContext.services;
147965
+ const webBase = appContext.env.ZERO_WEB_URL;
147966
+ const apiUrl = appContext.env.ZERO_API_URL;
147967
+ await ensureAuthenticated(client, opts.open);
147968
+ const skill = await readSkillMd(webBase);
147969
+ const zeroBin = resolveZeroBinary();
147970
+ const { ZERO_ENV: _drop, ...parentEnv } = process.env;
147971
+ const childEnv = { ...parentEnv };
147972
+ childEnv.ZERO_RUNNER = zeroBin !== "zero" ? zeroBin : childEnv.ZERO_RUNNER ?? "zero";
147973
+ if (zeroBin !== "zero") {
147974
+ childEnv.PATH = `${dirname(zeroBin)}:${process.env.PATH ?? ""}`;
147975
+ }
147976
+ for (let i = 0; i < 20; i++) {
147977
+ try {
147978
+ const res = await fetch(`${apiUrl}/health`, {
147979
+ signal: AbortSignal.timeout(2e3)
147980
+ });
147981
+ if (res.ok) break;
147982
+ } catch {
147983
+ await new Promise((r2) => setTimeout(r2, 500));
147984
+ }
147985
+ }
147986
+ return { skill, childEnv };
147987
+ };
147988
+ var claudeCommand = (appContext) => new Command("claude").description(
147989
+ "Open Claude Code with Zero capabilities pre-loaded \u2014 authenticate if needed, then hand off"
147990
+ ).argument(
147991
+ "[task...]",
147992
+ "Initial task for Claude Code (starts an interactive session with this as the first message)"
147993
+ ).option("--no-open", "Do not open the browser if sign-in is required").action(async (taskParts, opts) => {
147994
+ const { skill, childEnv } = await prepareHandoff(appContext, opts);
147995
+ const claudeArgs = ["--append-system-prompt", skill];
147996
+ const task = taskParts.join(" ").trim();
147997
+ if (task) claudeArgs.push(task);
147998
+ const result = spawnSync("claude", claudeArgs, {
147999
+ stdio: "inherit",
148000
+ env: childEnv
148001
+ });
148002
+ if (result.error) {
148003
+ process.stderr.write(
148004
+ `
148005
+ Failed to launch Claude Code: ${result.error.message}
148006
+ Make sure it is installed: https://claude.ai/download
148007
+ `
148008
+ );
148009
+ process.exitCode = 1;
148010
+ return;
148011
+ }
148012
+ if (result.status !== null) process.exitCode = result.status;
148013
+ });
148014
+ var codexCommand = (appContext) => new Command("codex").description(
148015
+ "Open Codex CLI with Zero capabilities pre-loaded \u2014 authenticate if needed, then hand off"
148016
+ ).argument(
148017
+ "[task...]",
148018
+ "Initial task for Codex (starts an interactive session with this as the first message)"
148019
+ ).option("--no-open", "Do not open the browser if sign-in is required").action(async (taskParts, opts) => {
148020
+ const { skill, childEnv } = await prepareHandoff(appContext, opts);
148021
+ installCodexSkill(skill);
148022
+ const codexArgs = [];
148023
+ const task = taskParts.join(" ").trim();
148024
+ if (task) codexArgs.push(task);
148025
+ const result = spawnSync("codex", codexArgs, {
148026
+ stdio: "inherit",
148027
+ env: childEnv
148028
+ });
148029
+ if (result.error) {
148030
+ process.stderr.write(
148031
+ `
148032
+ Failed to launch Codex: ${result.error.message}
148033
+ Make sure it is installed: https://openai.com/codex
148034
+ `
148035
+ );
148036
+ process.exitCode = 1;
148037
+ return;
148038
+ }
148039
+ if (result.status !== null) process.exitCode = result.status;
148040
+ });
148041
+
147788
148042
  // src/commands/runs-command.ts
147789
148043
  init_esm_shims();
147790
148044
  var USD_ASSETS = /* @__PURE__ */ new Set(["USD", "USDC"]);
@@ -149185,6 +149439,8 @@ var createApp = (appContext) => {
149185
149439
  program2.addCommand(configCommand());
149186
149440
  program2.addCommand(termsCommand());
149187
149441
  program2.addCommand(authCommand(appContext));
149442
+ program2.addCommand(claudeCommand(appContext));
149443
+ program2.addCommand(codexCommand(appContext));
149188
149444
  return program2;
149189
149445
  };
149190
149446
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeroxyz/cli",
3
- "version": "1.4.0",
3
+ "version": "1.6.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "zero": "dist/index.js",