claude-use 9.7.1 → 9.8.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
@@ -2663,7 +2663,7 @@ var init_package = __esm({
2663
2663
  "package.json"() {
2664
2664
  package_default = {
2665
2665
  name: "claude-use",
2666
- version: "9.7.1",
2666
+ version: "9.8.0",
2667
2667
  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.",
2668
2668
  license: "MIT",
2669
2669
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -6567,7 +6567,7 @@ function buildEnv(params) {
6567
6567
  const parentCustomHeaders = params.baseEnv.ANTHROPIC_CUSTOM_HEADERS;
6568
6568
  let providerCustomHeaders;
6569
6569
  if (!params.configDirEscapeHatch && params.resolvedIdentityName !== void 0) {
6570
- env.CLAUDE_CONFIG_DIR = import_node_path32.default.join(params.identitiesDir, params.resolvedIdentityName);
6570
+ env.CLAUDE_CONFIG_DIR = import_node_path33.default.join(params.identitiesDir, params.resolvedIdentityName);
6571
6571
  }
6572
6572
  if (params.provider !== void 0) {
6573
6573
  const providerEnv = params.provider.definition.env ?? {};
@@ -6611,11 +6611,11 @@ function buildEnv(params) {
6611
6611
  }
6612
6612
  return env;
6613
6613
  }
6614
- var import_node_path32, LOOPBACK_HOSTS;
6614
+ var import_node_path33, LOOPBACK_HOSTS;
6615
6615
  var init_flags = __esm({
6616
6616
  "src/launcher/flags.ts"() {
6617
6617
  "use strict";
6618
- import_node_path32 = __toESM(require("node:path"), 1);
6618
+ import_node_path33 = __toESM(require("node:path"), 1);
6619
6619
  init_envBool();
6620
6620
  init_credential();
6621
6621
  init_headers();
@@ -6938,7 +6938,7 @@ function decideLaunch(params, readOnly) {
6938
6938
  identityDefaultConfigProfile: loadedIdentity?.config.defaultConfigProfile,
6939
6939
  globalDefaultConfigProfile: params.globalDefaultConfigProfile
6940
6940
  });
6941
- if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(import_node_path33.default.join(paths.configProfilesDir, `${configProfileDecision.name}.json`)) === void 0) {
6941
+ if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(import_node_path34.default.join(paths.configProfilesDir, `${configProfileDecision.name}.json`)) === void 0) {
6942
6942
  log.error(
6943
6943
  `agent-shim: no configuration profile named "${configProfileDecision.name}" (selected via ${configProfileDecision.source}). Run \`agent-shim profile add ${configProfileDecision.name}\` first.`
6944
6944
  );
@@ -7017,10 +7017,16 @@ function decideLaunch(params, readOnly) {
7017
7017
  const assembled = assembleCascade(launchCascade);
7018
7018
  const flattened = flattenLayers(assembled.layers, { home: params.farm.home });
7019
7019
  cascadeLaunch = flattened.launch;
7020
- if (readOnly) {
7020
+ if (readOnly || farmContext === void 0) {
7021
7021
  for (const diagnostic of [...assembled.diagnostics, ...flattened.diagnostics]) {
7022
- if (diagnostic.severity !== "info") {
7023
- log.warn(`agent-shim: ${diagnostic.code}: ${diagnostic.message}`);
7022
+ if (diagnostic.severity === "info") {
7023
+ continue;
7024
+ }
7025
+ const message = `agent-shim: ${diagnostic.code}: ${diagnostic.message}`;
7026
+ if (diagnostic.severity === "error" && !readOnly) {
7027
+ log.error(message);
7028
+ } else {
7029
+ log.warn(message);
7024
7030
  }
7025
7031
  }
7026
7032
  }
@@ -7044,7 +7050,7 @@ function decideLaunch(params, readOnly) {
7044
7050
  extraFlags: splitExtraFlags(env.CLAUDE_EXTRA_FLAGS),
7045
7051
  passthrough: parsedArgv.rest
7046
7052
  });
7047
- const configDir = configDirEscapeHatchApplies || identityDecision.name === void 0 ? env.CLAUDE_CONFIG_DIR : import_node_path33.default.join(paths.identitiesDir, identityDecision.name);
7053
+ const configDir = configDirEscapeHatchApplies || identityDecision.name === void 0 ? env.CLAUDE_CONFIG_DIR : import_node_path34.default.join(paths.identitiesDir, identityDecision.name);
7048
7054
  const decision = {
7049
7055
  identitySource: identityDecision.source,
7050
7056
  configDirEscapeHatch: identityDecision.configDirEscapeHatch,
@@ -7085,7 +7091,7 @@ function prepareLaunch(params) {
7085
7091
  );
7086
7092
  const updateCheck = runLaunchUpdateCheck({
7087
7093
  mode: params.updateMode ?? "off",
7088
- checkPath: import_node_path33.default.join(paths.root, "update.check"),
7094
+ checkPath: import_node_path34.default.join(paths.root, "update.check"),
7089
7095
  currentVersion: package_default.version,
7090
7096
  port: params.update
7091
7097
  });
@@ -7216,12 +7222,12 @@ function runLaunchPlan(plan, spawn2) {
7216
7222
  function runLauncher(params) {
7217
7223
  params.proc.exit(runLaunchPlan(prepareLaunch(params), params.spawn));
7218
7224
  }
7219
- var import_node_crypto10, import_node_path33;
7225
+ var import_node_crypto10, import_node_path34;
7220
7226
  var init_launcher = __esm({
7221
7227
  "src/launcher.ts"() {
7222
7228
  "use strict";
7223
7229
  import_node_crypto10 = require("node:crypto");
7224
- import_node_path33 = __toESM(require("node:path"), 1);
7230
+ import_node_path34 = __toESM(require("node:path"), 1);
7225
7231
  init_package();
7226
7232
  init_envBool();
7227
7233
  init_argv();
@@ -7252,13 +7258,13 @@ function agentShimCliPath(distDir = typeof __AGENT_SHIM_DIST_DIR__ === "string"
7252
7258
  if (distDir === void 0) {
7253
7259
  throw new OwnCliPathUnknownError();
7254
7260
  }
7255
- return import_node_path34.default.join(distDir, OWN_CLI_FILE_NAME);
7261
+ return import_node_path35.default.join(distDir, OWN_CLI_FILE_NAME);
7256
7262
  }
7257
- var import_node_path34, OWN_CLI_FILE_NAME, OwnCliPathUnknownError;
7263
+ var import_node_path35, OWN_CLI_FILE_NAME, OwnCliPathUnknownError;
7258
7264
  var init_ownCli = __esm({
7259
7265
  "src/ownCli.ts"() {
7260
7266
  "use strict";
7261
- import_node_path34 = __toESM(require("node:path"), 1);
7267
+ import_node_path35 = __toESM(require("node:path"), 1);
7262
7268
  init_cliError();
7263
7269
  OWN_CLI_FILE_NAME = "cli.cjs";
7264
7270
  OwnCliPathUnknownError = class extends CliError {
@@ -7343,7 +7349,7 @@ request.on("error", (error) => finish(failed, (error.code ? error.code + ": " :
7343
7349
  // src/frontdoor/trust.ts
7344
7350
  function resolveTrustBundle(params) {
7345
7351
  const { caCertFile, bundlesDir, variable, inherited, fs: fs12 } = params;
7346
- if (inherited === void 0 || inherited === "" || import_node_path35.default.resolve(inherited) === import_node_path35.default.resolve(caCertFile)) {
7352
+ if (inherited === void 0 || inherited === "" || import_node_path36.default.resolve(inherited) === import_node_path36.default.resolve(caCertFile)) {
7347
7353
  return { path: caCertFile };
7348
7354
  }
7349
7355
  const caPem = fs12.readFileUtf8(caCertFile);
@@ -7361,19 +7367,19 @@ function resolveTrustBundle(params) {
7361
7367
  }
7362
7368
  const combined = `${inheritedPem.trimEnd()}
7363
7369
  ${caPem}`;
7364
- const bundle = import_node_path35.default.join(bundlesDir, `${(0, import_node_crypto11.createHash)("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
7370
+ const bundle = import_node_path36.default.join(bundlesDir, `${(0, import_node_crypto11.createHash)("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
7365
7371
  if (!fs12.exists(bundle)) {
7366
7372
  fs12.mkdirp(bundlesDir);
7367
7373
  fs12.writeFileAtomic(bundle, combined);
7368
7374
  }
7369
7375
  return { path: bundle };
7370
7376
  }
7371
- var import_node_crypto11, import_node_path35, BUNDLE_NAME_HEX_DIGITS;
7377
+ var import_node_crypto11, import_node_path36, BUNDLE_NAME_HEX_DIGITS;
7372
7378
  var init_trust = __esm({
7373
7379
  "src/frontdoor/trust.ts"() {
7374
7380
  "use strict";
7375
7381
  import_node_crypto11 = require("node:crypto");
7376
- import_node_path35 = __toESM(require("node:path"), 1);
7382
+ import_node_path36 = __toESM(require("node:path"), 1);
7377
7383
  BUNDLE_NAME_HEX_DIGITS = 16;
7378
7384
  }
7379
7385
  });
@@ -8717,8 +8723,8 @@ function parseConnectTarget(authority) {
8717
8723
  function isInterceptedHost(host, interceptHosts) {
8718
8724
  return interceptHosts.includes(host);
8719
8725
  }
8720
- function servedByPipeline(path36) {
8721
- return path36?.startsWith(ROUTED_PATH_PREFIX) === true;
8726
+ function servedByPipeline(path37) {
8727
+ return path37?.startsWith(ROUTED_PATH_PREFIX) === true;
8722
8728
  }
8723
8729
  var HOP_BY_HOP_HEADERS = /* @__PURE__ */ new Set([
8724
8730
  "connection",
@@ -9253,11 +9259,11 @@ function createRcSessionTracker(deps) {
9253
9259
  };
9254
9260
  const observeExchange = (request4) => {
9255
9261
  const method = (request4.method ?? "").toUpperCase();
9256
- const path36 = new URL(request4.url ?? "/", "http://127.0.0.1").pathname;
9257
- if (!path36.startsWith(RC_SESSIONS_PATH_PREFIX)) {
9262
+ const path37 = new URL(request4.url ?? "/", "http://127.0.0.1").pathname;
9263
+ if (!path37.startsWith(RC_SESSIONS_PATH_PREFIX)) {
9258
9264
  return void 0;
9259
9265
  }
9260
- const tail = path36.slice(RC_SESSIONS_PATH_PREFIX.length);
9266
+ const tail = path37.slice(RC_SESSIONS_PATH_PREFIX.length);
9261
9267
  const facts = {
9262
9268
  oauthAuthorization: oauthAuthorizationOf(request4.headers),
9263
9269
  anthropicVersion: singleHeader(request4.headers, "anthropic-version"),
@@ -9639,8 +9645,8 @@ var RC_READ_FILE_ENCODINGS = ["utf-8", "base64"];
9639
9645
  function isRcReadFileEncoding(value) {
9640
9646
  return RC_READ_FILE_ENCODINGS.some((encoding) => encoding === value);
9641
9647
  }
9642
- function buildRcReadFilePayload(requestId, path36, options) {
9643
- return buildRcControlRequestPayload(requestId, { subtype: "read_file", path: path36, ...options?.maxBytes === void 0 ? {} : { max_bytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } });
9648
+ function buildRcReadFilePayload(requestId, path37, options) {
9649
+ return buildRcControlRequestPayload(requestId, { subtype: "read_file", path: path37, ...options?.maxBytes === void 0 ? {} : { max_bytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } });
9644
9650
  }
9645
9651
  function buildRcFileSuggestionsPayload(requestId, query) {
9646
9652
  return buildRcControlRequestPayload(requestId, { subtype: "file_suggestions", query });
@@ -9742,15 +9748,15 @@ async function getRcSessionContextUsage(deps, sessionId, detail) {
9742
9748
  const result = await deliverRcClientPayload(deps, sessionId, buildRcGetContextUsagePayload(requestId, detail), `request the context usage of session ${sessionId}`);
9743
9749
  return result.ok ? { ...result, requestId } : result;
9744
9750
  }
9745
- async function readRcSessionFile(deps, sessionId, path36, options) {
9746
- if (path36 === "") {
9751
+ async function readRcSessionFile(deps, sessionId, path37, options) {
9752
+ if (path37 === "") {
9747
9753
  return { ok: false, message: "a read-file write needs a non-empty path: the SDK's own field names the file the worker resolves against the session's cwd, and an empty string names none" };
9748
9754
  }
9749
9755
  if (options?.maxBytes !== void 0 && (!Number.isInteger(options.maxBytes) || options.maxBytes <= 0)) {
9750
9756
  return { ok: false, message: "a read-file write's max-bytes is a positive whole number of bytes: the SDK's own field caps the read, and a zero or negative cap reads nothing" };
9751
9757
  }
9752
9758
  const requestId = deps.newUuid();
9753
- const result = await deliverRcClientPayload(deps, sessionId, buildRcReadFilePayload(requestId, path36, options), `read ${path36} from session ${sessionId}`);
9759
+ const result = await deliverRcClientPayload(deps, sessionId, buildRcReadFilePayload(requestId, path37, options), `read ${path37} from session ${sessionId}`);
9754
9760
  return result.ok ? { ...result, requestId } : result;
9755
9761
  }
9756
9762
  async function suggestRcSessionFiles(deps, sessionId, query) {
@@ -9919,11 +9925,11 @@ function createRcControlHandler(deps) {
9919
9925
  path: "read-file",
9920
9926
  read: (body) => {
9921
9927
  const session = bodyString(body, "session");
9922
- const path36 = bodyString(body, "path");
9928
+ const path37 = bodyString(body, "path");
9923
9929
  const maxBytes = "maxBytes" in body ? bodyPositiveInteger(body, "maxBytes") : void 0;
9924
9930
  const encoding = "encoding" in body && isRcReadFileEncoding(body.encoding) ? body.encoding : void 0;
9925
- const refused2 = session === void 0 || path36 === void 0 || "maxBytes" in body && maxBytes === void 0 || "encoding" in body && encoding === void 0;
9926
- return refused2 ? { error: `the read-file body must be JSON naming a non-empty session id and path, maxBytes only as a positive whole number or absent, and an encoding the SDK's own type permits (${RC_READ_FILE_ENCODINGS.join(", ")}) or none` } : { session, run: async () => await deps.readFile(session, path36, { ...maxBytes === void 0 ? {} : { maxBytes }, ...encoding === void 0 ? {} : { encoding } }) };
9931
+ const refused2 = session === void 0 || path37 === void 0 || "maxBytes" in body && maxBytes === void 0 || "encoding" in body && encoding === void 0;
9932
+ return refused2 ? { error: `the read-file body must be JSON naming a non-empty session id and path, maxBytes only as a positive whole number or absent, and an encoding the SDK's own type permits (${RC_READ_FILE_ENCODINGS.join(", ")}) or none` } : { session, run: async () => await deps.readFile(session, path37, { ...maxBytes === void 0 ? {} : { maxBytes }, ...encoding === void 0 ? {} : { encoding } }) };
9927
9933
  }
9928
9934
  },
9929
9935
  {
@@ -10233,9 +10239,9 @@ function requestIdOfBody(body) {
10233
10239
  }
10234
10240
  function frontDoorRcControl(transport, token) {
10235
10241
  const headers = { authorization: `Bearer ${token}` };
10236
- const listAnswerOf = async (path36, what) => {
10242
+ const listAnswerOf = async (path37, what) => {
10237
10243
  try {
10238
- return await transport.request({ method: "GET", path: path36, headers });
10244
+ return await transport.request({ method: "GET", path: path37, headers });
10239
10245
  } catch (error) {
10240
10246
  throw new Error(`${what}: could not reach the front door's control listener: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
10241
10247
  }
@@ -10307,10 +10313,10 @@ function frontDoorRcControl(transport, token) {
10307
10313
  }
10308
10314
  return pending;
10309
10315
  };
10310
- const writeOf = async (path36, body, describeFailure) => {
10316
+ const writeOf = async (path37, body, describeFailure) => {
10311
10317
  let answer;
10312
10318
  try {
10313
- answer = await transport.request({ method: "POST", path: path36, headers: { ...headers, "content-type": "application/json" }, body });
10319
+ answer = await transport.request({ method: "POST", path: path37, headers: { ...headers, "content-type": "application/json" }, body });
10314
10320
  } catch (error) {
10315
10321
  return { ok: false, message: `could not reach the front door's control listener: ${error instanceof Error ? error.message : String(error)}` };
10316
10322
  }
@@ -10341,10 +10347,10 @@ function frontDoorRcControl(transport, token) {
10341
10347
  endSession: async (sessionId, reason) => await writeOf(`${CONTROL_PATH_PREFIX}/end-session`, JSON.stringify({ session: sessionId, ...reason === void 0 ? {} : { reason } }), (status, message) => `ending ${sessionId} failed (HTTP ${String(status)}): ${message}`),
10342
10348
  getUsage: async (sessionId, skipBehaviors) => await writeOf(`${CONTROL_PATH_PREFIX}/get-usage`, JSON.stringify({ session: sessionId, ...skipBehaviors === void 0 ? {} : { skipBehaviors } }), (status, message) => `requesting the usage of ${sessionId} failed (HTTP ${String(status)}): ${message}`),
10343
10349
  getContextUsage: async (sessionId, detail) => await writeOf(`${CONTROL_PATH_PREFIX}/get-context-usage`, JSON.stringify({ session: sessionId, ...detail === void 0 ? {} : { detail } }), (status, message) => `requesting the context usage of ${sessionId} failed (HTTP ${String(status)}): ${message}`),
10344
- readFile: async (sessionId, path36, options) => await writeOf(
10350
+ readFile: async (sessionId, path37, options) => await writeOf(
10345
10351
  `${CONTROL_PATH_PREFIX}/read-file`,
10346
- JSON.stringify({ session: sessionId, path: path36, ...options?.maxBytes === void 0 ? {} : { maxBytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } }),
10347
- (status, message) => `reading ${path36} from ${sessionId} failed (HTTP ${String(status)}): ${message}`
10352
+ JSON.stringify({ session: sessionId, path: path37, ...options?.maxBytes === void 0 ? {} : { maxBytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } }),
10353
+ (status, message) => `reading ${path37} from ${sessionId} failed (HTTP ${String(status)}): ${message}`
10348
10354
  ),
10349
10355
  fileSuggestions: async (sessionId, query) => await writeOf(`${CONTROL_PATH_PREFIX}/file-suggestions`, JSON.stringify({ session: sessionId, query }), (status, message) => `requesting file suggestions from ${sessionId} failed (HTTP ${String(status)}): ${message}`),
10350
10356
  keepAlive: async (sessionId) => await writeOf(`${CONTROL_PATH_PREFIX}/keep-alive`, JSON.stringify({ session: sessionId }), (status, message) => `keeping ${sessionId} alive failed (HTTP ${String(status)}): ${message}`),
@@ -10503,12 +10509,12 @@ function tlsFacts(options) {
10503
10509
  }
10504
10510
  function realRcEventDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_PORT }) {
10505
10511
  const agent = new ExemptTlsAgent();
10506
- const post = async (path36, headers, body) => await new Promise((resolve, reject) => {
10512
+ const post = async (path37, headers, body) => await new Promise((resolve, reject) => {
10507
10513
  const options = {
10508
10514
  host: target.host,
10509
10515
  port: target.port,
10510
10516
  method: "POST",
10511
- path: path36,
10517
+ path: path37,
10512
10518
  // The Host header names the host whose API this is, not the address dialled: a redirected test dials a loopback stand-in while still speaking to the API host by name, exactly as the forwarded paths present their SNI.
10513
10519
  headers: { ...headers, host: target.servername ?? target.host, "content-length": String(Buffer.byteLength(body, "utf8")) },
10514
10520
  agent
@@ -10573,12 +10579,12 @@ function lateRcStreamDial(resolve) {
10573
10579
  }
10574
10580
  function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_PORT }) {
10575
10581
  const agent = new ExemptTlsAgent();
10576
- const request4 = async (method, path36, headers, body, signal) => await new Promise((resolve, reject) => {
10582
+ const request4 = async (method, path37, headers, body, signal) => await new Promise((resolve, reject) => {
10577
10583
  const options = {
10578
10584
  host: target.host,
10579
10585
  port: target.port,
10580
10586
  method,
10581
- path: path36,
10587
+ path: path37,
10582
10588
  // The Host header names the host whose API this is, not the address dialled: a redirected test dials a loopback stand-in while still speaking to the API host by name, exactly as the forwarded paths present their SNI.
10583
10589
  headers: { ...headers, host: target.servername ?? target.host, ...body === void 0 ? {} : { "content-length": String(Buffer.byteLength(body, "utf8")) } },
10584
10590
  agent,
@@ -10620,9 +10626,9 @@ function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_P
10620
10626
  return { status, body: await readAll(response) };
10621
10627
  },
10622
10628
  openStream: async (sessionId, headers, resume, signal) => {
10623
- const path36 = resume === void 0 ? `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream` : `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream?from_sequence_num=${String(resume.fromSequenceNum)}`;
10629
+ const path37 = resume === void 0 ? `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream` : `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream?from_sequence_num=${String(resume.fromSequenceNum)}`;
10624
10630
  const streamHeaders = resume === void 0 ? headers : { ...headers, "last-event-id": String(resume.fromSequenceNum) };
10625
- const { status, response } = await request4("GET", path36, streamHeaders, void 0, signal);
10631
+ const { status, response } = await request4("GET", path37, streamHeaders, void 0, signal);
10626
10632
  if (!isSuccessful2(status)) {
10627
10633
  await readAll(response);
10628
10634
  return { status, chunks: NO_CHUNKS };
@@ -11537,19 +11543,19 @@ function writePools(paths, pools) {
11537
11543
  applyPatch(paths.globalConfigFile, GlobalConfigSchema, { pools }, { defaults: {} });
11538
11544
  }
11539
11545
  function poolCycleOf(pools, name) {
11540
- const walk = (current, path36) => {
11546
+ const walk = (current, path37) => {
11541
11547
  for (const entry of pools[current]?.identities ?? []) {
11542
11548
  const nested = poolNameOf(poolMemberIdentity(entry));
11543
11549
  if (nested === void 0) {
11544
11550
  continue;
11545
11551
  }
11546
11552
  if (nested === name) {
11547
- return [...path36, nested];
11553
+ return [...path37, nested];
11548
11554
  }
11549
- if (path36.includes(nested)) {
11555
+ if (path37.includes(nested)) {
11550
11556
  continue;
11551
11557
  }
11552
- const found = walk(nested, [...path36, nested]);
11558
+ const found = walk(nested, [...path37, nested]);
11553
11559
  if (found !== void 0) {
11554
11560
  return found;
11555
11561
  }
@@ -12222,7 +12228,7 @@ init_middleware();
12222
12228
  init_preflight();
12223
12229
 
12224
12230
  // src/frontdoor/controlSchemas.ts
12225
- var import_node_path29 = __toESM(require("node:path"), 1);
12231
+ var import_node_path30 = __toESM(require("node:path"), 1);
12226
12232
  var import_zod19 = require("zod");
12227
12233
 
12228
12234
  // src/doctorReport.ts
@@ -12393,7 +12399,29 @@ function removeIdentity(paths, name) {
12393
12399
  // src/doctorReport.ts
12394
12400
  init_realPorts();
12395
12401
  var import_node_fs9 = __toESM(require("node:fs"), 1);
12402
+ var import_node_path29 = __toESM(require("node:path"), 1);
12403
+
12404
+ // src/usage/signIn.ts
12396
12405
  var import_node_path28 = __toESM(require("node:path"), 1);
12406
+ var CREDENTIALS_FILE = ".credentials.json";
12407
+ function keychainHasItem(run, account) {
12408
+ return run.run("security", ["find-generic-password", "-a", account]).status === 0;
12409
+ }
12410
+ function decideSignIn(facts) {
12411
+ if (facts.hasCredentialBlock) {
12412
+ return { state: "token", detail: "supplies its own credential through a credential block, so a stored login is not what a launch uses" };
12413
+ }
12414
+ if (facts.keychainItem === true) {
12415
+ return { state: "signed-in", detail: "a login is stored in the macOS Keychain" };
12416
+ }
12417
+ if (facts.credentialsFile) {
12418
+ return { state: "signed-in", detail: `a login is stored in ${CREDENTIALS_FILE}` };
12419
+ }
12420
+ return { state: "signed-out", detail: facts.platform === "darwin" ? `no Keychain item and no ${CREDENTIALS_FILE}` : `no ${CREDENTIALS_FILE}` };
12421
+ }
12422
+ function credentialsFilePath(farmRoot) {
12423
+ return import_node_path28.default.join(farmRoot, CREDENTIALS_FILE);
12424
+ }
12397
12425
 
12398
12426
  // src/codex/siwcStore.ts
12399
12427
  var import_zod18 = require("zod");
@@ -12494,6 +12522,7 @@ var DOCTOR_SECTIONS = [
12494
12522
  "legacy-name",
12495
12523
  "config-profile",
12496
12524
  "identity",
12525
+ "sign-in",
12497
12526
  "pool",
12498
12527
  "provider",
12499
12528
  "keychain",
@@ -12536,7 +12565,7 @@ function tcpPortEraRecord(raw) {
12536
12565
  return (has("port") || has("lastPort")) && !has("socketPath");
12537
12566
  }
12538
12567
  function pushPathResolution(push, resolution) {
12539
- const ownDir = import_node_path28.default.dirname(resolution.ownExecutablePath);
12568
+ const ownDir = import_node_path29.default.dirname(resolution.ownExecutablePath);
12540
12569
  switch (resolution.agentShim.status) {
12541
12570
  case "ok":
12542
12571
  push("path-resolution", "pass", `\`agent-shim\` on PATH resolves to this running executable, ${resolution.ownExecutablePath}.`, "agent-shim");
@@ -12635,14 +12664,14 @@ function pushProvider(push, entry, cacheEnv, signIn) {
12635
12664
  }
12636
12665
  function pushLegacyName(push, params) {
12637
12666
  const legacyVariables = Object.keys(params.env).filter((name) => name.startsWith(LEGACY_ENV_PREFIX) && params.env[name] !== void 0).sort();
12638
- if (legacyVariables.length === 0 && import_node_path28.default.basename(params.rootPath) !== LEGACY_HOME_DIRNAME) {
12667
+ if (legacyVariables.length === 0 && import_node_path29.default.basename(params.rootPath) !== LEGACY_HOME_DIRNAME) {
12639
12668
  push("legacy-name", "pass", "Nothing here still uses the former `claude-use` name.");
12640
12669
  return;
12641
12670
  }
12642
12671
  for (const name of legacyVariables) {
12643
12672
  push("legacy-name", "warn", `${name} is the former name of ${name.replace(LEGACY_ENV_PREFIX, ENV_PREFIX)}. Rename it; the old name still works but is only a fallback.`, name);
12644
12673
  }
12645
- if (import_node_path28.default.basename(params.rootPath) === LEGACY_HOME_DIRNAME) {
12674
+ if (import_node_path29.default.basename(params.rootPath) === LEGACY_HOME_DIRNAME) {
12646
12675
  push(
12647
12676
  "legacy-name",
12648
12677
  "warn",
@@ -12739,6 +12768,18 @@ function runDoctor(params) {
12739
12768
  `${entry.name} is valid and authenticates with ${credential === void 0 ? "its stored login" : `credential ${describeCredential(credential)}`}${cache.text}.`,
12740
12769
  entry.name
12741
12770
  );
12771
+ const signIn = decideSignIn({
12772
+ hasCredentialBlock: credential !== void 0,
12773
+ keychainItem: params.platform === "darwin" && params.run !== void 0 ? keychainHasItem(params.run, entry.farmRoot) : void 0,
12774
+ credentialsFile: entry.credentialsFilePresent,
12775
+ platform: params.platform
12776
+ });
12777
+ push(
12778
+ "sign-in",
12779
+ signIn.state === "signed-out" ? "warn" : "pass",
12780
+ signIn.state === "signed-out" ? `${entry.name} is signed out (${signIn.detail}). Run \`agent-shim run @${entry.name}\` and sign in.` : `${entry.name} ${signIn.state === "token" ? "uses a credential block" : "is signed in"} (${signIn.detail}).`,
12781
+ entry.name
12782
+ );
12742
12783
  }
12743
12784
  }
12744
12785
  const validatedGlobalConfig = params.globalConfig.raw === void 0 ? void 0 : validateJson(GlobalConfigSchema, params.globalConfig);
@@ -12784,7 +12825,7 @@ function runDoctor(params) {
12784
12825
  } else {
12785
12826
  for (const entry of params.identities) {
12786
12827
  const result = lookupKeychainService(params.run, entry.farmRoot);
12787
- push("keychain", result.found ? "pass" : "warn", result.note, entry.name);
12828
+ push("keychain", "pass", result.found ? result.note : `${result.note} The sign-in section reports whether a login is stored elsewhere.`, entry.name);
12788
12829
  }
12789
12830
  }
12790
12831
  if (params.directoryRules.raw === void 0) {
@@ -12919,6 +12960,7 @@ var SECTION_TITLES = {
12919
12960
  "legacy-name": "Former `claude-use` name",
12920
12961
  "config-profile": "Configuration profiles",
12921
12962
  identity: "Identities",
12963
+ "sign-in": "Sign-in",
12922
12964
  pool: "Pools",
12923
12965
  provider: "Providers",
12924
12966
  keychain: "macOS Keychain",
@@ -12935,6 +12977,7 @@ var SECTION_ORDER = [
12935
12977
  "path-resolution",
12936
12978
  "config-profile",
12937
12979
  "identity",
12980
+ "sign-in",
12938
12981
  "pool",
12939
12982
  "provider",
12940
12983
  "keychain",
@@ -12984,18 +13027,18 @@ function collectDoctorReport(params) {
12984
13027
  const { paths } = params;
12985
13028
  const identityNames = import_node_fs9.default.existsSync(paths.identitiesDir) ? import_node_fs9.default.readdirSync(paths.identitiesDir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && isIdentityDirectoryName(entry.name)).map((entry) => entry.name).sort() : [];
12986
13029
  const identities = identityNames.map((name) => {
12987
- const farmRoot = import_node_path28.default.join(paths.identitiesDir, name);
12988
- const identityPath = import_node_path28.default.join(farmRoot, "identity.json");
12989
- return { name, path: identityPath, raw: realFsPort.readFileUtf8(identityPath), farmRoot };
13030
+ const farmRoot = import_node_path29.default.join(paths.identitiesDir, name);
13031
+ const identityPath = import_node_path29.default.join(farmRoot, "identity.json");
13032
+ return { name, path: identityPath, raw: realFsPort.readFileUtf8(identityPath), farmRoot, credentialsFilePresent: import_node_fs9.default.existsSync(credentialsFilePath(farmRoot)) };
12990
13033
  });
12991
13034
  const profileNames = import_node_fs9.default.existsSync(paths.configProfilesDir) ? import_node_fs9.default.readdirSync(paths.configProfilesDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
12992
13035
  const configProfiles = profileNames.map((name) => {
12993
- const profilePath = import_node_path28.default.join(paths.configProfilesDir, `${name}.json`);
13036
+ const profilePath = import_node_path29.default.join(paths.configProfilesDir, `${name}.json`);
12994
13037
  return { name, path: profilePath, raw: realFsPort.readFileUtf8(profilePath) };
12995
13038
  });
12996
13039
  const providerNames = import_node_fs9.default.existsSync(paths.providersDir) ? import_node_fs9.default.readdirSync(paths.providersDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
12997
13040
  const providers = providerNames.map((name) => {
12998
- const providerPath = import_node_path28.default.join(paths.providersDir, `${name}.json`);
13041
+ const providerPath = import_node_path29.default.join(paths.providersDir, `${name}.json`);
12999
13042
  return { name, path: providerPath, raw: realFsPort.readFileUtf8(providerPath) };
13000
13043
  });
13001
13044
  const ownExecutablePath = realOwnExecutablePath();
@@ -13007,12 +13050,12 @@ function collectDoctorReport(params) {
13007
13050
  binaryDiscovery = { ok: false, message: error instanceof Error ? error.message : String(error) };
13008
13051
  }
13009
13052
  const shimState = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
13010
- const pathDirs = (params.env.PATH ?? "").split(import_node_path28.default.delimiter).filter((dir) => dir !== "");
13053
+ const pathDirs = (params.env.PATH ?? "").split(import_node_path29.default.delimiter).filter((dir) => dir !== "");
13011
13054
  const claudeShimShadow = shimState === void 0 ? void 0 : refinePathShadow(
13012
13055
  findPathShadow({
13013
13056
  pathDirs,
13014
- targetDir: import_node_path28.default.dirname(shimState.targetPath),
13015
- targetFilename: import_node_path28.default.basename(shimState.targetPath),
13057
+ targetDir: import_node_path29.default.dirname(shimState.targetPath),
13058
+ targetFilename: import_node_path29.default.basename(shimState.targetPath),
13016
13059
  findExecutableInDir
13017
13060
  }),
13018
13061
  shimState.targetPath,
@@ -13038,7 +13081,7 @@ function collectDoctorReport(params) {
13038
13081
  agentShim: refinePathShadow(
13039
13082
  findPathShadow({
13040
13083
  pathDirs,
13041
- targetDir: import_node_path28.default.dirname(ownExecutablePath),
13084
+ targetDir: import_node_path29.default.dirname(ownExecutablePath),
13042
13085
  targetFilename: commandFilename(ownExecutablePath, "agent-shim"),
13043
13086
  findExecutableInDir
13044
13087
  }),
@@ -13112,11 +13155,11 @@ var FrontDoorSessionsOutputSchema = import_zod19.z.strictObject({ sessions: impo
13112
13155
  var CheckRunInputSchema = import_zod19.z.strictObject({
13113
13156
  path: import_zod19.z.string().min(1),
13114
13157
  identity: import_zod19.z.string().min(1).optional()
13115
- }).refine((input) => import_node_path29.default.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
13158
+ }).refine((input) => import_node_path30.default.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
13116
13159
  var PoolPickInputSchema = import_zod19.z.strictObject({
13117
13160
  pool: import_zod19.z.string().min(1),
13118
13161
  path: import_zod19.z.string().min(1)
13119
- }).refine((input) => import_node_path29.default.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
13162
+ }).refine((input) => import_node_path30.default.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
13120
13163
  var DoctorFindingSchema = import_zod19.z.strictObject({
13121
13164
  section: import_zod19.z.enum(DOCTOR_SECTIONS),
13122
13165
  subject: import_zod19.z.string().optional(),
@@ -13492,7 +13535,7 @@ function profileValue(name, paths) {
13492
13535
  function createConfigApiRouter(deps) {
13493
13536
  const authed = doorApiAuth(deps.expectedToken);
13494
13537
  const { paths } = deps;
13495
- const route = (path36, summary) => authed.meta((0, import_openapi3.openapi)({ method: "POST", path: path36, summary, tags: [CONFIG_API_TAG] }));
13538
+ const route = (path37, summary) => authed.meta((0, import_openapi3.openapi)({ method: "POST", path: path37, summary, tags: [CONFIG_API_TAG] }));
13496
13539
  return {
13497
13540
  config: {
13498
13541
  identity: {
@@ -13851,7 +13894,7 @@ var import_openapi6 = require("@orpc/openapi");
13851
13894
  init_cliError();
13852
13895
 
13853
13896
  // src/frontdoor/launchSchemas.ts
13854
- var import_node_path30 = __toESM(require("node:path"), 1);
13897
+ var import_node_path31 = __toESM(require("node:path"), 1);
13855
13898
  var import_zod22 = require("zod");
13856
13899
  init_claudeVersion();
13857
13900
  init_identity();
@@ -13861,7 +13904,7 @@ var LaunchResolveInputSchema = import_zod22.z.strictObject({
13861
13904
  argv: import_zod22.z.readonly(import_zod22.z.array(import_zod22.z.string())).optional(),
13862
13905
  /** The launch's inherited environment. Absent means an empty one: the door's own environment is never a substitute for the caller's, so a caller that wants `AGENT_SHIM_*` switches or a `CLAUDE_CONFIG_DIR` considered names them here. Values are read, never reported. */
13863
13906
  env: import_zod22.z.record(import_zod22.z.string(), import_zod22.z.string()).optional()
13864
- }).refine((input) => import_node_path30.default.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
13907
+ }).refine((input) => import_node_path31.default.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
13865
13908
  var LaunchPoolDecisionSchema = import_zod22.z.strictObject({
13866
13909
  name: import_zod22.z.string(),
13867
13910
  reasons: import_zod22.z.readonly(import_zod22.z.array(import_zod22.z.string())),
@@ -15956,9 +15999,9 @@ data: ${JSON.stringify(envelope)}
15956
15999
  }
15957
16000
 
15958
16001
  // src/frontdoor/rcSelfHostMint.ts
15959
- var import_node_path31 = __toESM(require("node:path"), 1);
16002
+ var import_node_path32 = __toESM(require("node:path"), 1);
15960
16003
  init_account();
15961
- var CREDENTIALS_FILE = ".credentials.json";
16004
+ var CREDENTIALS_FILE2 = ".credentials.json";
15962
16005
  var CLAUDE_JSON2 = ".claude.json";
15963
16006
  var RC_SELF_HOST_RECORD_DIR = "rc-selfhost";
15964
16007
  var RC_SELF_HOST_RECORD_FILE = "credential.json";
@@ -15981,7 +16024,7 @@ function readJsonObject(fs12, file) {
15981
16024
  return isRecord11(parsed) ? parsed : void 0;
15982
16025
  }
15983
16026
  function readRcSelfHostRecord(fs12, frontdoorDir) {
15984
- const parsed = readJsonObject(fs12, import_node_path31.default.join(frontdoorDir, RC_SELF_HOST_RECORD_DIR, RC_SELF_HOST_RECORD_FILE));
16027
+ const parsed = readJsonObject(fs12, import_node_path32.default.join(frontdoorDir, RC_SELF_HOST_RECORD_DIR, RC_SELF_HOST_RECORD_FILE));
15985
16028
  if (parsed === void 0) {
15986
16029
  return void 0;
15987
16030
  }
@@ -15995,11 +16038,11 @@ function mintRcSelfHostCredential(deps) {
15995
16038
  if (!isIdentityName(deps.identity)) {
15996
16039
  throw new Error(`"${deps.identity}" is not a valid identity name.`);
15997
16040
  }
15998
- const identityDir = import_node_path31.default.join(deps.identitiesDir, deps.identity);
15999
- const credentialsFile = import_node_path31.default.join(identityDir, CREDENTIALS_FILE);
16000
- const claudeJsonFile = import_node_path31.default.join(identityDir, CLAUDE_JSON2);
16001
- const recordDir = import_node_path31.default.join(deps.frontdoorDir, RC_SELF_HOST_RECORD_DIR);
16002
- const recordFile = import_node_path31.default.join(recordDir, RC_SELF_HOST_RECORD_FILE);
16041
+ const identityDir = import_node_path32.default.join(deps.identitiesDir, deps.identity);
16042
+ const credentialsFile = import_node_path32.default.join(identityDir, CREDENTIALS_FILE2);
16043
+ const claudeJsonFile = import_node_path32.default.join(identityDir, CLAUDE_JSON2);
16044
+ const recordDir = import_node_path32.default.join(deps.frontdoorDir, RC_SELF_HOST_RECORD_DIR);
16045
+ const recordFile = import_node_path32.default.join(recordDir, RC_SELF_HOST_RECORD_FILE);
16003
16046
  const previousRecord = readRcSelfHostRecord(deps.fs, deps.frontdoorDir);
16004
16047
  const existingCredentials = readJsonObject(deps.fs, credentialsFile);
16005
16048
  const existingOauth = isRecord11(existingCredentials?.claudeAiOauth) ? existingCredentials.claudeAiOauth : void 0;
@@ -16015,7 +16058,7 @@ function mintRcSelfHostCredential(deps) {
16015
16058
  const organizationUuid = deps.newUuid();
16016
16059
  const accountUuid = deps.newUuid();
16017
16060
  const mintedAt = new Date(deps.now()).toISOString();
16018
- deps.fs.mkdirPrivate(import_node_path31.default.dirname(credentialsFile));
16061
+ deps.fs.mkdirPrivate(import_node_path32.default.dirname(credentialsFile));
16019
16062
  deps.fs.writeFilePrivate(credentialsFile, `${JSON.stringify({ ...existingCredentials, claudeAiOauth: { accessToken, refreshToken, expiresAt: null, scopes: [...RC_SELF_HOST_SCOPE_LIST], subscriptionType: SELF_HOST_SUBSCRIPTION_TYPE, rateLimitTier: null } }, null, 2)}
16020
16063
  `);
16021
16064
  const claudeJson = readJsonObject(deps.fs, claudeJsonFile) ?? {};