claude-use 11.28.0 → 11.30.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/README.md CHANGED
@@ -98,7 +98,7 @@ agent-shim profile set <name> [--category <category>=<bool>]... [--entry <catego
98
98
  agent-shim profile set <name> [--extends <profile>]... [--no-extends] [--description <text> | --no-description] [--json]
99
99
  agent-shim profile set <name> [--[no-]launch-skip-permissions] [--[no-]launch-remote-control] [--[no-]launch-headroom] [--[no-]launch-track-usage]
100
100
  agent-shim profile set <name> [--launch-claude-version <version> | --no-launch-claude-version] [--json] [--json]
101
- agent-shim profile set <name> [--launch-delay <duration> | --no-launch-delay] [--[no-]launch-pause] [--json]
101
+ agent-shim profile set <name> [--launch-delay <duration> | --no-launch-delay] [--[no-]launch-pause] [--[no-]launch-explain] [--json]
102
102
  agent-shim profile set <name> [--launch-provider <provider> | --no-launch-provider] [--json]
103
103
  agent-shim profile list [--json]
104
104
  agent-shim profile show <name> [--json]
@@ -183,6 +183,7 @@ agent-shim run [@<identity>] [launch flags] [claude arguments]
183
183
  # --[no-]skip-permissions --[no-]remote-control --[no-]headroom --[no-]track-usage --[no-]wait
184
184
  # --claude-version <version> run exactly this installed Claude Code version
185
185
  # --delay <duration> wait this long after the launcher's own output before starting claude; --[no-]pause waits for a key press instead
186
+ # --[no-]explain with @pool:<name>, list every member the pick ranked and why, not only the one picked
186
187
  # --native run the real claude with nothing from agent-shim applied; cannot be combined with the flags above
187
188
  claude @<identity> ... # the same, once `agent-shim shim enable` has run
188
189
  ```
package/dist/cli.cjs CHANGED
@@ -27031,7 +27031,9 @@ var init_schema = __esm({
27031
27031
  /** How long the launcher waits after its own output before it starts claude, so that output can be read before Claude Code takes over the terminal (`5s`, `500ms`). Applies only when a terminal is watching. */
27032
27032
  delay: external_exports.string().regex(DURATION_RE, "must be a duration such as 5s or 500ms").optional(),
27033
27033
  /** Whether the launcher waits for a key press after its own output before it starts claude. Takes the place of `delay` when both are set. Applies only when a terminal is watching. */
27034
- pause: external_exports.boolean().optional()
27034
+ pause: external_exports.boolean().optional(),
27035
+ /** Whether the launcher's report, for a launch that picks from a pool, lists every member the pick ranked with why each stands where it does, and not only the member it picked. */
27036
+ explain: external_exports.boolean().optional()
27035
27037
  });
27036
27038
  CREDENTIAL_TARGETS = ["bearer", "apiKey", "oauthToken"];
27037
27039
  PROVIDER_CREDENTIAL_TARGETS = ["bearer", "apiKey"];
@@ -28687,20 +28689,53 @@ var init_supervisor = __esm({
28687
28689
  }
28688
28690
  });
28689
28691
 
28690
- // src/logStyle.ts
28691
- function styledDiagnostic(style, colour, line) {
28692
- const lead = DIAGNOSTIC_LEAD.exec(line);
28693
- if (lead === null) {
28694
- return style([colour], line);
28692
+ // src/launcher/report.ts
28693
+ function renderReport(rows, style) {
28694
+ if (rows.length === 0) {
28695
+ return [];
28696
+ }
28697
+ const labelWidth = Math.max(...rows.map((row) => row.label.length));
28698
+ const indent = " ".repeat(COLUMN_GAP.length);
28699
+ const lines = [style(["bold"], REPORT_HEADING)];
28700
+ for (const row of rows) {
28701
+ const detail = row.detail === void 0 ? "" : ` ${style(["dim"], `(${row.detail})`)}`;
28702
+ lines.push(`${indent}${style(["dim"], row.label.padEnd(labelWidth))}${COLUMN_GAP}${row.value}${detail}`);
28703
+ for (const note of row.notes ?? []) {
28704
+ lines.push(`${indent}${" ".repeat(labelWidth)}${COLUMN_GAP}${style(["dim"], note)}`);
28705
+ }
28695
28706
  }
28696
- const [whole, prefix = "", code = "", separator = ""] = lead;
28697
- return `${style([colour], prefix)}${style([colour, "bold"], code)}${style([colour], `${separator}${line.slice(whole.length)}`)}`;
28707
+ return lines;
28708
+ }
28709
+ var REPORT_HEADING, COLUMN_GAP;
28710
+ var init_report = __esm({
28711
+ "src/launcher/report.ts"() {
28712
+ "use strict";
28713
+ REPORT_HEADING = "agent-shim";
28714
+ COLUMN_GAP = " ";
28715
+ }
28716
+ });
28717
+
28718
+ // src/logStyle.ts
28719
+ function styledDiagnostic(style, colour, text2) {
28720
+ return text2.split("\n").map((line, index) => {
28721
+ const lead = index === 0 ? DIAGNOSTIC_LEAD.exec(line) : null;
28722
+ if (lead === null) {
28723
+ return style([colour], line);
28724
+ }
28725
+ const [whole, prefix = "", code = "", separator = ""] = lead;
28726
+ return `${style([colour], prefix)}${style([colour, "bold"], code)}${style([colour], `${separator}${line.slice(whole.length)}`)}`;
28727
+ }).join("\n");
28698
28728
  }
28699
28729
  function createLogPort(sinks, styleFor) {
28700
28730
  return {
28701
28731
  info: (message) => {
28702
28732
  sinks.out(styleFor.out(["dim"], message));
28703
28733
  },
28734
+ report: (rows) => {
28735
+ for (const line of renderReport(rows, styleFor.out)) {
28736
+ sinks.out(line);
28737
+ }
28738
+ },
28704
28739
  warn: (message) => {
28705
28740
  sinks.warn(styledDiagnostic(styleFor.err, "yellow", message));
28706
28741
  },
@@ -28717,6 +28752,7 @@ var init_logStyle = __esm({
28717
28752
  "src/logStyle.ts"() {
28718
28753
  "use strict";
28719
28754
  import_node_util3 = require("node:util");
28755
+ init_report();
28720
28756
  DIAGNOSTIC_LEAD = /^(agent-shim: )([A-Z][A-Z0-9_]*)(: )/;
28721
28757
  }
28722
28758
  });
@@ -32537,6 +32573,9 @@ function flattenLayers(layers, options) {
32537
32573
  if (layer.launch.pause !== void 0) {
32538
32574
  launch.pause = layer.launch.pause;
32539
32575
  }
32576
+ if (layer.launch.explain !== void 0) {
32577
+ launch.explain = layer.launch.explain;
32578
+ }
32540
32579
  }
32541
32580
  if (layer.entries === void 0) {
32542
32581
  continue;
@@ -32635,11 +32674,15 @@ var init_flatten = __esm({
32635
32674
  });
32636
32675
 
32637
32676
  // src/resolve/decide.ts
32638
- function unclassifiedEntryMessage(names) {
32677
+ function unclassifiedEntrySummary(names) {
32639
32678
  const quoted = names.map((name) => `"${name}"`).join(", ");
32640
- const subject = names.length === 1 ? `${quoted} is not` : `${String(names.length)} entries are not`;
32641
- const excluded = names.length === 1 ? "it is excluded" : `they are excluded: ${quoted}`;
32642
- return `${subject} in the category map, so ${excluded}. Run \`agent-shim configure\` to classify ${names.length === 1 ? "it" : "them"}, which records the answer in the local overlay without touching the shipped default map.`;
32679
+ return names.length === 1 ? `${quoted} is not in the category map, so it is excluded` : `${String(names.length)} entries are not in the category map, so they are excluded: ${quoted}`;
32680
+ }
32681
+ function unclassifiedEntryFix(names) {
32682
+ return `Run \`agent-shim configure\` to classify ${names.length === 1 ? "it" : "them"}`;
32683
+ }
32684
+ function unclassifiedEntryMessage(names) {
32685
+ return `${unclassifiedEntrySummary(names)}. ${unclassifiedEntryFix(names)}.`;
32643
32686
  }
