claude-use 11.22.0 → 11.23.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
@@ -624,7 +624,7 @@ function parseIgnoringUnrecognisedKeys(schema, raw) {
624
624
  return second.success ? { success: true, data: second.data, ignored } : { success: false, issues: second.error.issues };
625
625
  }
626
626
  function describeIgnoredKeys(filePath, ignored) {
627
- const places = ignored.map(({ path: path41, keys }) => `${path41.length === 0 ? "" : `${path41.map(String).join(".")}.`}${keys.join(", ")}`);
627
+ const places = ignored.map(({ path: path42, keys }) => `${path42.length === 0 ? "" : `${path42.map(String).join(".")}.`}${keys.join(", ")}`);
628
628
  return `${filePath} has settings this version of agent-shim does not know and ignores: ${places.join("; ")}. A newer release may read them.`;
629
629
  }
630
630
  function noteIgnoredKeys(filePath, ignored) {
@@ -646,9 +646,9 @@ function restoreIgnoredKeys(filePath, value) {
646
646
  return value;
647
647
  }
648
648
  const restored = structuredClone(value);
649
- for (const { path: path41, values } of ignored) {
649
+ for (const { path: path42, values } of ignored) {
650
650
  let holder = restored;
651
- for (const step of path41) {
651
+ for (const step of path42) {
652
652
  holder = isRecord(holder) ? holder[step] : void 0;
653
653
  }
654
654
  if (isRecord(holder)) {
@@ -2928,7 +2928,7 @@ var init_package = __esm({
2928
2928
  "package.json"() {
2929
2929
  package_default = {
2930
2930
  name: "claude-use",
2931
- version: "11.22.0",
2931
+ version: "11.23.0",
2932
2932
  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.",
2933
2933
  license: "MIT",
2934
2934
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -6733,6 +6733,49 @@ var init_providersStore = __esm({
6733
6733
  }
6734
6734
  });
6735
6735
 
6736
+ // src/usage/signIn.ts
6737
+ function claudeCodeKeychainService(configDir) {
6738
+ return `${KEYCHAIN_SERVICE_PREFIX}-${(0, import_node_crypto9.createHash)("sha256").update(configDir).digest("hex").slice(0, KEYCHAIN_SERVICE_HASH_DIGITS)}`;
6739
+ }
6740
+ function keychainHasItem(run, configDir) {
6741
+ return run.run("security", ["find-generic-password", "-s", claudeCodeKeychainService(configDir)]).status === 0;
6742
+ }
6743
+ function decideSignIn(facts) {
6744
+ if (facts.hasCredentialBlock) {
6745
+ return { state: "token", detail: "supplies its own credential through a credential block, so a stored login is not what a launch uses" };
6746
+ }
6747
+ if (facts.keychainItem === true) {
6748
+ return { state: "signed-in", detail: "a login is stored in the macOS Keychain" };
6749
+ }
6750
+ if (facts.credentialsFile) {
6751
+ return { state: "signed-in", detail: `a login is stored in ${CREDENTIALS_FILE}` };
6752
+ }
6753
+ return { state: "signed-out", detail: facts.platform === "darwin" ? `no Keychain item and no ${CREDENTIALS_FILE}` : `no ${CREDENTIALS_FILE}` };
6754
+ }
6755
+ function credentialsFilePath(farmRoot) {
6756
+ return import_node_path26.default.join(farmRoot, CREDENTIALS_FILE);
6757
+ }
6758
+ function identitySignIn(fs13, probe, identity) {
6759
+ const probing = !identity.hasCredentialBlock;
6760
+ return decideSignIn({
6761
+ hasCredentialBlock: identity.hasCredentialBlock,
6762
+ keychainItem: probing && probe.platform === "darwin" && probe.run !== void 0 ? keychainHasItem(probe.run, identity.farmRoot) : void 0,
6763
+ credentialsFile: probing && fs13.lstat(credentialsFilePath(identity.farmRoot)) !== void 0,
6764
+ platform: probe.platform
6765
+ });
6766
+ }
6767
+ var import_node_crypto9, import_node_path26, CREDENTIALS_FILE, KEYCHAIN_SERVICE_PREFIX, KEYCHAIN_SERVICE_HASH_DIGITS;
6768
+ var init_signIn = __esm({
6769
+ "src/usage/signIn.ts"() {
6770
+ "use strict";
6771
+ import_node_crypto9 = require("node:crypto");
6772
+ import_node_path26 = __toESM(require("node:path"), 1);
6773
+ CREDENTIALS_FILE = ".credentials.json";
6774
+ KEYCHAIN_SERVICE_PREFIX = "Claude Code-credentials";
6775
+ KEYCHAIN_SERVICE_HASH_DIGITS = 8;
6776
+ }
6777
+ });
6778
+
6736
6779
  // src/cli/bool.ts
6737
6780
  function parseBoolWord(input) {
6738
6781
  switch (input) {
@@ -6886,10 +6929,10 @@ function commandFilename(ownExecutablePath, commandName) {
6886
6929
  }
6887
6930
  function resolveOwnBinaryCheck(paths, contentSourcePath) {
6888
6931
  const state = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
6889
- const recordedTarget = state === void 0 ? void 0 : import_node_path27.default.resolve(state.targetPath);
6932
+ const recordedTarget = state === void 0 ? void 0 : import_node_path28.default.resolve(state.targetPath);
6890
6933
  let ownStat;
6891
6934
  return (candidate) => {
6892
- if (recordedTarget !== void 0 && import_node_path27.default.resolve(candidate) === recordedTarget) {
6935
+ if (recordedTarget !== void 0 && import_node_path28.default.resolve(candidate) === recordedTarget) {
6893
6936
  return true;
6894
6937
  }
6895
6938
  ownStat ??= statOrUndefined(contentSourcePath);
@@ -6912,22 +6955,22 @@ function statOrUndefined(target) {
6912
6955
  }
6913
6956
  }
6914
6957
  function findPathShadow(params) {
6915
- const resolvedTargetDir = import_node_path27.default.resolve(params.targetDir);
6958
+ const resolvedTargetDir = import_node_path28.default.resolve(params.targetDir);
6916
6959
  for (const dir of params.pathDirs) {
6917
6960
  const found = params.findExecutableInDir(dir, params.targetFilename);
6918
6961
  if (found === void 0) {
6919
6962
  continue;
6920
6963
  }
6921
- return import_node_path27.default.resolve(dir) === resolvedTargetDir ? { status: "ok" } : { status: "shadowed", by: found };
6964
+ return import_node_path28.default.resolve(dir) === resolvedTargetDir ? { status: "ok" } : { status: "shadowed", by: found };
6922
6965
  }
6923
- return params.pathDirs.some((dir) => import_node_path27.default.resolve(dir) === resolvedTargetDir) ? { status: "ok" } : { status: "not-on-path" };
6966
+ return params.pathDirs.some((dir) => import_node_path28.default.resolve(dir) === resolvedTargetDir) ? { status: "ok" } : { status: "not-on-path" };
6924
6967
  }
6925
- var import_node_fs7, import_node_path27, import_zod19, ClaudeShimStateSchema, nodeLinkFs;
6968
+ var import_node_fs7, import_node_path28, import_zod19, ClaudeShimStateSchema, nodeLinkFs;
6926
6969
  var init_claudeShim = __esm({
6927
6970
  "src/claudeShim.ts"() {
6928
6971
  "use strict";
6929
6972
  import_node_fs7 = __toESM(require("node:fs"), 1);
6930
- import_node_path27 = __toESM(require("node:path"), 1);
6973
+ import_node_path28 = __toESM(require("node:path"), 1);
6931
6974
  import_zod19 = require("zod");
6932
6975
  init_commandDeps();
6933
6976
  init_store();
@@ -7128,7 +7171,7 @@ function ensureFrontDoor(params) {
7128
7171
  if (supervisorPid !== void 0 && !distrusted.has(supervisorPid) && ports.isRunning(supervisorPid)) {
7129
7172
  if (state?.port !== void 0 && state.connectPort !== void 0) {
7130
7173
  if (supervisorPid === params.launcherPid && params.replace !== true && ports.isFrontDoorSupervisor(supervisorPid)) {
7131
- const token = (0, import_node_crypto9.randomUUID)();
7174
+ const token = (0, import_node_crypto10.randomUUID)();
7132
7175
  writeFrontDoorSession(ports.fs, paths.frontdoorSessionsDir, { pid: params.launcherPid, startedAt: ports.now(), token, supervisorPid });
7133
7176
  return { port: state.port, connectPort: state.connectPort, token };
7134
7177
  }
@@ -7142,7 +7185,7 @@ function ensureFrontDoor(params) {
7142
7185
  continue;
7143
7186
  }
7144
7187
  if (verdict.ok) {
7145
- const token = (0, import_node_crypto9.randomUUID)();
7188
+ const token = (0, import_node_crypto10.randomUUID)();
7146
7189
  writeFrontDoorSession(ports.fs, paths.frontdoorSessionsDir, { pid: params.launcherPid, startedAt: ports.now(), token, supervisorPid });
7147
7190
  return { port: state.port, connectPort: state.connectPort, token };
7148
7191
  }
@@ -7195,11 +7238,11 @@ function ensureFrontDoor(params) {
7195
7238
  ports.sleep(FRONTDOOR_LAUNCHER_POLL_MS);
7196
7239
  }
7197
7240
  }
7198
- var import_node_crypto9, FRONTDOOR_START_TIMEOUT_MS, FRONTDOOR_LAUNCHER_POLL_MS, FRONTDOOR_PROBE_ATTEMPTS, FRONTDOOR_EXIT_GRACE_MS, FrontDoorStartError;
7241
+ var import_node_crypto10, FRONTDOOR_START_TIMEOUT_MS, FRONTDOOR_LAUNCHER_POLL_MS, FRONTDOOR_PROBE_ATTEMPTS, FRONTDOOR_EXIT_GRACE_MS, FrontDoorStartError;
7199
7242
  var init_ensure2 = __esm({
7200
7243
  "src/frontdoor/ensure.ts"() {
7201
7244
  "use strict";
7202
- import_node_crypto9 = require("node:crypto");
7245
+ import_node_crypto10 = require("node:crypto");
7203
7246
  init_cliError();
7204
7247
  init_state2();
7205
7248
  init_state();
@@ -7580,7 +7623,7 @@ function buildEnv(params) {
7580
7623
  }
7581
7624
  }
7582
7625
  if (params.provider !== void 0) {
7583
- env.ANTHROPIC_AUTH_TOKEN = void 0;
7626
+ env.ANTHROPIC_AUTH_TOKEN = params.remoteControl ? void 0 : PROVIDER_SESSION_PLACEHOLDER;
7584
7627
  env.ANTHROPIC_API_KEY = void 0;
7585
7628
  env.CLAUDE_CODE_OAUTH_TOKEN = void 0;
7586
7629
  } else if (params.identityCredential !== void 0) {
@@ -7612,7 +7655,7 @@ function buildEnv(params) {
7612
7655
  }
7613
7656
  return env;
7614
7657
  }
7615
- var import_node_path36, LOOPBACK_HOSTS;
7658
+ var import_node_path36, LOOPBACK_HOSTS, PROVIDER_SESSION_PLACEHOLDER;
7616
7659
  var init_flags = __esm({
7617
7660
  "src/launcher/flags.ts"() {
7618
7661
  "use strict";
@@ -7623,6 +7666,7 @@ var init_flags = __esm({
7623
7666
  init_capability();
7624
7667
  init_route();
7625
7668
  LOOPBACK_HOSTS = ["127.0.0.1", "localhost", "::1"];
7669
+ PROVIDER_SESSION_PLACEHOLDER = "agent-shim-provider-session";
7626
7670
  }
7627
7671
  });
7628
7672
 
@@ -8180,7 +8224,7 @@ function decideLaunch(params, readOnly) {
8180
8224
  }
8181
8225
  const pinnedVersion = resolveClaudeVersion({ env, ...parsedArgv.claudeVersion === void 0 ? {} : { flag: parsedArgv.claudeVersion }, ...cascadeLaunch?.claudeVersion === void 0 ? {} : { cascade: cascadeLaunch.claudeVersion } });
8182
8226
  const discovered = params.resolveClaudeBinary(pinnedVersion === void 0 ? void 0 : { version: pinnedVersion.version });
8183
- const flags = resolveLaunchFlags({
8227
+ const requestedFlags = resolveLaunchFlags({
8184
8228
  env,
8185
8229
  ...cascadeLaunch === void 0 ? {} : { cascade: cascadeLaunch },
8186
8230
  flags: {
@@ -8190,6 +8234,11 @@ function decideLaunch(params, readOnly) {
8190
8234
  ...parsedArgv.trackUsage === void 0 ? {} : { trackUsage: parsedArgv.trackUsage }
8191
8235
  }
8192
8236
  });
8237
+ const loginlessProvider = requestedFlags.remoteControl && selectedProvider !== void 0 && farmIdentity !== void 0 && params.hasStoredLogin?.(farmIdentity) === false ? { identity: farmIdentity, provider: selectedProvider.name } : void 0;
8238
+ if (loginlessProvider !== void 0 && !readOnly) {
8239
+ 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`);
8240
+ }
8241
+ const flags = loginlessProvider === void 0 ? requestedFlags : { ...requestedFlags, remoteControl: false };
8193
8242
  const args = buildArgv({
8194
8243
  toolFlags: buildFlagArgs(flags),
8195
8244
  extraFlags: splitExtraFlags(env.CLAUDE_EXTRA_FLAGS),
@@ -8305,7 +8354,7 @@ function prepareLaunch(params) {
8305
8354
  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})`}`);
8306
8355
  }
8307
8356
  const frontDoorRelease = frontDoor === void 0 ? void 0 : frontDoorPort?.release;
8308
- const sessionId = params.supervised?.sessionId ?? (0, import_node_crypto10.randomUUID)();
8357
+ const sessionId = params.supervised?.sessionId ?? (0, import_node_crypto11.randomUUID)();
8309
8358
  const finalEnv = buildEnv({
8310
8359
  baseEnv: env,
8311
8360
  configDirEscapeHatch: configDirEscapeHatchApplies,
@@ -8315,7 +8364,8 @@ function prepareLaunch(params) {
8315
8364
  ...identityCredential === void 0 ? {} : { identityCredential },
8316
8365
  ...frontDoor === void 0 ? {} : { frontdoor: frontDoor },
8317
8366
  ...headroom === void 0 ? {} : { headroom },
8318
- sessionId
8367
+ sessionId,
8368
+ remoteControl: resolvedFlags.remoteControl
8319
8369
  });
8320
8370
  const releases = [...headroom === void 0 || headroomPort === void 0 ? [] : [headroomPort.release], ...frontDoorRelease === void 0 ? [] : [frontDoorRelease]];
8321
8371
  const release = () => {
@@ -8337,7 +8387,8 @@ function resolveLaunch(params) {
8337
8387
  ...decided.provider === void 0 ? {} : { provider: decided.provider },
8338
8388
  ...frontDoor ? { frontdoor: { port: 0, connectPort: 0, trustBundlePath: "", sessionToken: "" } } : {},
8339
8389
  ...decided.flags.headroom ? { headroom: { socketPath: "", projectId: "" } } : {},
8340
- sessionId: ""
8390
+ sessionId: "",
8391
+ remoteControl: decided.flags.remoteControl
8341
8392
  });
8342
8393
  const credentialNames = decided.identityCredentialBlock === void 0 ? [] : Object.keys(credentialVariables(decided.identityCredentialBlock.target ?? "bearer", ""));
8343
8394
  const environment = [.../* @__PURE__ */ new Set([...Object.keys(built).filter((name) => built[name] !== env[name]), ...credentialNames])].sort();
@@ -8368,11 +8419,11 @@ function runLaunchPlan(plan, spawn3) {
8368
8419
  function runLauncher(params) {
8369
8420
  params.proc.exit(runLaunchPlan(prepareLaunch(params), params.spawn));
8370
8421
  }
8371
- var import_node_crypto10, import_node_path38;
8422
+ var import_node_crypto11, import_node_path38;
8372
8423
  var init_launcher = __esm({
8373
8424
  "src/launcher.ts"() {
8374
8425
  "use strict";
8375
- import_node_crypto10 = require("node:crypto");
8426
+ import_node_crypto11 = require("node:crypto");
8376
8427
  import_node_path38 = __toESM(require("node:path"), 1);
8377
8428
  init_package();
8378
8429
  init_envBool();
@@ -8456,18 +8507,18 @@ function resolveTrustBundle(params) {
8456
8507
  }
8457
8508
  const combined = `${inheritedPem.trimEnd()}
8458
8509
  ${caPem}`;
8459
- const bundle = import_node_path40.default.join(bundlesDir, `${(0, import_node_crypto11.createHash)("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
8510
+ const bundle = import_node_path40.default.join(bundlesDir, `${(0, import_node_crypto12.createHash)("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
8460
8511
  if (!fs13.exists(bundle)) {
8461
8512
  fs13.mkdirp(bundlesDir);
8462
8513
  fs13.writeFileAtomic(bundle, combined);
8463
8514
  }
8464
8515
  return { path: bundle };
8465
8516
  }
8466
- var import_node_crypto11, import_node_path40, BUNDLE_NAME_HEX_DIGITS;
8517
+ var import_node_crypto12, import_node_path40, BUNDLE_NAME_HEX_DIGITS;
8467
8518
  var init_trust = __esm({
8468
8519
  "src/frontdoor/trust.ts"() {
8469
8520
  "use strict";
8470
- import_node_crypto11 = require("node:crypto");
8521
+ import_node_crypto12 = require("node:crypto");
8471
8522
  import_node_path40 = __toESM(require("node:path"), 1);
8472
8523
  BUNDLE_NAME_HEX_DIGITS = 16;
8473
8524
  }
@@ -8561,7 +8612,7 @@ function buildFarmRuntime(paths, cwd) {
8561
8612
  ...cliOverride === void 0 ? {} : { cliOverride }
8562
8613
  }).input,
8563
8614
  now: () => Date.now(),
8564
- uniqueSuffix: `${String(process.pid)}.${(0, import_node_crypto12.randomUUID)()}`,
8615
+ uniqueSuffix: `${String(process.pid)}.${(0, import_node_crypto13.randomUUID)()}`,
8565
8616
  // Zombie-aware on purpose: a previous launcher that crashed out of a resync without releasing the lock may sit unreaped, still answering signal 0 as alive, and must read as a dead holder so this launch takes the lock over instead of timing out.
8566
8617
  lock: { pid: process.pid, isRunning: realIsProcessRunning, sleep: realSleepSync }
8567
8618
  },
@@ -8587,6 +8638,7 @@ function realPrepareLaunchParams(paths, options) {
8587
8638
  headroom: realHeadroomPort(paths, { spawnDaemon: options.spawnDaemon, cwd: farm.runtime.cwd }),
8588
8639
  frontdoor: realFrontDoorPort(paths, options.spawnDaemon),
8589
8640
  credentials: { ...realCredentialPort, cache: realCredentialCacheEnv(paths) },
8641
+ hasStoredLogin: (identity) => identitySignIn(realFarmFs, { platform: process.platform, run: realRunPort }, { farmRoot: import_node_path41.default.join(paths.identitiesDir, identity), hasCredentialBlock: false }).state !== "signed-out",
8590
8642
  ...farm.directoryIdentity === void 0 ? {} : { directoryPinnedIdentity: farm.directoryIdentity },
8591
8643
  ...farm.directoryConfigProfile === void 0 ? {} : { directoryRuleConfigProfile: farm.directoryConfigProfile },
8592
8644
  ...farm.globalDefaultConfigProfile === void 0 ? {} : { globalDefaultConfigProfile: farm.globalDefaultConfigProfile },
@@ -8643,12 +8695,13 @@ function resolveClaudeLaunch(options) {
8643
8695
  };
8644
8696
  return { resolution: resolveLaunch(realPrepareLaunchParams(paths, { proc, log, spawnDaemon, farm: buildFarmRuntime(paths, options.cwd) })), warnings };
8645
8697
  }
8646
- var import_node_os7, import_node_crypto12, LaunchRefusedError;
8698
+ var import_node_os7, import_node_path41, import_node_crypto13, LaunchRefusedError;
8647
8699
  var init_launchWiring = __esm({
8648
8700
  "src/launchWiring.ts"() {
8649
8701
  "use strict";
8650
8702
  import_node_os7 = __toESM(require("node:os"), 1);
8651
- import_node_crypto12 = require("node:crypto");
8703
+ import_node_path41 = __toESM(require("node:path"), 1);
8704
+ import_node_crypto13 = require("node:crypto");
8652
8705
  init_cliError();
8653
8706
  init_claudeShim();
8654
8707
  init_classify();
@@ -8660,6 +8713,7 @@ var init_launchWiring = __esm({
8660
8713
  init_launchHook();
8661
8714
  init_cascade();
8662
8715
  init_paths();
8716
+ init_signIn();
8663
8717
  init_realPorts();
8664
8718
  LaunchRefusedError = class extends CliError {
8665
8719
  exitCode;
@@ -9951,8 +10005,8 @@ function parseConnectTarget(authority) {
9951
10005
  function isInterceptedHost(host, interceptHosts) {
9952
10006
  return interceptHosts.includes(host);
9953
10007
  }
9954
- function servedByPipeline(path41) {
9955
- return path41?.startsWith(ROUTED_PATH_PREFIX) === true;
10008
+ function servedByPipeline(path42) {
10009
+ return path42?.startsWith(ROUTED_PATH_PREFIX) === true;
9956
10010
  }
9957
10011
  var HOP_BY_HOP_HEADERS = /* @__PURE__ */ new Set([
9958
10012
  "connection",
@@ -10746,11 +10800,11 @@ function createRcSessionTracker(deps) {
10746
10800
  };
10747
10801
  const observeExchange = (request4) => {
10748
10802
  const method = (request4.method ?? "").toUpperCase();
10749
- const path41 = new URL(request4.url ?? "/", "http://127.0.0.1").pathname;
10750
- if (!path41.startsWith(RC_SESSIONS_PATH_PREFIX)) {
10803
+ const path42 = new URL(request4.url ?? "/", "http://127.0.0.1").pathname;
10804
+ if (!path42.startsWith(RC_SESSIONS_PATH_PREFIX)) {
10751
10805
  return void 0;
10752
10806
  }
10753
- const tail = path41.slice(RC_SESSIONS_PATH_PREFIX.length);
10807
+ const tail = path42.slice(RC_SESSIONS_PATH_PREFIX.length);
10754
10808
  const facts = {
10755
10809
  oauthAuthorization: oauthAuthorizationOf(request4.headers),
10756
10810
  anthropicVersion: singleHeader(request4.headers, "anthropic-version"),
@@ -11140,8 +11194,8 @@ var RC_READ_FILE_ENCODINGS = ["utf-8", "base64"];
11140
11194
  function isRcReadFileEncoding(value) {
11141
11195
  return RC_READ_FILE_ENCODINGS.some((encoding) => encoding === value);
11142
11196
  }
11143
- function buildRcReadFilePayload(requestId, path41, options) {
11144
- return buildRcControlRequestPayload(requestId, { subtype: "read_file", path: path41, ...options?.maxBytes === void 0 ? {} : { max_bytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } });
11197
+ function buildRcReadFilePayload(requestId, path42, options) {
11198
+ return buildRcControlRequestPayload(requestId, { subtype: "read_file", path: path42, ...options?.maxBytes === void 0 ? {} : { max_bytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } });
11145
11199
  }
11146
11200
  function buildRcFileSuggestionsPayload(requestId, query) {
11147
11201
  return buildRcControlRequestPayload(requestId, { subtype: "file_suggestions", query });
@@ -11243,15 +11297,15 @@ async function getRcSessionContextUsage(deps, sessionId, detail) {
11243
11297
  const result = await deliverRcClientPayload(deps, sessionId, buildRcGetContextUsagePayload(requestId, detail), `request the context usage of session ${sessionId}`);
11244
11298
  return result.ok ? { ...result, requestId } : result;
11245
11299
  }
11246
- async function readRcSessionFile(deps, sessionId, path41, options) {
11247
- if (path41 === "") {
11300
+ async function readRcSessionFile(deps, sessionId, path42, options) {
11301
+ if (path42 === "") {
11248
11302
  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" };
11249
11303
  }
11250
11304
  if (options?.maxBytes !== void 0 && (!Number.isInteger(options.maxBytes) || options.maxBytes <= 0)) {
11251
11305
  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" };
11252
11306
  }
11253
11307
  const requestId = deps.newUuid();
11254
- const result = await deliverRcClientPayload(deps, sessionId, buildRcReadFilePayload(requestId, path41, options), `read ${path41} from session ${sessionId}`);
11308
+ const result = await deliverRcClientPayload(deps, sessionId, buildRcReadFilePayload(requestId, path42, options), `read ${path42} from session ${sessionId}`);
11255
11309
  return result.ok ? { ...result, requestId } : result;
11256
11310
  }
11257
11311
  async function suggestRcSessionFiles(deps, sessionId, query) {
@@ -11420,11 +11474,11 @@ function createRcControlHandler(deps) {
11420
11474
  path: "read-file",
11421
11475
  read: (body) => {
11422
11476
  const session = bodyString(body, "session");
11423
- const path41 = bodyString(body, "path");
11477
+ const path42 = bodyString(body, "path");
11424
11478
  const maxBytes = "maxBytes" in body ? bodyPositiveInteger(body, "maxBytes") : void 0;
11425
11479
  const encoding = "encoding" in body && isRcReadFileEncoding(body.encoding) ? body.encoding : void 0;
11426
- const refused2 = session === void 0 || path41 === void 0 || "maxBytes" in body && maxBytes === void 0 || "encoding" in body && encoding === void 0;
11427
- 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, path41, { ...maxBytes === void 0 ? {} : { maxBytes }, ...encoding === void 0 ? {} : { encoding } }) };
11480
+ const refused2 = session === void 0 || path42 === void 0 || "maxBytes" in body && maxBytes === void 0 || "encoding" in body && encoding === void 0;
11481
+ 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, path42, { ...maxBytes === void 0 ? {} : { maxBytes }, ...encoding === void 0 ? {} : { encoding } }) };
11428
11482
  }
11429
11483
  },
11430
11484
  {
@@ -11734,9 +11788,9 @@ function requestIdOfBody(body) {
11734
11788
  }
11735
11789
  function frontDoorRcControl(transport, token) {
11736
11790
  const headers = { authorization: `Bearer ${token}` };
11737
- const listAnswerOf = async (path41, what) => {
11791
+ const listAnswerOf = async (path42, what) => {
11738
11792
  try {
11739
- return await transport.request({ method: "GET", path: path41, headers });
11793
+ return await transport.request({ method: "GET", path: path42, headers });
11740
11794
  } catch (error) {
11741
11795
  throw new Error(`${what}: could not reach the front door's control listener: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
11742
11796
  }
@@ -11808,10 +11862,10 @@ function frontDoorRcControl(transport, token) {
11808
11862
  }
11809
11863
  return pending;
11810
11864
  };
11811
- const writeOf = async (path41, body, describeFailure2) => {
11865
+ const writeOf = async (path42, body, describeFailure2) => {
11812
11866
  let answer;
11813
11867
  try {
11814
- answer = await transport.request({ method: "POST", path: path41, headers: { ...headers, "content-type": "application/json" }, body });
11868
+ answer = await transport.request({ method: "POST", path: path42, headers: { ...headers, "content-type": "application/json" }, body });
11815
11869
  } catch (error) {
11816
11870
  return { ok: false, message: `could not reach the front door's control listener: ${error instanceof Error ? error.message : String(error)}` };
11817
11871
  }
@@ -11842,10 +11896,10 @@ function frontDoorRcControl(transport, token) {
11842
11896
  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}`),
11843
11897
  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}`),
11844
11898
  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}`),
11845
- readFile: async (sessionId, path41, options) => await writeOf(
11899
+ readFile: async (sessionId, path42, options) => await writeOf(
11846
11900
  `${CONTROL_PATH_PREFIX}/read-file`,
11847
- JSON.stringify({ session: sessionId, path: path41, ...options?.maxBytes === void 0 ? {} : { maxBytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } }),
11848
- (status, message) => `reading ${path41} from ${sessionId} failed (HTTP ${String(status)}): ${message}`
11901
+ JSON.stringify({ session: sessionId, path: path42, ...options?.maxBytes === void 0 ? {} : { maxBytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } }),
11902
+ (status, message) => `reading ${path42} from ${sessionId} failed (HTTP ${String(status)}): ${message}`
11849
11903
  ),
11850
11904
  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}`),
11851
11905
  keepAlive: async (sessionId) => await writeOf(`${CONTROL_PATH_PREFIX}/keep-alive`, JSON.stringify({ session: sessionId }), (status, message) => `keeping ${sessionId} alive failed (HTTP ${String(status)}): ${message}`),
@@ -12004,12 +12058,12 @@ function tlsFacts(options) {
12004
12058
  }
12005
12059
  function realRcEventDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_PORT }) {
12006
12060
  const agent = new ExemptTlsAgent();
12007
- const post = async (path41, headers, body) => await new Promise((resolve, reject) => {
12061
+ const post = async (path42, headers, body) => await new Promise((resolve, reject) => {
12008
12062
  const options = {
12009
12063
  host: target.host,
12010
12064
  port: target.port,
12011
12065
  method: "POST",
12012
- path: path41,
12066
+ path: path42,
12013
12067
  // 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.
12014
12068
  headers: { ...headers, host: target.servername ?? target.host, "content-length": String(Buffer.byteLength(body, "utf8")) },
12015
12069
  agent
@@ -12074,12 +12128,12 @@ function lateRcStreamDial(resolve) {
12074
12128
  }
12075
12129
  function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_PORT }) {
12076
12130
  const agent = new ExemptTlsAgent();
12077
- const request4 = async (method, path41, headers, body, signal) => await new Promise((resolve, reject) => {
12131
+ const request4 = async (method, path42, headers, body, signal) => await new Promise((resolve, reject) => {
12078
12132
  const options = {
12079
12133
  host: target.host,
12080
12134
  port: target.port,
12081
12135
  method,
12082
- path: path41,
12136
+ path: path42,
12083
12137
  // 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.
12084
12138
  headers: { ...headers, host: target.servername ?? target.host, ...body === void 0 ? {} : { "content-length": String(Buffer.byteLength(body, "utf8")) } },
12085
12139
  agent,
@@ -12121,9 +12175,9 @@ function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_P
12121
12175
  return { status, body: await readAll(response) };
12122
12176
  },
12123
12177
  openStream: async (sessionId, headers, resume, signal) => {
12124
- const path41 = resume === void 0 ? `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream` : `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream?from_sequence_num=${String(resume.fromSequenceNum)}`;
12178
+ const path42 = resume === void 0 ? `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream` : `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream?from_sequence_num=${String(resume.fromSequenceNum)}`;
12125
12179
  const streamHeaders = resume === void 0 ? headers : { ...headers, "last-event-id": String(resume.fromSequenceNum) };
12126
- const { status, response } = await request4("GET", path41, streamHeaders, void 0, signal);
12180
+ const { status, response } = await request4("GET", path42, streamHeaders, void 0, signal);
12127
12181
  if (!isSuccessful2(status)) {
12128
12182
  await readAll(response);
12129
12183
  return { status, chunks: NO_CHUNKS };
@@ -13275,19 +13329,19 @@ function writePools(paths, pools) {
13275
13329
  applyPatch(paths.globalConfigFile, GlobalConfigSchema, { pools }, { defaults: {} });
13276
13330
  }
13277
13331
  function poolCycleOf(pools, name) {
13278
- const walk = (current, path41) => {
13332
+ const walk = (current, path42) => {
13279
13333
  for (const entry of pools[current]?.identities ?? []) {
13280
13334
  const nested = poolNameOf(poolMemberIdentity(entry));
13281
13335
  if (nested === void 0) {
13282
13336
  continue;
13283
13337
  }
13284
13338
  if (nested === name) {
13285
- return [...path41, nested];
13339
+ return [...path42, nested];
13286
13340
  }
13287
- if (path41.includes(nested)) {
13341
+ if (path42.includes(nested)) {
13288
13342
  continue;
13289
13343
  }
13290
- const found = walk(nested, [...path41, nested]);
13344
+ const found = walk(nested, [...path42, nested]);
13291
13345
  if (found !== void 0) {
13292
13346
  return found;
13293
13347
  }
@@ -13409,8 +13463,9 @@ init_cascade();
13409
13463
  init_paths();
13410
13464
  init_realCredentialCache();
13411
13465
  init_providersStore();
13466
+ init_signIn();
13412
13467
  init_realPorts();
13413
- var import_node_path26 = __toESM(require("node:path"), 1);
13468
+ var import_node_path27 = __toESM(require("node:path"), 1);
13414
13469
  var import_zod15 = require("zod");
13415
13470
  init_envBool();
13416
13471
  init_load();
@@ -13478,26 +13533,18 @@ function formatDecision(decision) {
13478
13533
  const eliminatedNote = decision.eliminated !== void 0 && decision.eliminated.length > 0 ? ` [${String(decision.eliminated.length)} more specific rule(s) eliminated by a failing when-condition]` : "";
13479
13534
  return `${decision.relPath}: ${status} \u2014 ${reason}${eliminatedNote}`;
13480
13535
  }
13481
- function parseKeychainServiceName(stderr) {
13482
- const match = /"svce"<blob>="([^"]*)"/.exec(stderr);
13483
- return match?.[1];
13484
- }
13485
13536
  function lookupKeychainService(run, farmRoot) {
13486
- const result = run.run("security", ["find-generic-password", "-a", farmRoot, "-g"]);
13537
+ const serviceName = claudeCodeKeychainService(farmRoot);
13538
+ const result = run.run("security", ["find-generic-password", "-s", serviceName]);
13487
13539
  if (result.status !== 0) {
13488
13540
  return {
13489
13541
  checked: true,
13490
13542
  found: false,
13491
- note: `No Keychain entry found for account "${farmRoot}" (security exited ${result.status === null ? "with no status" : String(result.status)}).`
13543
+ serviceName,
13544
+ note: `No Keychain entry found for service "${serviceName}" (security exited ${result.status === null ? "with no status" : String(result.status)}).`
13492
13545
  };
13493
13546
  }
13494
- const serviceName = parseKeychainServiceName(result.stderr);
13495
- return {
13496
- checked: true,
13497
- found: true,
13498
- ...serviceName === void 0 ? {} : { serviceName },
13499
- note: serviceName === void 0 ? `A Keychain entry was found for account "${farmRoot}" but its service name could not be parsed from security's output.` : `Keychain service name for this identity: "${serviceName}".`
13500
- };
13547
+ return { checked: true, found: true, serviceName, note: `Keychain service name for this identity: "${serviceName}".` };
13501
13548
  }
13502
13549
  var SettingsSecretsShapeSchema = import_zod15.z.looseObject({
13503
13550
  env: import_zod15.z.record(import_zod15.z.string(), import_zod15.z.unknown()).optional(),
@@ -13759,10 +13806,10 @@ function collectCheckReport(params) {
13759
13806
  }).input;
13760
13807
  const providerName = cascadeProviderName(cascade);
13761
13808
  const provider = providerName === void 0 ? void 0 : loadCheckProvider(paths, providerName);
13762
- const farmRoot = identityDecision.name === void 0 ? void 0 : import_node_path26.default.join(paths.identitiesDir, identityDecision.name);
13809
+ const farmRoot = identityDecision.name === void 0 ? void 0 : import_node_path27.default.join(paths.identitiesDir, identityDecision.name);
13763
13810
  const settingsFiles = {
13764
- "settings.json": realFsPort.readFileUtf8(import_node_path26.default.join(claudeHome, "settings.json")),
13765
- "settings.local.json": realFsPort.readFileUtf8(import_node_path26.default.join(claudeHome, "settings.local.json"))
13811
+ "settings.json": realFsPort.readFileUtf8(import_node_path27.default.join(claudeHome, "settings.json")),
13812
+ "settings.local.json": realFsPort.readFileUtf8(import_node_path27.default.join(claudeHome, "settings.local.json"))
13766
13813
  };
13767
13814
  const report = runCheck({
13768
13815
  cwd,
@@ -14063,7 +14110,7 @@ init_store();
14063
14110
 
14064
14111
  // src/identityStore.ts
14065
14112
  var import_node_fs8 = __toESM(require("node:fs"), 1);
14066
- var import_node_path28 = __toESM(require("node:path"), 1);
14113
+ var import_node_path29 = __toESM(require("node:path"), 1);
14067
14114
  init_load();
14068
14115
  init_store();
14069
14116
  init_schema();
@@ -14097,7 +14144,7 @@ var InvalidIdentityNameError = class extends CliError {
14097
14144
  attemptedName;
14098
14145
  };
14099
14146
  function identityJsonPath(paths, name) {
14100
- return import_node_path28.default.join(paths.identitiesDir, name, "identity.json");
14147
+ return import_node_path29.default.join(paths.identitiesDir, name, "identity.json");
14101
14148
  }
14102
14149
  function requireIdentityNames(paths, names) {
14103
14150
  const existing = new Set(listIdentities(paths).map((entry) => entry.name));
@@ -14212,7 +14259,7 @@ function setIdentityCredential(paths, identityName, change) {
14212
14259
  });
14213
14260
  }
14214
14261
  function belongsToIdentity(entry, name) {
14215
- return entry === name || entry === import_node_path28.default.basename(identityLockPath("", name)) || entry.startsWith(`.${name}.scratch.`) || entry.startsWith(`.${name}.previous.`);
14262
+ return entry === name || entry === import_node_path29.default.basename(identityLockPath("", name)) || entry.startsWith(`.${name}.scratch.`) || entry.startsWith(`.${name}.previous.`);
14216
14263
  }
14217
14264
  function removeIdentity(paths, name) {
14218
14265
  if (!identityExists(paths, name)) {
@@ -14220,7 +14267,7 @@ function removeIdentity(paths, name) {
14220
14267
  }
14221
14268
  for (const entry of import_node_fs8.default.readdirSync(paths.identitiesDir)) {
14222
14269
  if (belongsToIdentity(entry, name)) {
14223
- import_node_fs8.default.rmSync(import_node_path28.default.join(paths.identitiesDir, entry), { recursive: true, force: true });
14270
+ import_node_fs8.default.rmSync(import_node_path29.default.join(paths.identitiesDir, entry), { recursive: true, force: true });
14224
14271
  }
14225
14272
  }
14226
14273
  if (readActiveIdentity2(paths) === name) {
@@ -14232,28 +14279,7 @@ function removeIdentity(paths, name) {
14232
14279
  init_realPorts();
14233
14280
  var import_node_fs10 = __toESM(require("node:fs"), 1);
14234
14281
  var import_node_path30 = __toESM(require("node:path"), 1);
14235
-
14236
- // src/usage/signIn.ts
14237
- var import_node_path29 = __toESM(require("node:path"), 1);
14238
- var CREDENTIALS_FILE = ".credentials.json";
14239
- function keychainHasItem(run, account) {
14240
- return run.run("security", ["find-generic-password", "-a", account]).status === 0;
14241
- }
14242
- function decideSignIn(facts) {
14243
- if (facts.hasCredentialBlock) {
14244
- return { state: "token", detail: "supplies its own credential through a credential block, so a stored login is not what a launch uses" };
14245
- }
14246
- if (facts.keychainItem === true) {
14247
- return { state: "signed-in", detail: "a login is stored in the macOS Keychain" };
14248
- }
14249
- if (facts.credentialsFile) {
14250
- return { state: "signed-in", detail: `a login is stored in ${CREDENTIALS_FILE}` };
14251
- }
14252
- return { state: "signed-out", detail: facts.platform === "darwin" ? `no Keychain item and no ${CREDENTIALS_FILE}` : `no ${CREDENTIALS_FILE}` };
14253
- }
14254
- function credentialsFilePath(farmRoot) {
14255
- return import_node_path29.default.join(farmRoot, CREDENTIALS_FILE);
14256
- }
14282
+ init_signIn();
14257
14283
 
14258
14284
  // src/codex/siwcStore.ts
14259
14285
  var import_zod22 = require("zod");
@@ -15594,7 +15620,7 @@ function profileValue(name, paths) {
15594
15620
  function createConfigApiRouter(deps) {
15595
15621
  const authed = doorApiAuth(deps.expectedToken);
15596
15622
  const { paths } = deps;
15597
- const route = (path41, summary) => authed.meta((0, import_openapi3.openapi)({ method: "POST", path: path41, summary, tags: [CONFIG_API_TAG] }));
15623
+ const route = (path42, summary) => authed.meta((0, import_openapi3.openapi)({ method: "POST", path: path42, summary, tags: [CONFIG_API_TAG] }));
15598
15624
  return {
15599
15625
  config: {
15600
15626
  identity: {