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/dist/index.cjs CHANGED
@@ -289,7 +289,9 @@ var init_schema = __esm({
289
289
  /** 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. */
290
290
  delay: import_zod.z.string().regex(DURATION_RE, "must be a duration such as 5s or 500ms").optional(),
291
291
  /** 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. */
292
- pause: import_zod.z.boolean().optional()
292
+ pause: import_zod.z.boolean().optional(),
293
+ /** 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. */
294
+ explain: import_zod.z.boolean().optional()
293
295
  });
294
296
  CREDENTIAL_TARGETS = ["bearer", "apiKey", "oauthToken"];
295
297
  PROVIDER_CREDENTIAL_TARGETS = ["bearer", "apiKey"];
@@ -1398,6 +1400,9 @@ function flattenLayers(layers, options) {
1398
1400
  if (layer.launch.pause !== void 0) {
1399
1401
  launch.pause = layer.launch.pause;
1400
1402
  }
1403
+ if (layer.launch.explain !== void 0) {
1404
+ launch.explain = layer.launch.explain;
1405
+ }
1401
1406
  }
1402
1407
  if (layer.entries === void 0) {
1403
1408
  continue;
@@ -1496,11 +1501,15 @@ var init_flatten = __esm({
1496
1501
  });
1497
1502
 
1498
1503
  // src/resolve/decide.ts
1499
- function unclassifiedEntryMessage(names) {
1504
+ function unclassifiedEntrySummary(names) {
1500
1505
  const quoted = names.map((name) => `"${name}"`).join(", ");
1501
- const subject = names.length === 1 ? `${quoted} is not` : `${String(names.length)} entries are not`;
1502
- const excluded = names.length === 1 ? "it is excluded" : `they are excluded: ${quoted}`;
1503
- 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.`;
1506
+ 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}`;
1507
+ }
1508
+ function unclassifiedEntryFix(names) {
1509
+ return `Run \`agent-shim configure\` to classify ${names.length === 1 ? "it" : "them"}`;
1510
+ }
1511
+ function unclassifiedEntryMessage(names) {
1512
+ return `${unclassifiedEntrySummary(names)}. ${unclassifiedEntryFix(names)}.`;
1504
1513
  }
1505
1514
  function selectRule(relPath, flattened, context) {
1506
1515
  const eliminated = [];
@@ -2974,7 +2983,7 @@ var init_package = __esm({
2974
2983
  "package.json"() {
2975
2984
  package_default = {
2976
2985
  name: "claude-use",
2977
- version: "11.28.0",
2986
+ version: "11.30.0",
2978
2987
  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.",
2979
2988
  license: "MIT",
2980
2989
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -4140,20 +4149,53 @@ var init_supervisor = __esm({
4140
4149
  }
4141
4150
  });
4142
4151
 
4143
- // src/logStyle.ts
4144
- function styledDiagnostic(style, colour, line) {
4145
- const lead = DIAGNOSTIC_LEAD.exec(line);
4146
- if (lead === null) {
4147
- return style([colour], line);
4152
+ // src/launcher/report.ts
4153
+ function renderReport(rows, style) {
4154
+ if (rows.length === 0) {
4155
+ return [];
4156
+ }
4157
+ const labelWidth = Math.max(...rows.map((row) => row.label.length));
4158
+ const indent = " ".repeat(COLUMN_GAP.length);
4159
+ const lines = [style(["bold"], REPORT_HEADING)];
4160
+ for (const row of rows) {
4161
+ const detail = row.detail === void 0 ? "" : ` ${style(["dim"], `(${row.detail})`)}`;
4162
+ lines.push(`${indent}${style(["dim"], row.label.padEnd(labelWidth))}${COLUMN_GAP}${row.value}${detail}`);
4163
+ for (const note of row.notes ?? []) {
4164
+ lines.push(`${indent}${" ".repeat(labelWidth)}${COLUMN_GAP}${style(["dim"], note)}`);
4165
+ }
4166
+ }
4167
+ return lines;
4168
+ }
4169
+ var REPORT_HEADING, COLUMN_GAP;
4170
+ var init_report = __esm({
4171
+ "src/launcher/report.ts"() {
4172
+ "use strict";
4173
+ REPORT_HEADING = "agent-shim";
4174
+ COLUMN_GAP = " ";
4148
4175
  }
4149
- const [whole, prefix = "", code = "", separator = ""] = lead;
4150
- return `${style([colour], prefix)}${style([colour, "bold"], code)}${style([colour], `${separator}${line.slice(whole.length)}`)}`;
4176
+ });
4177
+
4178
+ // src/logStyle.ts
4179
+ function styledDiagnostic(style, colour, text) {
4180
+ return text.split("\n").map((line, index) => {
4181
+ const lead = index === 0 ? DIAGNOSTIC_LEAD.exec(line) : null;
4182
+ if (lead === null) {
4183
+ return style([colour], line);
4184
+ }
4185
+ const [whole, prefix = "", code = "", separator = ""] = lead;
4186
+ return `${style([colour], prefix)}${style([colour, "bold"], code)}${style([colour], `${separator}${line.slice(whole.length)}`)}`;
4187
+ }).join("\n");
4151
4188
  }
4152
4189
  function createLogPort(sinks, styleFor) {
4153
4190
  return {
4154
4191
  info: (message) => {
4155
4192
  sinks.out(styleFor.out(["dim"], message));
4156
4193
  },
4194
+ report: (rows) => {
4195
+ for (const line of renderReport(rows, styleFor.out)) {
4196
+ sinks.out(line);
4197
+ }
4198
+ },
4157
4199
  warn: (message) => {
4158
4200
  sinks.warn(styledDiagnostic(styleFor.err, "yellow", message));
4159
4201
  },
@@ -4170,6 +4212,7 @@ var init_logStyle = __esm({
4170
4212
  "src/logStyle.ts"() {
4171
4213
  "use strict";
4172
4214
  import_node_util = require("node:util");
4215
+ init_report();
4173
4216
  DIAGNOSTIC_LEAD = /^(agent-shim: )([A-Z][A-Z0-9_]*)(: )/;
4174
4217
  }
4175
4218
  });
@@ -7540,7 +7583,8 @@ var init_argv = __esm({
7540
7583
  { flag: "--skip-permissions", key: "skipPermissions" },
7541
7584
  { flag: "--remote-control", key: "remoteControl" },
7542
7585
  { flag: "--wait", key: "wait" },
7543
- { flag: "--pause", key: "pause" }
7586
+ { flag: "--pause", key: "pause" },
7587
+ { flag: "--explain", key: "explain" }
7544
7588
  ];
7545
7589
  LAUNCHER_FLAG_NAMES = [
7546
7590
  ...VALUED_FLAGS,
@@ -7729,6 +7773,7 @@ function resolveLaunchFlags(params) {
7729
7773
  headroom: params.flags?.headroom ?? parseEnvBool("AGENT_SHIM_HEADROOM", params.env.AGENT_SHIM_HEADROOM) ?? params.cascade?.headroom ?? false,
7730
7774
  trackUsage: params.flags?.trackUsage ?? parseEnvBool("AGENT_SHIM_TRACK_USAGE", params.env.AGENT_SHIM_TRACK_USAGE) ?? params.cascade?.trackUsage ?? true,
7731
7775
  pause: params.flags?.pause ?? parseEnvBool("AGENT_SHIM_PAUSE", params.env.AGENT_SHIM_PAUSE) ?? params.cascade?.pause ?? false,
7776
+ explain: params.flags?.explain ?? parseEnvBool("AGENT_SHIM_EXPLAIN", params.env.AGENT_SHIM_EXPLAIN) ?? params.cascade?.explain ?? false,
7732
7777
  delayMs: resolveDelayMs(params)
7733
7778
  };
7734
7779
  }
@@ -8014,7 +8059,9 @@ function diagnosticLines(diagnostics) {
8014
8059
  if (diagnostic.code === "UNCLASSIFIED_ENTRY") {
8015
8060
  if (!unclassifiedReported) {
8016
8061
  unclassifiedReported = true;
8017
- lines.push({ severity: diagnostic.severity, text: `agent-shim: ${diagnostic.code}: ${unclassifiedEntryMessage(unclassified.filter((name) => name !== void 0))}` });
8062
+ const names = unclassified.filter((name) => name !== void 0);
8063
+ lines.push({ severity: diagnostic.severity, text: `agent-shim: ${diagnostic.code}: ${unclassifiedEntrySummary(names)}
8064
+ ${unclassifiedEntryFix(names)}.` });
8018
8065
  }
8019
8066
  continue;
8020
8067
  }
@@ -8022,8 +8069,8 @@ function diagnosticLines(diagnostics) {
8022
8069
  }
8023
8070
  return lines;
8024
8071
  }
8025
- function reportDiagnostics(log, diagnostics, options) {
8026
- for (const line of diagnosticLines(diagnostics)) {
8072
+ function printDiagnosticLines(log, lines, options) {
8073
+ for (const line of lines) {
8027
8074
  if (line.severity === "error" && !options.errorsAsWarnings) {
8028
8075
  log.error(line.text);
8029
8076
  } else {
@@ -8031,6 +8078,9 @@ function reportDiagnostics(log, diagnostics, options) {
8031
8078
  }
8032
8079
  }
8033
8080
  }
8081
+ function reportDiagnostics(log, diagnostics, options) {
8082
+ printDiagnosticLines(log, diagnosticLines(diagnostics), options);
8083
+ }
8034
8084
  var init_diagnostics = __esm({
8035
8085
  "src/launcher/diagnostics.ts"() {
8036
8086
  "use strict";
@@ -8063,6 +8113,79 @@ var init_hold = __esm({
8063
8113
  }
8064
8114
  });
8065
8115
 
8116
+ // src/usage/candidateText.ts
8117
+ function candidateHeading(candidate) {
8118
+ const score = candidate.score === void 0 ? "" : ` score ${candidate.score.toFixed(2)}${candidate.scoreWindow === "fiveHour" ? " by 5h reset" : " by 7d reset"}`;
8119
+ const dry = candidate.feasible ? "" : " (5h would run dry)";
8120
+ return `[${candidate.class}${score}]${dry}`;
8121
+ }
8122
+ var init_candidateText = __esm({
8123
+ "src/usage/candidateText.ts"() {
8124
+ "use strict";
8125
+ }
8126
+ });
8127
+
8128
+ // src/launcher/launchReport.ts
8129
+ function poolDetail(pool) {
8130
+ const [reason] = pool.reasons;
8131
+ if (pool.movedOff !== void 0) {
8132
+ return { detail: `moved off ${pool.movedOff.identity}: ${pool.movedOff.reason}`, ...reason === void 0 ? {} : { notes: [reason] } };
8133
+ }
8134
+ return reason === void 0 ? {} : { detail: reason };
8135
+ }
8136
+ function rankingNotes(ranking, picked) {
8137
+ return ranking.flatMap((candidate, index) => [
8138
+ `${String(index + 1)}. ${candidate.identity} ${candidateHeading(candidate)}${candidate.identity === picked ? " (picked)" : ""}`,
8139
+ ` ${candidate.reasons.join("; ")}`
8140
+ ]);
8141
+ }
8142
+ function decisionRows(facts) {
8143
+ return [
8144
+ { label: "identity", value: facts.identity ?? "(none)", detail: facts.identitySource },
8145
+ ...facts.pool === void 0 ? [] : [
8146
+ {
8147
+ label: "pool",
8148
+ value: facts.pool.name,
8149
+ ...poolDetail(facts.pool),
8150
+ ...facts.ranking === void 0 ? {} : { notes: rankingNotes(facts.ranking, facts.identity) }
8151
+ }
8152
+ ],
8153
+ ...facts.profile === void 0 ? [] : [{ label: "profile", value: facts.profile.name, detail: facts.profile.source }],
8154
+ ...facts.provider === void 0 ? [] : [{ label: "provider", value: facts.provider.name, detail: `credential ${facts.provider.credential}` }],
8155
+ ...facts.identityCredential === void 0 ? [] : [{ label: "credential", value: facts.identityCredential, detail: "the identity's own" }]
8156
+ ];
8157
+ }
8158
+ function pinnedVersionRow(version, source) {
8159
+ return { label: "claude", value: version, detail: `pinned by ${source}` };
8160
+ }
8161
+ function routingRows(facts) {
8162
+ if (facts.frontDoor === void 0) {
8163
+ return [];
8164
+ }
8165
+ return [
8166
+ {
8167
+ label: "routing",
8168
+ value: `front door 127.0.0.1:${String(facts.frontDoor.port)}`,
8169
+ ...facts.provider ? {} : { detail: `OAuth via CONNECT 127.0.0.1:${String(facts.frontDoor.connectPort)}` }
8170
+ },
8171
+ ...facts.headroom === void 0 ? [] : [{ label: "headroom", value: "on", detail: `project ${facts.headroom.projectId}` }]
8172
+ ];
8173
+ }
8174
+ function farmRow(links, builtDirectories, adopted) {
8175
+ const counted = (count, singular, plural) => `${String(count)} ${count === 1 ? singular : plural}`;
8176
+ const parts = [counted(links, "link", "links"), counted(builtDirectories, "built directory", "built directories"), ...adopted === 0 ? [] : [`${String(adopted)} adopted`]];
8177
+ return { label: "farm", value: "resynced", detail: parts.join(", ") };
8178
+ }
8179
+ function noteRow(text) {
8180
+ return { label: "note", value: text };
8181
+ }
8182
+ var init_launchReport = __esm({
8183
+ "src/launcher/launchReport.ts"() {
8184
+ "use strict";
8185
+ init_candidateText();
8186
+ }
8187
+ });
8188
+
8066
8189
  // src/antigravity/cloudUpstream.ts
8067
8190
  var init_cloudUpstream = __esm({
8068
8191
  "src/antigravity/cloudUpstream.ts"() {
@@ -8445,6 +8568,7 @@ function resolvePoolLaunch(params) {
8445
8568
  identity: pick.identity,
8446
8569
  explanation: `pool ${poolName}: ${move}${pick.reasons.slice(0, REASONS_LOGGED).join("; ")}`,
8447
8570
  reasons: pick.reasons,
8571
+ candidates: graph.ranking.candidates,
8448
8572
  ...movedOff === void 0 ? {} : { movedOff }
8449
8573
  };
8450
8574
  }
@@ -8588,7 +8712,7 @@ function pickFromPool(decided, params, parsedArgv, readOnly) {
8588
8712
  }
8589
8713
  if (params.supervised?.member !== void 0) {
8590
8714
  const reasons = ["resumed here by the supervising launcher after the previous member ran out of quota"];
8591
- return { identityDecision: { ...decided, name: params.supervised.member }, poolExplanation: `pool ${decided.pool}: ${reasons.join("; ")}`, poolPick: { name: decided.pool, reasons } };
8715
+ return { identityDecision: { ...decided, name: params.supervised.member }, poolPick: { name: decided.pool, reasons } };
8592
8716
  }
8593
8717
  const farmRuntime = params.farm;
8594
8718
  if (farmRuntime === void 0) {
@@ -8619,8 +8743,8 @@ function pickFromPool(decided, params, parsedArgv, readOnly) {
8619
8743
  }
8620
8744
  return {
8621
8745
  identityDecision: { ...decided, name: resolution.identity },
8622
- poolExplanation: resolution.explanation,
8623
- poolPick: { name: decided.pool, reasons: resolution.reasons, ...resolution.movedOff === void 0 ? {} : { movedOff: resolution.movedOff } }
8746
+ poolPick: { name: decided.pool, reasons: resolution.reasons, ...resolution.movedOff === void 0 ? {} : { movedOff: resolution.movedOff } },
8747
+ poolRanking: resolution.candidates
8624
8748
  };
8625
8749
  }
8626
8750
  function decideLaunch(params, readOnly) {
@@ -8647,7 +8771,7 @@ function decideLaunch(params, readOnly) {
8647
8771
  return trimmed === "" ? void 0 : trimmed;
8648
8772
  }
8649
8773
  });
8650
- const { identityDecision, poolExplanation, poolPick } = pickFromPool(decidedIdentity, params, parsedArgv, readOnly);
8774
+ const { identityDecision, poolPick, poolRanking } = pickFromPool(decidedIdentity, params, parsedArgv, readOnly);
8651
8775
  const farmIdentity = configDirEscapeHatchApplies ? void 0 : identityDecision.name;
8652
8776
  const farm = farmIdentity === void 0 ? void 0 : params.farm;
8653
8777
  if (!readOnly && farm !== void 0 && farmIdentity !== void 0) {
@@ -8783,19 +8907,21 @@ function decideLaunch(params, readOnly) {
8783
8907
  ...parsedArgv.headroom === void 0 ? {} : { headroom: parsedArgv.headroom },
8784
8908
  ...parsedArgv.trackUsage === void 0 ? {} : { trackUsage: parsedArgv.trackUsage },
8785
8909
  ...parsedArgv.pause === void 0 ? {} : { pause: parsedArgv.pause },
8910
+ ...parsedArgv.explain === void 0 ? {} : { explain: parsedArgv.explain },
8786
8911
  ...parsedArgv.delay === void 0 ? {} : { delay: parsedArgv.delay }
8787
8912
  }
8788
8913
  });
8789
8914
  const loginlessProvider = requestedFlags.remoteControl && selectedProvider !== void 0 && farmIdentity !== void 0 && params.hasStoredLogin?.(farmIdentity) === false ? { identity: farmIdentity, provider: selectedProvider.name } : void 0;
8790
- if (loginlessProvider !== void 0 && !readOnly) {
8791
- 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`);
8915
+ const notes = [];
8916
+ if (loginlessProvider !== void 0) {
8917
+ notes.push(`${loginlessProvider.identity} has no stored login, so Remote Control is off; provider ${loginlessProvider.provider} runs without it`);
8792
8918
  }
8793
8919
  const flags = loginlessProvider === void 0 ? requestedFlags : { ...requestedFlags, remoteControl: false };
8794
8920
  const catalogue = selectedProvider === void 0 ? void 0 : parseCatalogueCache(params.fs.readFileUtf8(catalogueCachePath(paths, selectedProvider.name)));
8795
8921
  const pickerSettings = selectedProvider === void 0 ? void 0 : modelPickerSettings(selectedProvider.definition, catalogue?.models);
8796
8922
  const callerSettings = hasSettingsArgument(parsedArgv.rest);
8797
- if (pickerSettings !== void 0 && callerSettings && !readOnly) {
8798
- 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");
8923
+ if (pickerSettings !== void 0 && callerSettings) {
8924
+ notes.push("--settings was passed, so /model keeps Claude Code's own model names");
8799
8925
  }
8800
8926
  const launcherSettings = mergeSettings([params.supervised?.settings, callerSettings ? void 0 : pickerSettings]);
8801
8927
  const args = buildArgv({
@@ -8817,8 +8943,9 @@ function decideLaunch(params, readOnly) {
8817
8943
  return {
8818
8944
  parsedArgv,
8819
8945
  identityDecision,
8820
- poolExplanation,
8821
8946
  poolPick,
8947
+ poolRanking,
8948
+ notes,
8822
8949
  configDirEscapeHatch: configDirEscapeHatchApplies,
8823
8950
  farmIdentity,
8824
8951
  farmContext,
@@ -8838,10 +8965,19 @@ function prepareLaunch(params) {
8838
8965
  const { paths, proc, log } = params;
8839
8966
  const { env } = proc;
8840
8967
  const decided = decideLaunch(params, false);
8841
- const { identityDecision, configProfileDecision, resolvedProvider, identityCredential, poolExplanation, flags: resolvedFlags, args: finalArgv, configDirEscapeHatch: configDirEscapeHatchApplies, decision } = decided;
8842
- log.info(
8843
- `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)}`)
8844
- );
8968
+ const { identityDecision, configProfileDecision, resolvedProvider, identityCredential, poolPick, poolRanking, notes, flags: resolvedFlags, args: finalArgv, configDirEscapeHatch: configDirEscapeHatchApplies, decision } = decided;
8969
+ const rows = [
8970
+ ...decisionRows({
8971
+ identity: identityDecision.name,
8972
+ identitySource: identityDecision.source,
8973
+ pool: poolPick,
8974
+ ranking: resolvedFlags.explain ? poolRanking : void 0,
8975
+ profile: configProfileDecision.name === void 0 ? void 0 : { name: configProfileDecision.name, source: configProfileDecision.source },
8976
+ provider: resolvedProvider === void 0 ? void 0 : { name: resolvedProvider.name, credential: `${resolvedProvider.credential.target} from ${describeSource(resolvedProvider.credential.source)}` },
8977
+ identityCredential: identityCredential === void 0 ? void 0 : `${identityCredential.target} from ${describeSource(identityCredential.source)}`
8978
+ })
8979
+ ];
8980
+ let warnings = [];
8845
8981
  const updateCheck = runLaunchUpdateCheck({
8846
8982
  mode: params.updateMode ?? "off",
8847
8983
  checkPath: import_node_path39.default.join(paths.root, "update.check"),
@@ -8876,15 +9012,13 @@ function prepareLaunch(params) {
8876
9012
  }
8877
9013
  throw error;
8878
9014
  }
8879
- reportDiagnostics(log, result.diagnostics, { errorsAsWarnings: false });
9015
+ warnings = diagnosticLines(result.diagnostics);
8880
9016
  if (!result.noOp) {
8881
- log.info(
8882
- `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}`})`
8883
- );
9017
+ rows.push(farmRow(result.manifest.links.length, result.manifest.materialised.length, result.adopted.length));
8884
9018
  }
8885
9019
  }
8886
9020
  if (decided.pinnedVersion !== void 0) {
8887
- log.info(`agent-shim: Claude Code ${decided.pinnedVersion.version} (pinned by ${decided.pinnedVersion.source})`);
9021
+ rows.push(pinnedVersionRow(decided.pinnedVersion.version, decided.pinnedVersion.source));
8888
9022
  }
8889
9023
  const frontDoorPort = params.frontdoor;
8890
9024
  const frontDoorEngaged = resolvedProvider !== void 0 || resolvedFlags.headroom || resolvedFlags.trackUsage;
@@ -8900,14 +9034,11 @@ function prepareLaunch(params) {
8900
9034
  const headroomPort = params.headroom;
8901
9035
  if (resolvedFlags.headroom && headroomPort !== void 0) {
8902
9036
  headroom = headroomPort.ensure({ routesProvider: resolvedProvider !== void 0 });
8903
- const via = resolvedProvider === void 0 ? `OAuth via the door's CONNECT surface on 127.0.0.1:${String(frontDoor?.connectPort ?? 0)}` : `provider ${resolvedProvider.name}`;
8904
- 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})`);
8905
9037
  } else if (resolvedFlags.headroom) {
8906
9038
  log.error("agent-shim: headroom routing was requested but this launcher has no headroom port wired; refusing to launch without it.");
8907
9039
  proc.exit(1);
8908
- } else if (frontDoor !== void 0) {
8909
- 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})`}`);
8910
9040
  }
9041
+ rows.push(...routingRows({ frontDoor, headroom, provider: resolvedProvider !== void 0 }));
8911
9042
  const frontDoorRelease = frontDoor === void 0 ? void 0 : frontDoorPort?.release;
8912
9043
  const sessionId = params.supervised?.sessionId ?? (0, import_node_crypto11.randomUUID)();
8913
9044
  const finalEnv = buildEnv({
@@ -8928,6 +9059,9 @@ function prepareLaunch(params) {
8928
9059
  registered();
8929
9060
  }
8930
9061
  };
9062
+ rows.push(...notes.map(noteRow));
9063
+ log.report(rows);
9064
+ printDiagnosticLines(log, warnings, { errorsAsWarnings: false });
8931
9065
  const hold = () => holdBeforeLaunch({ delayMs: resolvedFlags.delayMs, pause: resolvedFlags.pause }, params.hold, log);
8932
9066
  return { bin: decided.bin, args: finalArgv, env: finalEnv, sessionId, release, markChildStarted: updateCheck.markChildStarted, hold, decision };
8933
9067
  }
@@ -8996,6 +9130,7 @@ var init_launcher = __esm({
8996
9130
  init_claudeSession();
8997
9131
  init_diagnostics();
8998
9132
  init_hold();
9133
+ init_launchReport();
8999
9134
  init_modelPicker();
9000
9135
  init_providerCatalogue();
9001
9136
  init_pool();
@@ -9219,6 +9354,7 @@ function prepareClaudeLaunch(options) {
9219
9354
  const refusals = [];
9220
9355
  const log = {
9221
9356
  info: () => void 0,
9357
+ report: () => void 0,
9222
9358
  warn: () => void 0,
9223
9359
  error: (message) => {
9224
9360
  refusals.push(message);
@@ -9240,6 +9376,7 @@ function resolveClaudeLaunch(options) {
9240
9376
  const warnings = [];
9241
9377
  const log = {
9242
9378
  info: () => void 0,
9379
+ report: () => void 0,
9243
9380
  warn: (message) => {
9244
9381
  warnings.push(message);
9245
9382
  },
@@ -9448,6 +9585,7 @@ async function withIdentityClaude(params, identity, flags, use) {
9448
9585
  },
9449
9586
  log: {
9450
9587
  info: () => void 0,
9588
+ report: () => void 0,
9451
9589
  warn: () => void 0,
9452
9590
  error: (message) => {
9453
9591
  refusals.push(message);
@@ -13843,6 +13981,9 @@ function applyProfileChange(paths, name, change) {
13843
13981
  if (change.launchPause !== void 0) {
13844
13982
  launchPatch.pause = change.launchPause;
13845
13983
  }
13984
+ if (change.launchExplain !== void 0) {
13985
+ launchPatch.explain = change.launchExplain;
13986
+ }
13846
13987
  if (Object.keys(launchPatch).length > 0) {
13847
13988
  setProfileLaunchFlags(paths, name, launchPatch);
13848
13989
  touched = true;
@@ -16060,7 +16201,8 @@ var ConfigProfileSetInputSchema = import_zod24.z.strictObject({
16060
16201
  provider: import_zod24.z.union([import_zod24.z.string().min(1), import_zod24.z.literal(false)]).optional(),
16061
16202
  claudeVersion: import_zod24.z.union([import_zod24.z.string().min(1), import_zod24.z.literal(false)]).optional(),
16062
16203
  delay: import_zod24.z.union([import_zod24.z.string().regex(DURATION_RE), import_zod24.z.literal(false)]).optional(),
16063
- pause: import_zod24.z.boolean().optional()
16204
+ pause: import_zod24.z.boolean().optional(),
16205
+ explain: import_zod24.z.boolean().optional()
16064
16206
  }).optional()
16065
16207
  });
16066
16208
  var ConfigProfileSetOutputSchema = storedMutationOutput("profile", "updated", ProfileValueSchema);
@@ -16272,7 +16414,8 @@ function createConfigApiRouter(deps) {
16272
16414
  ...launch?.provider === void 0 ? {} : { launchProvider: launch.provider },
16273
16415
  ...launch?.claudeVersion === void 0 ? {} : { launchClaudeVersion: launch.claudeVersion },
16274
16416
  ...launch?.delay === void 0 ? {} : { launchDelay: launch.delay },
16275
- ...launch?.pause === void 0 ? {} : { launchPause: launch.pause }
16417
+ ...launch?.pause === void 0 ? {} : { launchPause: launch.pause },
16418
+ ...launch?.explain === void 0 ? {} : { launchExplain: launch.explain }
16276
16419
  });
16277
16420
  return { action: "updated", kind: "profile", name: input.name, value: profileValue(input.name, paths) };
16278
16421
  })
@@ -16582,6 +16725,7 @@ var LaunchFlagsSchema = import_zod26.z.strictObject({
16582
16725
  headroom: import_zod26.z.boolean(),
16583
16726
  trackUsage: import_zod26.z.boolean(),
16584
16727
  pause: import_zod26.z.boolean(),
16728
+ explain: import_zod26.z.boolean(),
16585
16729
  /** How long the launch waits after its own output before it starts claude, in milliseconds. */
16586
16730
  delayMs: import_zod26.z.number()
16587
16731
  });