32644
32687
  function selectRule(relPath, flattened, context) {
32645
32688
  const eliminated = [];
@@ -34280,7 +34323,7 @@ var init_package = __esm({
34280
34323
  "package.json"() {
34281
34324
  package_default = {
34282
34325
  name: "claude-use",
34283
- version: "11.28.0",
34326
+ version: "11.30.0",
34284
34327
  description: "A profile manager and launcher for Claude Code that lets one person run multiple logins from one machine while controlling what gets shared between them.",
34285
34328
  license: "MIT",
34286
34329
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -63087,7 +63130,8 @@ var init_argv = __esm({
63087
63130
  { flag: "--skip-permissions", key: "skipPermissions" },
63088
63131
  { flag: "--remote-control", key: "remoteControl" },
63089
63132
  { flag: "--wait", key: "wait" },
63090
- { flag: "--pause", key: "pause" }
63133
+ { flag: "--pause", key: "pause" },
63134
+ { flag: "--explain", key: "explain" }
63091
63135
  ];
63092
63136
  LAUNCHER_FLAG_NAMES = [
63093
63137
  ...VALUED_FLAGS,
@@ -63276,6 +63320,7 @@ function resolveLaunchFlags(params) {
63276
63320
  headroom: params.flags?.headroom ?? parseEnvBool("AGENT_SHIM_HEADROOM", params.env.AGENT_SHIM_HEADROOM) ?? params.cascade?.headroom ?? false,
63277
63321
  trackUsage: params.flags?.trackUsage ?? parseEnvBool("AGENT_SHIM_TRACK_USAGE", params.env.AGENT_SHIM_TRACK_USAGE) ?? params.cascade?.trackUsage ?? true,
63278
63322
  pause: params.flags?.pause ?? parseEnvBool("AGENT_SHIM_PAUSE", params.env.AGENT_SHIM_PAUSE) ?? params.cascade?.pause ?? false,
63323
+ explain: params.flags?.explain ?? parseEnvBool("AGENT_SHIM_EXPLAIN", params.env.AGENT_SHIM_EXPLAIN) ?? params.cascade?.explain ?? false,
63279
63324
  delayMs: resolveDelayMs(params)
63280
63325
  };
63281
63326
  }
@@ -63595,7 +63640,9 @@ function diagnosticLines(diagnostics) {
63595
63640
  if (diagnostic.code === "UNCLASSIFIED_ENTRY") {
63596
63641
  if (!unclassifiedReported) {
63597
63642
  unclassifiedReported = true;
63598
- lines.push({ severity: diagnostic.severity, text: `agent-shim: ${diagnostic.code}: ${unclassifiedEntryMessage(unclassified.filter((name) => name !== void 0))}` });
63643
+ const names = unclassified.filter((name) => name !== void 0);
63644
+ lines.push({ severity: diagnostic.severity, text: `agent-shim: ${diagnostic.code}: ${unclassifiedEntrySummary(names)}
63645
+ ${unclassifiedEntryFix(names)}.` });
63599
63646
  }
63600
63647
  continue;
63601
63648
  }
@@ -63603,8 +63650,8 @@ function diagnosticLines(diagnostics) {
63603
63650
  }
63604
63651
  return lines;
63605
63652
  }
63606
- function reportDiagnostics(log, diagnostics, options) {
63607
- for (const line of diagnosticLines(diagnostics)) {
63653
+ function printDiagnosticLines(log, lines, options) {
63654
+ for (const line of lines) {
63608
63655
  if (line.severity === "error" && !options.errorsAsWarnings) {
63609
63656
  log.error(line.text);
63610
63657
  } else {
@@ -63612,6 +63659,9 @@ function reportDiagnostics(log, diagnostics, options) {
63612
63659
  }
63613
63660
  }
63614
63661
  }
63662
+ function reportDiagnostics(log, diagnostics, options) {
63663
+ printDiagnosticLines(log, diagnosticLines(diagnostics), options);
63664
+ }
63615
63665
  var init_diagnostics = __esm({
63616
63666
  "src/launcher/diagnostics.ts"() {
63617
63667
  "use strict";
@@ -63644,6 +63694,79 @@ var init_hold = __esm({
63644
63694
  }
63645
63695
  });
63646
63696
 
63697
+ // src/usage/candidateText.ts
63698
+ function candidateHeading(candidate) {
63699
+ const score = candidate.score === void 0 ? "" : ` score ${candidate.score.toFixed(2)}${candidate.scoreWindow === "fiveHour" ? " by 5h reset" : " by 7d reset"}`;
63700
+ const dry = candidate.feasible ? "" : " (5h would run dry)";
63701
+ return `[${candidate.class}${score}]${dry}`;
63702
+ }
63703
+ var init_candidateText = __esm({
63704
+ "src/usage/candidateText.ts"() {
63705
+ "use strict";
63706
+ }
63707
+ });
63708
+
63709
+ // src/launcher/launchReport.ts
63710
+ function poolDetail(pool) {
63711
+ const [reason] = pool.reasons;
63712
+ if (pool.movedOff !== void 0) {
63713
+ return { detail: `moved off ${pool.movedOff.identity}: ${pool.movedOff.reason}`, ...reason === void 0 ? {} : { notes: [reason] } };
63714
+ }
63715
+ return reason === void 0 ? {} : { detail: reason };
63716
+ }
63717
+ function rankingNotes(ranking, picked) {
63718
+ return ranking.flatMap((candidate, index) => [
63719
+ `${String(index + 1)}. ${candidate.identity} ${candidateHeading(candidate)}${candidate.identity === picked ? " (picked)" : ""}`,
63720
+ ` ${candidate.reasons.join("; ")}`
63721
+ ]);
63722
+ }
63723
+ function decisionRows(facts) {
63724
+ return [
63725
+ { label: "identity", value: facts.identity ?? "(none)", detail: facts.identitySource },
63726
+ ...facts.pool === void 0 ? [] : [
63727
+ {
63728
+ label: "pool",
63729
+ value: facts.pool.name,
63730
+ ...poolDetail(facts.pool),
63731
+ ...facts.ranking === void 0 ? {} : { notes: rankingNotes(facts.ranking, facts.identity) }
63732
+ }
63733
+ ],
63734
+ ...facts.profile === void 0 ? [] : [{ label: "profile", value: facts.profile.name, detail: facts.profile.source }],
63735
+ ...facts.provider === void 0 ? [] : [{ label: "provider", value: facts.provider.name, detail: `credential ${facts.provider.credential}` }],
63736
+ ...facts.identityCredential === void 0 ? [] : [{ label: "credential", value: facts.identityCredential, detail: "the identity's own" }]
63737
+ ];
63738
+ }
63739
+ function pinnedVersionRow(version2, source) {
63740
+ return { label: "claude", value: version2, detail: `pinned by ${source}` };
63741
+ }
63742
+ function routingRows(facts) {
63743
+ if (facts.frontDoor === void 0) {
63744
+ return [];
63745
+ }
63746
+ return [
63747
+ {
63748
+ label: "routing",
63749
+ value: `front door 127.0.0.1:${String(facts.frontDoor.port)}`,
63750
+ ...facts.provider ? {} : { detail: `OAuth via CONNECT 127.0.0.1:${String(facts.frontDoor.connectPort)}` }
63751
+ },
63752
+ ...facts.headroom === void 0 ? [] : [{ label: "headroom", value: "on", detail: `project ${facts.headroom.projectId}` }]
63753
+ ];
63754
+ }
63755
+ function farmRow(links, builtDirectories, adopted) {
63756
+ const counted = (count, singular, plural2) => `${String(count)} ${count === 1 ? singular : plural2}`;
63757
+ const parts = [counted(links, "link", "links"), counted(builtDirectories, "built directory", "built directories"), ...adopted === 0 ? [] : [`${String(adopted)} adopted`]];
63758
+ return { label: "farm", value: "resynced", detail: parts.join(", ") };
63759
+ }
63760
+ function noteRow(text2) {
63761
+ return { label: "note", value: text2 };
63762
+ }
63763
+ var init_launchReport = __esm({
63764
+ "src/launcher/launchReport.ts"() {
63765
+ "use strict";
63766
+ init_candidateText();
63767
+ }
63768
+ });
63769
+
63647
63770
  // src/antigravity/cloudUpstream.ts
63648
63771
  function isCcpaEndpoint(endpoint) {
63649
63772
  return endpoint.includes("cloudcode-pa.googleapis.com");
@@ -64895,6 +65018,7 @@ function resolvePoolLaunch(params) {
64895
65018
  identity: pick2.identity,
64896
65019
  explanation: `pool ${poolName}: ${move}${pick2.reasons.slice(0, REASONS_LOGGED).join("; ")}`,
64897
65020
  reasons: pick2.reasons,
65021
+ candidates: graph.ranking.candidates,
64898
65022
  ...movedOff === void 0 ? {} : { movedOff }
64899
65023
  };
64900
65024
  }
@@ -65038,7 +65162,7 @@ function pickFromPool(decided, params, parsedArgv, readOnly) {
65038
65162
  }
65039
65163
  if (params.supervised?.member !== void 0) {
65040
65164
  const reasons = ["resumed here by the supervising launcher after the previous member ran out of quota"];
65041
- return { identityDecision: { ...decided, name: params.supervised.member }, poolExplanation: `pool ${decided.pool}: ${reasons.join("; ")}`, poolPick: { name: decided.pool, reasons } };
65165
+ return { identityDecision: { ...decided, name: params.supervised.member }, poolPick: { name: decided.pool, reasons } };
65042
65166
  }
65043
65167
  const farmRuntime = params.farm;
65044
65168
  if (farmRuntime === void 0) {
@@ -65069,8 +65193,8 @@ function pickFromPool(decided, params, parsedArgv, readOnly) {
65069
65193
  }
65070
65194
  return {
65071
65195
  identityDecision: { ...decided, name: resolution.identity },
65072
- poolExplanation: resolution.explanation,
65073
- poolPick: { name: decided.pool, reasons: resolution.reasons, ...resolution.movedOff === void 0 ? {} : { movedOff: resolution.movedOff } }
65196
+ poolPick: { name: decided.pool, reasons: resolution.reasons, ...resolution.movedOff === void 0 ? {} : { movedOff: resolution.movedOff } },
65197
+ poolRanking: resolution.candidates
65074
65198
  };
65075
65199
  }
65076
65200
  function decideLaunch(params, readOnly) {
@@ -65097,7 +65221,7 @@ function decideLaunch(params, readOnly) {
65097
65221
  return trimmed === "" ? void 0 : trimmed;
65098
65222
  }
65099
65223
  });
65100
- const { identityDecision, poolExplanation, poolPick } = pickFromPool(decidedIdentity, params, parsedArgv, readOnly);
65224
+ const { identityDecision, poolPick, poolRanking } = pickFromPool(decidedIdentity, params, parsedArgv, readOnly);
65101
65225
  const farmIdentity = configDirEscapeHatchApplies ? void 0 : identityDecision.name;
65102
65226
  const farm = farmIdentity === void 0 ? void 0 : params.farm;
65103
65227
  if (!readOnly && farm !== void 0 && farmIdentity !== void 0) {
@@ -65233,19 +65357,21 @@ function decideLaunch(params, readOnly) {
65233
65357
  ...parsedArgv.headroom === void 0 ? {} : { headroom: parsedArgv.headroom },
65234
65358
  ...parsedArgv.trackUsage === void 0 ? {} : { trackUsage: parsedArgv.trackUsage },
65235
65359
  ...parsedArgv.pause === void 0 ? {} : { pause: parsedArgv.pause },
65360
+ ...parsedArgv.explain === void 0 ? {} : { explain: parsedArgv.explain },
65236
65361
  ...parsedArgv.delay === void 0 ? {} : { delay: parsedArgv.delay }
65237
65362
  }
65238
65363
  });
65239
65364
  const loginlessProvider = requestedFlags.remoteControl && selectedProvider !== void 0 && farmIdentity !== void 0 && params.hasStoredLogin?.(farmIdentity) === false ? { identity: farmIdentity, provider: selectedProvider.name } : void 0;
65240
- if (loginlessProvider !== void 0 && !readOnly) {
65241
- log.info(`agent-shim: identity ${loginlessProvider.identity} has no stored login, so Remote Control, which needs one, is off for this launch; provider ${loginlessProvider.provider} runs without it`);
65365
+ const notes = [];
65366
+ if (loginlessProvider !== void 0) {
65367
+ notes.push(`${loginlessProvider.identity} has no stored login, so Remote Control is off; provider ${loginlessProvider.provider} runs without it`);
65242
65368
  }
65243
65369
  const flags = loginlessProvider === void 0 ? requestedFlags : { ...requestedFlags, remoteControl: false };
65244
65370
  const catalogue = selectedProvider === void 0 ? void 0 : parseCatalogueCache(params.fs.readFileUtf8(catalogueCachePath(paths, selectedProvider.name)));
65245
65371
  const pickerSettings = selectedProvider === void 0 ? void 0 : modelPickerSettings(selectedProvider.definition, catalogue?.models);
65246
65372
  const callerSettings = hasSettingsArgument(parsedArgv.rest);
65247
- if (pickerSettings !== void 0 && callerSettings && !readOnly) {
65248
- log.info("agent-shim: this launch passes its own --settings, so /model keeps Claude Code's own model names instead of listing the provider's models");
65373
+ if (pickerSettings !== void 0 && callerSettings) {
65374
+ notes.push("--settings was passed, so /model keeps Claude Code's own model names");
65249
65375
  }
65250
65376
  const launcherSettings = mergeSettings([params.supervised?.settings, callerSettings ? void 0 : pickerSettings]);
65251
65377
  const args = buildArgv({
@@ -65267,8 +65393,9 @@ function decideLaunch(params, readOnly) {
65267
65393
  return {
65268
65394
  parsedArgv,
65269
65395
  identityDecision,
65270
- poolExplanation,
65271
65396
  poolPick,
65397
+ poolRanking,
65398
+ notes,
65272
65399
  configDirEscapeHatch: configDirEscapeHatchApplies,
65273
65400
  farmIdentity,
65274
65401
  farmContext,
@@ -65288,10 +65415,19 @@ function prepareLaunch(params) {
65288
65415
  const { paths, proc, log } = params;
65289
65416
  const { env } = proc;
65290
65417
  const decided = decideLaunch(params, false);
65291
- const { identityDecision, configProfileDecision, resolvedProvider, identityCredential, poolExplanation, flags: resolvedFlags, args: finalArgv, configDirEscapeHatch: configDirEscapeHatchApplies, decision } = decided;
65292
- log.info(
65293
- `agent-shim: identity ${identityDecision.name ?? "(none)"} (${identityDecision.source}${poolExplanation === void 0 ? "" : `, ${poolExplanation}`}), config profile ${configProfileDecision.name ?? "(none)"} (${configProfileDecision.source})` + (resolvedProvider === void 0 ? "" : `, provider ${resolvedProvider.name} (credential ${resolvedProvider.credential.target} from ${describeSource(resolvedProvider.credential.source)})`) + (identityCredential === void 0 ? "" : `, identity credential ${identityCredential.target} from ${describeSource(identityCredential.source)}`)
65294
- );
65418
+ const { identityDecision, configProfileDecision, resolvedProvider, identityCredential, poolPick, poolRanking, notes, flags: resolvedFlags, args: finalArgv, configDirEscapeHatch: configDirEscapeHatchApplies, decision } = decided;
65419
+ const rows = [
65420
+ ...decisionRows({
65421
+ identity: identityDecision.name,
65422
+ identitySource: identityDecision.source,
65423
+ pool: poolPick,
65424
+ ranking: resolvedFlags.explain ? poolRanking : void 0,
65425
+ profile: configProfileDecision.name === void 0 ? void 0 : { name: configProfileDecision.name, source: configProfileDecision.source },
65426
+ provider: resolvedProvider === void 0 ? void 0 : { name: resolvedProvider.name, credential: `${resolvedProvider.credential.target} from ${describeSource(resolvedProvider.credential.source)}` },
65427
+ identityCredential: identityCredential === void 0 ? void 0 : `${identityCredential.target} from ${describeSource(identityCredential.source)}`
65428
+ })
65429
+ ];
65430
+ let warnings = [];
65295
65431
  const updateCheck = runLaunchUpdateCheck({
65296
65432
  mode: params.updateMode ?? "off",
65297
65433
  checkPath: import_node_path43.default.join(paths.root, "update.check"),
@@ -65326,15 +65462,13 @@ function prepareLaunch(params) {
65326
65462
  }
65327
65463
  throw error63;
65328
65464
  }
65329
- reportDiagnostics(log, result.diagnostics, { errorsAsWarnings: false });
65465
+ warnings = diagnosticLines(result.diagnostics);
65330
65466
  if (!result.noOp) {
65331
- log.info(
65332
- `agent-shim: farm at ${result.farmRoot} resynced (${String(result.manifest.links.length)} link(s), ${String(result.manifest.materialised.length)} built director(ies)${result.adopted.length === 0 ? "" : `, ${String(result.adopted.length)} adopted into ${resyncFarmRuntime.claudeHome}`})`
65333
- );
65467
+ rows.push(farmRow(result.manifest.links.length, result.manifest.materialised.length, result.adopted.length));
65334
65468
  }
65335
65469
  }
65336
65470
  if (decided.pinnedVersion !== void 0) {
65337
- log.info(`agent-shim: Claude Code ${decided.pinnedVersion.version} (pinned by ${decided.pinnedVersion.source})`);
65471
+ rows.push(pinnedVersionRow(decided.pinnedVersion.version, decided.pinnedVersion.source));
65338
65472
  }
65339
65473
  const frontDoorPort = params.frontdoor;
65340
65474
  const frontDoorEngaged = resolvedProvider !== void 0 || resolvedFlags.headroom || resolvedFlags.trackUsage;
@@ -65350,14 +65484,11 @@ function prepareLaunch(params) {
65350
65484
  const headroomPort = params.headroom;
65351
65485
  if (resolvedFlags.headroom && headroomPort !== void 0) {
65352
65486
  headroom = headroomPort.ensure({ routesProvider: resolvedProvider !== void 0 });
65353
- const via = resolvedProvider === void 0 ? `OAuth via the door's CONNECT surface on 127.0.0.1:${String(frontDoor?.connectPort ?? 0)}` : `provider ${resolvedProvider.name}`;
65354
- log.info(`agent-shim: routing through the front door on 127.0.0.1:${String(frontDoor?.port ?? 0)} with headroom on unix socket ${headroom.socketPath} (${via}, project ${headroom.projectId})`);
65355
65487
  } else if (resolvedFlags.headroom) {
65356
65488
  log.error("agent-shim: headroom routing was requested but this launcher has no headroom port wired; refusing to launch without it.");
65357
65489
  proc.exit(1);
65358
- } else if (frontDoor !== void 0) {
65359
- log.info(`agent-shim: routing through the front door on 127.0.0.1:${String(frontDoor.port)}${resolvedProvider === void 0 ? ` (OAuth via the door's CONNECT surface on 127.0.0.1:${String(frontDoor.connectPort)}, usage recorded)` : ` (provider ${resolvedProvider.name})`}`);
65360
65490
  }
65491
+ rows.push(...routingRows({ frontDoor, headroom, provider: resolvedProvider !== void 0 }));
65361
65492
  const frontDoorRelease = frontDoor === void 0 ? void 0 : frontDoorPort?.release;
65362
65493
  const sessionId = params.supervised?.sessionId ?? (0, import_node_crypto18.randomUUID)();
65363
65494
  const finalEnv = buildEnv({
@@ -65378,6 +65509,9 @@ function prepareLaunch(params) {
65378
65509
  registered();
65379
65510
  }
65380
65511
  };
65512
+ rows.push(...notes.map(noteRow));
65513
+ log.report(rows);
65514
+ printDiagnosticLines(log, warnings, { errorsAsWarnings: false });
65381
65515
  const hold = () => holdBeforeLaunch({ delayMs: resolvedFlags.delayMs, pause: resolvedFlags.pause }, params.hold, log);
65382
65516
  return { bin: decided.bin, args: finalArgv, env: finalEnv, sessionId, release, markChildStarted: updateCheck.markChildStarted, hold, decision };
65383
65517
  }
@@ -65446,6 +65580,7 @@ var init_launcher = __esm({
65446
65580
  init_claudeSession();
65447
65581
  init_diagnostics();
65448
65582
  init_hold();
65583
+ init_launchReport();
65449
65584
  init_modelPicker();
65450
65585
  init_providerCatalogue();
65451
65586
  init_pool();
@@ -65537,6 +65672,7 @@ function resolveClaudeLaunch(options) {
65537
65672
  const warnings = [];
65538
65673
  const log = {
65539
65674
  info: () => void 0,
65675
+ report: () => void 0,
65540
65676
  warn: (message) => {
65541
65677
  warnings.push(message);
65542
65678
  },
@@ -65607,6 +65743,7 @@ async function withIdentityClaude(params, identity, flags, use2) {
65607
65743
  },
65608
65744
  log: {
65609
65745
  info: () => void 0,
65746
+ report: () => void 0,
65610
65747
  warn: () => void 0,
65611
65748
  error: (message) => {
65612
65749
  refusals.push(message);
@@ -111415,6 +111552,9 @@ function applyProfileChange(paths, name, change) {
111415
111552
  if (change.launchPause !== void 0) {
111416
111553
  launchPatch.pause = change.launchPause;
111417
111554
  }
111555
+ if (change.launchExplain !== void 0) {
111556
+ launchPatch.explain = change.launchExplain;
111557
+ }
111418
111558
  if (Object.keys(launchPatch).length > 0) {
111419
111559
  setProfileLaunchFlags(paths, name, launchPatch);
111420
111560
  touched = true;
@@ -112701,7 +112841,7 @@ function registerProfileCommand(program2, deps) {
112701
112841
  withExamples(
112702
112842
  profile.command("set <name>").description(
112703
112843
  "Update a configuration profile's categories, entries, extends list, description or launch settings. With no options on a terminal, walks through its categories."
112704
- ).option("--category <category=bool>", "Share (true) or hide (false) a whole category (repeatable).", collectBoolPair).option("--entry <path=bool>", "Share (true) or hide (false) one <category>/<path> entry (repeatable).", collectBoolPair).option("--extends <profile>", "Replace the extends list with these profiles (repeatable, in order).", collectRepeated).option("--no-extends", "Clear the extends list.").option("--description <text>", "Replace the description.").option("--no-description", "Clear the description.").option("--launch-skip-permissions", "Launches under this profile skip permission prompts.").option("--no-launch-skip-permissions", "Launches under this profile keep permission prompts.").option("--launch-remote-control", "Launches under this profile enable Remote Control.").option("--no-launch-remote-control", "Launches under this profile leave Remote Control off.").option("--launch-headroom", "Launches under this profile route through headroom.").option("--no-launch-headroom", "Launches under this profile route direct.").option("--launch-track-usage", "Launches under this profile route through the front door so their requests and quota are recorded, with no headroom needed.").option("--no-launch-track-usage", "Launches under this profile are not recorded unless a provider or headroom routes them anyway.").option("--launch-provider <provider>", "Launches under this profile route through this provider.").option("--no-launch-provider", "Clear this profile's provider selection.").option("--launch-claude-version <version>", "Launches under this profile run exactly this installed Claude Code version (such as 2.1.220); a version that is not installed fails the launch.").option("--no-launch-claude-version", "Clear this profile's Claude Code version pin.").option("--launch-delay <duration>", "Launches under this profile wait this long (such as 5s) after the launcher's own output before starting claude, so the output can be read.", parseDurationLiteral).option("--no-launch-delay", "Clear this profile's launch delay.").option("--launch-pause", "Launches under this profile wait for a key press after the launcher's own output before starting claude.").option("--no-launch-pause", "Launches under this profile start claude without waiting for a key press.").option("--json", "Print the result as JSON.").action(async (name, allOptions) => {
112844
+ ).option("--category <category=bool>", "Share (true) or hide (false) a whole category (repeatable).", collectBoolPair).option("--entry <path=bool>", "Share (true) or hide (false) one <category>/<path> entry (repeatable).", collectBoolPair).option("--extends <profile>", "Replace the extends list with these profiles (repeatable, in order).", collectRepeated).option("--no-extends", "Clear the extends list.").option("--description <text>", "Replace the description.").option("--no-description", "Clear the description.").option("--launch-skip-permissions", "Launches under this profile skip permission prompts.").option("--no-launch-skip-permissions", "Launches under this profile keep permission prompts.").option("--launch-remote-control", "Launches under this profile enable Remote Control.").option("--no-launch-remote-control", "Launches under this profile leave Remote Control off.").option("--launch-headroom", "Launches under this profile route through headroom.").option("--no-launch-headroom", "Launches under this profile route direct.").option("--launch-track-usage", "Launches under this profile route through the front door so their requests and quota are recorded, with no headroom needed.").option("--no-launch-track-usage", "Launches under this profile are not recorded unless a provider or headroom routes them anyway.").option("--launch-provider <provider>", "Launches under this profile route through this provider.").option("--no-launch-provider", "Clear this profile's provider selection.").option("--launch-claude-version <version>", "Launches under this profile run exactly this installed Claude Code version (such as 2.1.220); a version that is not installed fails the launch.").option("--no-launch-claude-version", "Clear this profile's Claude Code version pin.").option("--launch-delay <duration>", "Launches under this profile wait this long (such as 5s) after the launcher's own output before starting claude, so the output can be read.", parseDurationLiteral).option("--no-launch-delay", "Clear this profile's launch delay.").option("--launch-pause", "Launches under this profile wait for a key press after the launcher's own output before starting claude.").option("--no-launch-pause", "Launches under this profile start claude without waiting for a key press.").option("--launch-explain", "Launches under this profile that pick from a pool list every member the pick ranked and why, in the launcher's report.").option("--no-launch-explain", "Launches under this profile name only the member a pool pick chose.").option("--json", "Print the result as JSON.").action(async (name, allOptions) => {
112705
112845
  const { json: json2, ...options } = allOptions;
112706
112846
  requireProfileExists(paths, name);
112707
112847
  if (Object.entries(allOptions).every(([key, value2]) => key === "json" || value2 === void 0)) {
@@ -127603,7 +127743,8 @@ var ConfigProfileSetInputSchema = external_exports.strictObject({
127603
127743
  provider: external_exports.union([external_exports.string().min(1), external_exports.literal(false)]).optional(),
127604
127744
  claudeVersion: external_exports.union([external_exports.string().min(1), external_exports.literal(false)]).optional(),
127605
127745
  delay: external_exports.union([external_exports.string().regex(DURATION_RE), external_exports.literal(false)]).optional(),
127606
- pause: external_exports.boolean().optional()
127746
+ pause: external_exports.boolean().optional(),
127747
+ explain: external_exports.boolean().optional()
127607
127748
  }).optional()
127608
127749
  });
127609
127750
  var ConfigProfileSetOutputSchema = storedMutationOutput("profile", "updated", ProfileValueSchema);
@@ -127815,7 +127956,8 @@ function createConfigApiRouter(deps) {
127815
127956
  ...launch?.provider === void 0 ? {} : { launchProvider: launch.provider },
127816
127957
  ...launch?.claudeVersion === void 0 ? {} : { launchClaudeVersion: launch.claudeVersion },
127817
127958
  ...launch?.delay === void 0 ? {} : { launchDelay: launch.delay },
127818
- ...launch?.pause === void 0 ? {} : { launchPause: launch.pause }
127959
+ ...launch?.pause === void 0 ? {} : { launchPause: launch.pause },
127960
+ ...launch?.explain === void 0 ? {} : { launchExplain: launch.explain }
127819
127961
  });
127820
127962
  return { action: "updated", kind: "profile", name: input2.name, value: profileValue(input2.name, paths) };
127821
127963
  })
@@ -128116,6 +128258,7 @@ var LaunchFlagsSchema = external_exports.strictObject({
128116
128258
  headroom: external_exports.boolean(),
128117
128259
  trackUsage: external_exports.boolean(),
128118
128260
  pause: external_exports.boolean(),
128261
+ explain: external_exports.boolean(),
128119
128262
  /** How long the launch waits after its own output before it starts claude, in milliseconds. */
128120
128263
  delayMs: external_exports.number()
128121
128264
  });
@@ -146018,13 +146161,12 @@ init_cliError();
146018
146161
  init_schema();
146019
146162
  init_schema();
146020
146163
  init_realPorts();
146164
+ init_candidateText();
146021
146165
  init_preflight();
146022
146166
  function formatPoolPick(report, nowMs) {
146023
146167
  const head = report.pick === void 0 ? `Pool ${report.pool}: every member is refused right now${report.earliestReturn === void 0 ? "" : `; ${report.earliestReturn.identity} returns at ${report.earliestReturn.at} (in ${formatAge(Date.parse(report.earliestReturn.at) - nowMs)})`}` : `Pool ${report.pool}: a launch from ${report.directory} would run as ${report.pick}`;
146024
146168
  const rows = report.candidates.map((candidate, index) => {
146025
- const score = candidate.score === void 0 ? "" : ` score ${candidate.score.toFixed(2)}${candidate.scoreWindow === "fiveHour" ? " by 5h reset" : " by 7d reset"}`;
146026
- const dry = candidate.feasible ? "" : " (5h would run dry)";
146027
- return ` ${String(index + 1)}. ${candidate.identity} [${candidate.class}${score}]${dry}
146169
+ return ` ${String(index + 1)}. ${candidate.identity} ${candidateHeading(candidate)}
146028
146170
  ${candidate.reasons.join("; ")}`;
146029
146171
  });
146030
146172
  return [head, ...rows, ...report.missing.map((name) => ` (skipped: ${name} is not an identity)`), ...report.stickyProblem === void 0 ? [] : [`Note: ${report.stickyProblem}; the last-pick record was ignored.`]];
@@ -146924,11 +147066,12 @@ Launching:
146924
147066
  --[no-]wait with @pool:<name>, sleep until the earliest member returns when all are refused
146925
147067
  --delay <duration> wait this long (5s, 500ms) after the launcher's own output before starting claude
146926
147068
  --[no-]pause wait for a key press after the launcher's own output before starting claude
147069
+ --[no-]explain with @pool:<name>, list every member the pick ranked and why, not only the one picked
146927
147070
  --native run the real claude with nothing from agent-shim applied (no other launch flag allowed)
146928
147071
 
146929
147072
  Environment:
146930
147073
  AGENT_SHIM_IDENTITY, AGENT_SHIM_CONFIG_PROFILE, AGENT_SHIM_SKIP_PERMISSIONS,
146931
- AGENT_SHIM_REMOTE_CONTROL, AGENT_SHIM_HEADROOM, AGENT_SHIM_TRACK_USAGE, AGENT_SHIM_DELAY, AGENT_SHIM_PAUSE, AGENT_SHIM_ALLOW_AMBIENT_CREDENTIAL,
147074
+ AGENT_SHIM_REMOTE_CONTROL, AGENT_SHIM_HEADROOM, AGENT_SHIM_TRACK_USAGE, AGENT_SHIM_DELAY, AGENT_SHIM_PAUSE, AGENT_SHIM_EXPLAIN, AGENT_SHIM_ALLOW_AMBIENT_CREDENTIAL,
146932
147075
  AGENT_SHIM_CATEGORY_OVERRIDE, AGENT_SHIM_ENTRY_OVERRIDE, AGENT_SHIM_HOME,
146933
147076
  AGENT_SHIM_DEBUG (print stack traces), NO_COLOR. Booleans are true, false, 1 or 0.
146934
147077
 
@@ -147650,6 +147793,7 @@ function otherLaunchFlags(parsed) {
147650
147793
  ...parsed.claudeVersion === void 0 ? [] : ["--claude-version"],
147651
147794
  ...parsed.delay === void 0 ? [] : ["--delay"],
147652
147795
  ...parsed.pause === void 0 ? [] : ["--[no-]pause"],
147796
+ ...parsed.explain === void 0 ? [] : ["--[no-]explain"],
147653
147797
  ...parsed.headroom === void 0 ? [] : ["--[no-]headroom"],
147654
147798
  ...parsed.trackUsage === void 0 ? [] : ["--[no-]track-usage"],
147655
147799
  ...parsed.skipPermissions === void 0 ? [] : ["--[no-]skip-permissions"],