agent-shim 7.14.0 → 8.0.1

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
@@ -413,7 +413,7 @@ var HeadroomGlobalConfigSchema = HeadroomGlobalConfigObjectSchema.superRefine((c
413
413
  context.addIssue({ code: "custom", path: ["readMaturation"], message: "readMaturation needs rolloutChannel beta or dev" });
414
414
  }
415
415
  });
416
- var HEADROOM_DEFAULT_SOURCE = "headroom-ai[proxy] @ git+https://github.com/ExaDev/headroom@ecd1c351fcfed97499721e86852e148436ff2ee6";
416
+ var HEADROOM_DEFAULT_SOURCE = "headroom-ai[proxy] @ git+https://github.com/ExaDev/headroom@53525f479f2f48e8ef6b08cf729601feab7d2382";
417
417
  var HEADROOM_DEFAULT_IDLE_SHUTDOWN_MINUTES = 15;
418
418
  var FrontDoorGlobalConfigSchema = import_zod.z.strictObject({
419
419
  /** How long the front door may sit with no registered sessions before it closes and exits. Defaults to FRONTDOOR_DEFAULT_IDLE_SHUTDOWN_MINUTES. */
@@ -2650,7 +2650,7 @@ function providerBaseUrl(port, provider) {
2650
2650
  // src/frontdoor/state.ts
2651
2651
  var import_node_path7 = __toESM(require("node:path"), 1);
2652
2652
  var import_zod3 = require("zod");
2653
- var FRONT_DOOR_PROTOCOL = 1;
2653
+ var FRONT_DOOR_PROTOCOL = 2;
2654
2654
  var FrontDoorSessionSchema = import_zod3.z.strictObject({ pid: import_zod3.z.number().int().positive(), startedAt: import_zod3.z.number(), token: import_zod3.z.string().min(1) });
2655
2655
  var FrontDoorStateSchema = import_zod3.z.strictObject({
2656
2656
  /**
@@ -2875,8 +2875,8 @@ function parseConnectTarget(authority) {
2875
2875
  function isInterceptedHost(host, interceptHosts) {
2876
2876
  return interceptHosts.includes(host);
2877
2877
  }
2878
- function servedByPipeline(path28) {
2879
- return path28?.startsWith(ROUTED_PATH_PREFIX) === true;
2878
+ function servedByPipeline(path29) {
2879
+ return path29?.startsWith(ROUTED_PATH_PREFIX) === true;
2880
2880
  }
2881
2881
  var HOP_BY_HOP_HEADERS = /* @__PURE__ */ new Set([
2882
2882
  "connection",
@@ -3442,17 +3442,16 @@ var import_node_crypto5 = require("node:crypto");
3442
3442
  var import_node_path8 = __toESM(require("node:path"), 1);
3443
3443
  var import_zod4 = require("zod");
3444
3444
  var HEADROOM_ANTHROPIC_UPSTREAM = "https://api.anthropic.com";
3445
+ var HEADROOM_STATE_SCHEMA_VERSION = 2;
3445
3446
  var HeadroomStateSchema = import_zod4.z.strictObject({
3446
3447
  /** The supervisor process owning the daemon. Alive means someone is keeping headroom running. */
3447
3448
  supervisorPid: import_zod4.z.number().int().positive().optional(),
3448
3449
  /** The headroom proxy process itself. Absent while the supervisor is between restarts. */
3449
3450
  headroomPid: import_zod4.z.number().int().positive().optional(),
3450
- /** The loopback port the proxy listens on. Absent until the proxy has passed its readiness check, so "port is set" is itself the ready signal a launcher polls for. */
3451
- port: import_zod4.z.number().int().positive().optional(),
3452
3451
  /**
3453
- * The sticky port preference: the address the daemon last served on, kept across crashes, restarts, and idle shutdowns so the next start reuses it. Distinct from `port` on purpose: `port` is the ready signal (absent whenever nothing is serving), while `lastPort` survives every shutdown, because the front door (which routes sessions through this daemon) reads it live and follows a restart to whichever address it lands on.
3452
+ * The unix socket the proxy serves on, inside the owner-only socket directory. Absent until the proxy has passed its readiness check, so "socketPath is set" is itself the ready signal a launcher polls for. The front door reads it on every hop, so a restart (which keeps the generation's path) is followed without anything being relaunched.
3454
3453
  */
3455
- lastPort: import_zod4.z.number().int().positive().optional(),
3454
+ socketPath: import_zod4.z.string().min(1).optional(),
3456
3455
  /** The `headroom --version` output of the running install. */
3457
3456
  version: import_zod4.z.string().optional(),
3458
3457
  /** Hash of the allowlist the running proxy was started with, so a provider-file change is detected as drift. */
@@ -3959,10 +3958,10 @@ function ensureHeadroom(params) {
3959
3958
  for (; ; ) {
3960
3959
  const state = readHeadroomState(ports.fs, paths.headroomStateFile);
3961
3960
  if (state?.supervisorPid !== void 0 && ports.isRunning(state.supervisorPid)) {
3962
- const daemonUp = state.port !== void 0 && state.headroomPid !== void 0 && ports.isRunning(state.headroomPid);
3963
- if (daemonUp && state.port !== void 0) {
3961
+ const daemonUp = state.socketPath !== void 0 && state.headroomPid !== void 0 && ports.isRunning(state.headroomPid);
3962
+ if (daemonUp && state.socketPath !== void 0) {
3964
3963
  writeSession(ports.fs, paths.headroomSessionsDir, { pid: params.launcherPid, startedAt: ports.now(), supervisorPid: state.supervisorPid });
3965
- return { port: state.port };
3964
+ return { socketPath: state.socketPath };
3966
3965
  }
3967
3966
  if (state.lastError !== void 0) {
3968
3967
  throw new HeadroomStartError(
@@ -4026,6 +4025,71 @@ function hashSettings(settings) {
4026
4025
  return (0, import_node_crypto7.createHash)("sha256").update(JSON.stringify([...settingsArgs(settings), JSON.stringify(settingsEnv(settings))])).digest("hex");
4027
4026
  }
4028
4027
 
4028
+ // src/headroom/socket.ts
4029
+ var import_node_path11 = __toESM(require("node:path"), 1);
4030
+ var GROUP_OR_OTHER_BITS = 63;
4031
+ var OCTAL_RADIX = 8;
4032
+ var MODE_DIGITS = 4;
4033
+ var HEADROOM_SOCKET_SUFFIX = ".sock";
4034
+ var HEADROOM_SOCKET_NAME = /^(\d+)\.sock$/;
4035
+ var UNIX_SOCKET_PATH_MAX_BYTES = 103;
4036
+ var PLATFORMS_WITHOUT_UNIX_SOCKETS = ["win32"];
4037
+ function headroomSocketPath(paths, supervisorPid) {
4038
+ return import_node_path11.default.join(paths.headroomSocketDir, `${String(supervisorPid)}${HEADROOM_SOCKET_SUFFIX}`);
4039
+ }
4040
+ function platformRefusal(platform) {
4041
+ return PLATFORMS_WITHOUT_UNIX_SOCKETS.includes(platform) ? `headroom routing needs a unix domain socket, which headroom cannot serve on ${platform}; agent-shim never falls back to a TCP port for this hop` : void 0;
4042
+ }
4043
+ function ownerOnlyRefusal(label, target, stat, expected, uid) {
4044
+ if (stat === void 0) {
4045
+ return `the headroom ${label} ${target} does not exist`;
4046
+ }
4047
+ if (stat.kind === "symlink") {
4048
+ return `the headroom ${label} ${target} is a symlink; it must be the real ${expected === "dir" ? "directory" : "socket"}`;
4049
+ }
4050
+ if (stat.kind !== expected) {
4051
+ return `the headroom ${label} ${target} is not a ${expected === "dir" ? "directory" : "socket"}`;
4052
+ }
4053
+ if (stat.uid !== uid) {
4054
+ return `the headroom ${label} ${target} is owned by uid ${String(stat.uid)}, not by this user (uid ${String(uid)})`;
4055
+ }
4056
+ if ((stat.mode & GROUP_OR_OTHER_BITS) !== 0) {
4057
+ return `the headroom ${label} ${target} has mode ${stat.mode.toString(OCTAL_RADIX).padStart(MODE_DIGITS, "0")}, which lets other users reach it; it must be accessible to its owner only`;
4058
+ }
4059
+ return void 0;
4060
+ }
4061
+ function prepareHeadroomSocket(fs12, ports, paths, supervisorPid) {
4062
+ const unsupported = platformRefusal(ports.platform);
4063
+ if (unsupported !== void 0) {
4064
+ return { refused: unsupported };
4065
+ }
4066
+ const socketPath = headroomSocketPath(paths, supervisorPid);
4067
+ const length = Buffer.byteLength(socketPath, "utf8");
4068
+ if (length > UNIX_SOCKET_PATH_MAX_BYTES) {
4069
+ return {
4070
+ refused: `the headroom socket path ${socketPath} is ${String(length)} bytes, longer than the ${String(UNIX_SOCKET_PATH_MAX_BYTES)} a unix socket path can hold; set AGENT_SHIM_HOME to a shorter directory`
4071
+ };
4072
+ }
4073
+ if (ports.lstat(paths.headroomSocketDir)?.kind === "symlink") {
4074
+ return { refused: `the headroom socket directory ${paths.headroomSocketDir} is a symlink; it must be the real directory` };
4075
+ }
4076
+ fs12.mkdirPrivate(paths.headroomSocketDir);
4077
+ const refusal = ownerOnlyRefusal("socket directory", paths.headroomSocketDir, ports.lstat(paths.headroomSocketDir), "dir", ports.currentUid());
4078
+ return refusal === void 0 ? { socketPath } : { refused: refusal };
4079
+ }
4080
+ function pruneStaleHeadroomSockets(fs12, paths, isRunning) {
4081
+ const removed = [];
4082
+ for (const name of fs12.readdir(paths.headroomSocketDir)) {
4083
+ const pid = HEADROOM_SOCKET_NAME.exec(name)?.[1];
4084
+ if (pid === void 0 || isRunning(Number.parseInt(pid, 10))) {
4085
+ continue;
4086
+ }
4087
+ fs12.removeRecursive(import_node_path11.default.join(paths.headroomSocketDir, name));
4088
+ removed.push(name);
4089
+ }
4090
+ return removed;
4091
+ }
4092
+
4029
4093
  // src/headroom/source.ts
4030
4094
  var import_zod6 = require("zod");
4031
4095
  var GIT_SPEC_RE = /git\+[^@\s]+(?:@([^\s#]+))?/;
@@ -4121,8 +4185,6 @@ async function runSupervisor(initialConfig, ports, options = {}) {
4121
4185
  return 0;
4122
4186
  }
4123
4187
  let installedSource = previousState?.installedSource;
4124
- let lastPort = previousState?.lastPort;
4125
- const sticky = () => lastPort === void 0 ? {} : { lastPort };
4126
4188
  const ownsState = () => {
4127
4189
  const owner = readHeadroomState(fs12, paths.headroomStateFile)?.supervisorPid;
4128
4190
  return owner === void 0 || owner === ports.ownPid || !ports.isRunning(owner);
@@ -4135,7 +4197,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
4135
4197
  return true;
4136
4198
  };
4137
4199
  const fail = (message) => {
4138
- if (writeOwnState({ lastError: message, ...sticky() })) {
4200
+ if (writeOwnState({ lastError: message })) {
4139
4201
  fs12.removeRecursive(paths.headroomLockFile);
4140
4202
  }
4141
4203
  ports.log(`agent-shim headroom supervisor: ${message}`);
@@ -4158,11 +4220,17 @@ async function runSupervisor(initialConfig, ports, options = {}) {
4158
4220
  installedSource = config.source;
4159
4221
  return true;
4160
4222
  };
4223
+ const socket = prepareHeadroomSocket(fs12, ports.socketTrust, paths, ports.ownPid);
4224
+ if (socket.refused !== void 0) {
4225
+ return fail(socket.refused);
4226
+ }
4227
+ const { socketPath } = socket;
4228
+ pruneStaleHeadroomSockets(fs12, paths, ports.isRunning);
4161
4229
  if (!ensureInstalled()) {
4162
4230
  return fail(`could not install headroom from ${config.source}: install failed (is uv installed and on PATH?)`);
4163
4231
  }
4164
4232
  const version = ports.headroomVersion() ?? "unknown";
4165
- writeOwnState({ supervisorPid: ports.ownPid, version, installedSource, ...sticky() });
4233
+ writeOwnState({ supervisorPid: ports.ownPid, version, installedSource });
4166
4234
  ports.log(`agent-shim headroom supervisor ${String(ports.ownPid)}: managing headroom on allowlist [${allowlistOf(ports).join(", ")}]`);
4167
4235
  const orphanPid = previousState?.headroomPid;
4168
4236
  if (orphanPid !== void 0 && ports.isRunning(orphanPid)) {
@@ -4188,7 +4256,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
4188
4256
  pruneDeadSessions(fs12, paths.headroomSessionsDir, ports.isRunning);
4189
4257
  const ownsNow = ownsState();
4190
4258
  if (!ownsNow && !superseded) {
4191
- ports.log("agent-shim headroom supervisor: another supervisor now owns state.json; serving this daemon's own sessions until they end");
4259
+ ports.log("agent-shim headroom supervisor: another supervisor now owns the state file; serving this daemon's own sessions until they end");
4192
4260
  }
4193
4261
  superseded = !ownsNow;
4194
4262
  const crashed = headroomPid !== void 0 && !ports.isRunning(headroomPid);
@@ -4201,8 +4269,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
4201
4269
  writeOwnState({
4202
4270
  supervisorPid: ports.ownPid,
4203
4271
  version,
4204
- installedSource,
4205
- ...sticky()
4272
+ installedSource
4206
4273
  });
4207
4274
  }
4208
4275
  if (consecutiveFailures >= HEADROOM_START_RETRY_BUDGET) {
@@ -4211,41 +4278,32 @@ async function runSupervisor(initialConfig, ports, options = {}) {
4211
4278
  if (installedSource !== config.source && !ensureInstalled()) {
4212
4279
  return fail(`could not install headroom from ${config.source}: install failed (is uv installed and on PATH?)`);
4213
4280
  }
4214
- const previousSticky = lastPort;
4215
- const port = lastPort !== void 0 && await ports.isPortFree(lastPort) ? lastPort : await ports.freePort();
4216
- const pid = ports.spawnHeadroom(port, allowlist, config.settings);
4217
- const ready = await waitUntilReady(ports, port);
4281
+ const pid = ports.spawnHeadroom(socketPath, allowlist, config.settings);
4282
+ const ready = await waitUntilReady(ports, socketPath);
4218
4283
  if (ready) {
4219
4284
  consecutiveFailures = 0;
4220
4285
  headroomPid = pid;
4221
4286
  runningHash = allowlistHash;
4222
4287
  runningSettingsHash = settingsHash;
4223
- lastPort = port;
4224
- if (previousSticky !== void 0 && port !== previousSticky) {
4225
- ports.log(
4226
- `agent-shim headroom supervisor: sticky port ${String(previousSticky)} was occupied; moving to ${String(port)} (sessions launched against the old port are stale until they relaunch)`
4227
- );
4228
- }
4229
4288
  const recorded = writeOwnState({
4230
4289
  supervisorPid: ports.ownPid,
4231
4290
  headroomPid: pid,
4232
- port,
4291
+ socketPath,
4233
4292
  version,
4234
4293
  allowlistHash,
4235
4294
  settingsHash,
4236
- installedSource: config.source,
4237
- ...sticky()
4295
+ installedSource: config.source
4238
4296
  });
4239
4297
  if (recorded) {
4240
4298
  fs12.removeRecursive(paths.headroomLockFile);
4241
4299
  }
4242
4300
  idleSince = void 0;
4243
- ports.log(`agent-shim headroom supervisor: headroom pid ${String(pid)} ready on 127.0.0.1:${String(port)}`);
4301
+ ports.log(`agent-shim headroom supervisor: headroom pid ${String(pid)} ready on unix socket ${socketPath}`);
4244
4302
  } else {
4245
4303
  ports.stopProcess(pid);
4246
4304
  consecutiveFailures += 1;
4247
4305
  ports.log(
4248
- `agent-shim headroom supervisor: headroom did not become ready on port ${String(port)} (attempt ${String(consecutiveFailures)} of ${String(HEADROOM_START_RETRY_BUDGET)})`
4306
+ `agent-shim headroom supervisor: headroom did not become ready on unix socket ${socketPath} (attempt ${String(consecutiveFailures)} of ${String(HEADROOM_START_RETRY_BUDGET)})`
4249
4307
  );
4250
4308
  await ports.sleep(backoffForAttempt(consecutiveFailures));
4251
4309
  continue;
@@ -4270,10 +4328,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
4270
4328
  `agent-shim headroom supervisor: no sessions for ${String(config.idleShutdownMinutes)} minute(s); stopping headroom and exiting`
4271
4329
  );
4272
4330
  ports.stopProcess(headroomPid);
4273
- writeOwnState({
4274
- version,
4275
- ...sticky()
4276
- });
4331
+ writeOwnState({ version });
4277
4332
  return 0;
4278
4333
  }
4279
4334
  } else {
@@ -4290,10 +4345,10 @@ function currentHeadroomAllowlist(fs12, paths) {
4290
4345
  function allowlistOf(ports) {
4291
4346
  return currentHeadroomAllowlist(ports.fs, ports.paths);
4292
4347
  }
4293
- async function waitUntilReady(ports, port) {
4348
+ async function waitUntilReady(ports, socketPath) {
4294
4349
  const deadline = ports.now() + HEADROOM_READY_TIMEOUT_MS;
4295
4350
  for (; ; ) {
4296
- if (await ports.ready(port)) {
4351
+ if (await ports.ready(socketPath)) {
4297
4352
  return true;
4298
4353
  }
4299
4354
  if (ports.now() >= deadline) {
@@ -4353,14 +4408,14 @@ function evaluateAmbientCredentialGuard(params) {
4353
4408
  // src/paths.ts
4354
4409
  var import_node_fs2 = __toESM(require("node:fs"), 1);
4355
4410
  var import_node_os = __toESM(require("node:os"), 1);
4356
- var import_node_path11 = __toESM(require("node:path"), 1);
4411
+ var import_node_path12 = __toESM(require("node:path"), 1);
4357
4412
  function resolveAgentShimHome(env = process.env, home = import_node_os.default.homedir(), isDirectory = isExistingDirectory) {
4358
4413
  const fromEnv = env.AGENT_SHIM_HOME;
4359
4414
  if (fromEnv !== void 0 && fromEnv !== "") {
4360
4415
  return fromEnv;
4361
4416
  }
4362
- const current = import_node_path11.default.join(home, HOME_DIRNAME);
4363
- const legacy = import_node_path11.default.join(home, LEGACY_HOME_DIRNAME);
4417
+ const current = import_node_path12.default.join(home, HOME_DIRNAME);
4418
+ const legacy = import_node_path12.default.join(home, LEGACY_HOME_DIRNAME);
4364
4419
  return !isDirectory(current) && isDirectory(legacy) ? legacy : current;
4365
4420
  }
4366
4421
  function isExistingDirectory(candidate) {
@@ -4371,38 +4426,39 @@ function resolveClaudeHome() {
4371
4426
  if (fromEnv !== void 0 && fromEnv !== "") {
4372
4427
  return fromEnv;
4373
4428
  }
4374
- return import_node_path11.default.join(import_node_os.default.homedir(), ".claude");
4429
+ return import_node_path12.default.join(import_node_os.default.homedir(), ".claude");
4375
4430
  }
4376
4431
  function buildLayoutPaths(root) {
4377
4432
  return {
4378
4433
  root,
4379
- identitiesDir: import_node_path11.default.join(root, "identities"),
4380
- configProfilesDir: import_node_path11.default.join(root, "config-profiles"),
4381
- providersDir: import_node_path11.default.join(root, "providers"),
4382
- directoryRulesFile: import_node_path11.default.join(root, "directory-rules.json"),
4383
- activeIdentityFile: import_node_path11.default.join(root, "active-identity"),
4384
- globalConfigFile: import_node_path11.default.join(root, "config.json"),
4385
- categoriesLocalFile: import_node_path11.default.join(root, "categories.local.json"),
4386
- claudeShimFile: import_node_path11.default.join(root, "claude-shim.json"),
4387
- headroomDir: import_node_path11.default.join(root, "headroom"),
4388
- headroomStateFile: import_node_path11.default.join(root, "headroom", "state.json"),
4389
- headroomLockFile: import_node_path11.default.join(root, "headroom", "start.lock"),
4390
- headroomSessionsDir: import_node_path11.default.join(root, "headroom", "sessions"),
4391
- logsDir: import_node_path11.default.join(root, "logs"),
4392
- headroomLogPath: import_node_path11.default.join(root, "logs", "headroom.log"),
4393
- frontdoorDir: import_node_path11.default.join(root, "frontdoor"),
4394
- frontdoorCaDir: import_node_path11.default.join(root, "frontdoor", "ca"),
4395
- frontdoorCaCertFile: import_node_path11.default.join(root, "frontdoor", "ca", "ca.pem"),
4396
- frontdoorCaKeyFile: import_node_path11.default.join(root, "frontdoor", "ca", "ca.key"),
4397
- frontdoorCaBundlesDir: import_node_path11.default.join(root, "frontdoor", "ca", "bundles"),
4398
- frontdoorStateFile: import_node_path11.default.join(root, "frontdoor", "state.json"),
4399
- frontdoorLockFile: import_node_path11.default.join(root, "frontdoor", "start.lock"),
4400
- frontdoorSessionsDir: import_node_path11.default.join(root, "frontdoor", "sessions"),
4401
- frontdoorLogPath: import_node_path11.default.join(root, "logs", "frontdoor.log"),
4402
- usageDir: import_node_path11.default.join(root, "usage"),
4403
- usageLogDir: import_node_path11.default.join(root, "usage", "log"),
4404
- usageSnapshotsDir: import_node_path11.default.join(root, "usage", "snapshots"),
4405
- usagePicksFile: import_node_path11.default.join(root, "usage", "picks.json")
4434
+ identitiesDir: import_node_path12.default.join(root, "identities"),
4435
+ configProfilesDir: import_node_path12.default.join(root, "config-profiles"),
4436
+ providersDir: import_node_path12.default.join(root, "providers"),
4437
+ directoryRulesFile: import_node_path12.default.join(root, "directory-rules.json"),
4438
+ activeIdentityFile: import_node_path12.default.join(root, "active-identity"),
4439
+ globalConfigFile: import_node_path12.default.join(root, "config.json"),
4440
+ categoriesLocalFile: import_node_path12.default.join(root, "categories.local.json"),
4441
+ claudeShimFile: import_node_path12.default.join(root, "claude-shim.json"),
4442
+ headroomDir: import_node_path12.default.join(root, "headroom"),
4443
+ headroomStateFile: import_node_path12.default.join(root, "headroom", `state.v${String(HEADROOM_STATE_SCHEMA_VERSION)}.json`),
4444
+ headroomSocketDir: import_node_path12.default.join(root, "headroom", "run"),
4445
+ headroomLockFile: import_node_path12.default.join(root, "headroom", "start.lock"),
4446
+ headroomSessionsDir: import_node_path12.default.join(root, "headroom", "sessions"),
4447
+ logsDir: import_node_path12.default.join(root, "logs"),
4448
+ headroomLogPath: import_node_path12.default.join(root, "logs", "headroom.log"),
4449
+ frontdoorDir: import_node_path12.default.join(root, "frontdoor"),
4450
+ frontdoorCaDir: import_node_path12.default.join(root, "frontdoor", "ca"),
4451
+ frontdoorCaCertFile: import_node_path12.default.join(root, "frontdoor", "ca", "ca.pem"),
4452
+ frontdoorCaKeyFile: import_node_path12.default.join(root, "frontdoor", "ca", "ca.key"),
4453
+ frontdoorCaBundlesDir: import_node_path12.default.join(root, "frontdoor", "ca", "bundles"),
4454
+ frontdoorStateFile: import_node_path12.default.join(root, "frontdoor", "state.json"),
4455
+ frontdoorLockFile: import_node_path12.default.join(root, "frontdoor", "start.lock"),
4456
+ frontdoorSessionsDir: import_node_path12.default.join(root, "frontdoor", "sessions"),
4457
+ frontdoorLogPath: import_node_path12.default.join(root, "logs", "frontdoor.log"),
4458
+ usageDir: import_node_path12.default.join(root, "usage"),
4459
+ usageLogDir: import_node_path12.default.join(root, "usage", "log"),
4460
+ usageSnapshotsDir: import_node_path12.default.join(root, "usage", "snapshots"),
4461
+ usagePicksFile: import_node_path12.default.join(root, "usage", "picks.json")
4406
4462
  };
4407
4463
  }
4408
4464
  function resolveLayoutPaths() {
@@ -4411,10 +4467,10 @@ function resolveLayoutPaths() {
4411
4467
 
4412
4468
  // src/identityStore.ts
4413
4469
  var import_node_fs4 = __toESM(require("node:fs"), 1);
4414
- var import_node_path14 = __toESM(require("node:path"), 1);
4470
+ var import_node_path15 = __toESM(require("node:path"), 1);
4415
4471
 
4416
4472
  // src/launcher/identity.ts
4417
- var import_node_path12 = __toESM(require("node:path"), 1);
4473
+ var import_node_path13 = __toESM(require("node:path"), 1);
4418
4474
  function poolNameOf(selector) {
4419
4475
  return selector.startsWith(POOL_SELECTOR_PREFIX) ? selector.slice(POOL_SELECTOR_PREFIX.length) : void 0;
4420
4476
  }
@@ -4463,12 +4519,12 @@ function decideConfigProfile(params) {
4463
4519
  return { source: "none" };
4464
4520
  }
4465
4521
  function loadIdentity(identitiesDir, name, fs12) {
4466
- return loadConfigFile(import_node_path12.default.join(identitiesDir, name, "identity.json"), IdentitySchema, fs12.readConfigFile);
4522
+ return loadConfigFile(import_node_path13.default.join(identitiesDir, name, "identity.json"), IdentitySchema, fs12.readConfigFile);
4467
4523
  }
4468
4524
 
4469
4525
  // src/configProfilesStore.ts
4470
4526
  var import_node_fs3 = __toESM(require("node:fs"), 1);
4471
- var import_node_path13 = __toESM(require("node:path"), 1);
4527
+ var import_node_path14 = __toESM(require("node:path"), 1);
4472
4528
  var ProfileNotFoundError = class extends CliError {
4473
4529
  constructor(profileName) {
4474
4530
  super(`No configuration profile named "${profileName}". Run \`agent-shim profile add ${profileName}\` first.`);
@@ -4494,7 +4550,7 @@ var InvalidCategoryNameError = class extends CliError {
4494
4550
  categoryName;
4495
4551
  };
4496
4552
  function profileJsonPath(paths, name) {
4497
- return import_node_path13.default.join(paths.configProfilesDir, `${name}.json`);
4553
+ return import_node_path14.default.join(paths.configProfilesDir, `${name}.json`);
4498
4554
  }
4499
4555
  function profileExists(paths, name) {
4500
4556
  return import_node_fs3.default.existsSync(profileJsonPath(paths, name));
@@ -4682,7 +4738,7 @@ var InvalidIdentityNameError = class extends CliError {
4682
4738
  attemptedName;
4683
4739
  };
4684
4740
  function identityJsonPath(paths, name) {
4685
- return import_node_path14.default.join(paths.identitiesDir, name, "identity.json");
4741
+ return import_node_path15.default.join(paths.identitiesDir, name, "identity.json");
4686
4742
  }
4687
4743
  function identityExists(paths, name) {
4688
4744
  return import_node_fs4.default.existsSync(identityJsonPath(paths, name));
@@ -4783,7 +4839,7 @@ function setIdentityCredential(paths, identityName, change) {
4783
4839
  });
4784
4840
  }
4785
4841
  function belongsToIdentity(entry, name) {
4786
- return entry === name || entry === import_node_path14.default.basename(identityLockPath("", name)) || entry.startsWith(`.${name}.scratch.`) || entry.startsWith(`.${name}.previous.`);
4842
+ return entry === name || entry === import_node_path15.default.basename(identityLockPath("", name)) || entry.startsWith(`.${name}.scratch.`) || entry.startsWith(`.${name}.previous.`);
4787
4843
  }
4788
4844
  function removeIdentity(paths, name) {
4789
4845
  if (!identityExists(paths, name)) {
@@ -4791,7 +4847,7 @@ function removeIdentity(paths, name) {
4791
4847
  }
4792
4848
  for (const entry of import_node_fs4.default.readdirSync(paths.identitiesDir)) {
4793
4849
  if (belongsToIdentity(entry, name)) {
4794
- import_node_fs4.default.rmSync(import_node_path14.default.join(paths.identitiesDir, entry), { recursive: true, force: true });
4850
+ import_node_fs4.default.rmSync(import_node_path15.default.join(paths.identitiesDir, entry), { recursive: true, force: true });
4795
4851
  }
4796
4852
  }
4797
4853
  if (readActiveIdentity(paths) === name) {
@@ -4801,7 +4857,7 @@ function removeIdentity(paths, name) {
4801
4857
 
4802
4858
  // src/providersStore.ts
4803
4859
  var import_node_fs5 = __toESM(require("node:fs"), 1);
4804
- var import_node_path15 = __toESM(require("node:path"), 1);
4860
+ var import_node_path16 = __toESM(require("node:path"), 1);
4805
4861
 
4806
4862
  // src/credentialCache.ts
4807
4863
  var import_zod7 = require("zod");
@@ -4838,7 +4894,7 @@ var CREDENTIAL_COMMAND_TIMEOUT_MS = 1e4;
4838
4894
  var CREDENTIAL_INTERACTIVE_TIMEOUT_MS = 12e4;
4839
4895
  var GROUP_OTHER_PERMISSION_BITS = 63;
4840
4896
  var PERMISSION_BITS = 511;
4841
- var OCTAL_RADIX = 8;
4897
+ var OCTAL_RADIX2 = 8;
4842
4898
  function commandArgv(source) {
4843
4899
  if ("command" in source) {
4844
4900
  return source.command;
@@ -4931,7 +4987,7 @@ function trySource(source, params) {
4931
4987
  }
4932
4988
  if (read.mode !== void 0 && (read.mode & GROUP_OTHER_PERMISSION_BITS) !== 0) {
4933
4989
  return none(
4934
- `is readable or writable by group or others (mode ${(read.mode & PERMISSION_BITS).toString(OCTAL_RADIX)}); run \`chmod 600 ${source.file}\``,
4990
+ `is readable or writable by group or others (mode ${(read.mode & PERMISSION_BITS).toString(OCTAL_RADIX2)}); run \`chmod 600 ${source.file}\``,
4935
4991
  true
4936
4992
  );
4937
4993
  }
@@ -5027,7 +5083,7 @@ var InvalidProviderNameError = class extends CliError {
5027
5083
  };
5028
5084
  var PROVIDER_NAME_RE = /^[A-Za-z0-9][A-Za-z0-9._@-]*$/;
5029
5085
  function providerJsonPath(paths, name) {
5030
- return import_node_path15.default.join(paths.providersDir, `${name}.json`);
5086
+ return import_node_path16.default.join(paths.providersDir, `${name}.json`);
5031
5087
  }
5032
5088
  function providerExists(paths, name) {
5033
5089
  return import_node_fs5.default.existsSync(providerJsonPath(paths, name));
@@ -5103,7 +5159,7 @@ function readProvider(paths, name) {
5103
5159
  return parseProviderFile(filePath, raw);
5104
5160
  }
5105
5161
  function loadProvider(providersDir, name, port) {
5106
- const filePath = import_node_path15.default.join(providersDir, `${name}.json`);
5162
+ const filePath = import_node_path16.default.join(providersDir, `${name}.json`);
5107
5163
  const raw = port.readConfigFile(filePath);
5108
5164
  return raw === void 0 ? void 0 : parseProviderFile(filePath, raw);
5109
5165
  }
@@ -5358,21 +5414,21 @@ function removeDirectoryRule(paths, rulePath) {
5358
5414
  var import_node_os4 = __toESM(require("node:os"), 1);
5359
5415
 
5360
5416
  // src/launcher/cascade.ts
5361
- var import_node_path17 = __toESM(require("node:path"), 1);
5417
+ var import_node_path18 = __toESM(require("node:path"), 1);
5362
5418
 
5363
5419
  // src/pathNorm.ts
5364
- var import_node_path16 = __toESM(require("node:path"), 1);
5420
+ var import_node_path17 = __toESM(require("node:path"), 1);
5365
5421
  function expandTilde(value, home) {
5366
5422
  if (value === "~") {
5367
5423
  return home;
5368
5424
  }
5369
5425
  if (value.startsWith("~/")) {
5370
- return import_node_path16.default.join(home, value.slice(2));
5426
+ return import_node_path17.default.join(home, value.slice(2));
5371
5427
  }
5372
5428
  return value;
5373
5429
  }
5374
5430
  function normaliseRulePath(rulePath, home) {
5375
- return import_node_path16.default.resolve(expandTilde(rulePath, home));
5431
+ return import_node_path17.default.resolve(expandTilde(rulePath, home));
5376
5432
  }
5377
5433
 
5378
5434
  // src/launcher/cascade.ts
@@ -5382,7 +5438,7 @@ function loadCascadeInput(params) {
5382
5438
  const globalConfig = loadConfigFile(params.paths.globalConfigFile, GlobalConfigSchema, params.read);
5383
5439
  const directoryRules = loadConfigFile(params.paths.directoryRulesFile, DirectoryRulesSchema, params.read);
5384
5440
  const loadProfile = (name) => {
5385
- const filepath = import_node_path17.default.join(params.paths.configProfilesDir, `${name}.json`);
5441
+ const filepath = import_node_path18.default.join(params.paths.configProfilesDir, `${name}.json`);
5386
5442
  const loaded = loadConfigFile(filepath, ConfigProfileSchema, params.read);
5387
5443
  if (loaded === void 0) {
5388
5444
  return void 0;
@@ -5397,8 +5453,8 @@ function loadCascadeInput(params) {
5397
5453
  });
5398
5454
  const levels = [];
5399
5455
  for (const dir of dirs) {
5400
- const portable = loadConfigFile(import_node_path17.default.join(dir, PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(import_node_path17.default.join(dir, LEGACY_PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read);
5401
- const portableLocal = loadConfigFile(import_node_path17.default.join(dir, PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(import_node_path17.default.join(dir, LEGACY_PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read);
5456
+ const portable = loadConfigFile(import_node_path18.default.join(dir, PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(import_node_path18.default.join(dir, LEGACY_PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read);
5457
+ const portableLocal = loadConfigFile(import_node_path18.default.join(dir, PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(import_node_path18.default.join(dir, LEGACY_PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read);
5402
5458
  const rules = (directoryRules?.config.rules ?? []).map((rule, index) => ({ rule, index })).filter(({ rule }) => normaliseRulePath(rule.path, params.home) === dir).map(({ rule, index }) => {
5403
5459
  const entryOrder = directoryRules?.ruleEntryOrders[index];
5404
5460
  return {
@@ -5495,7 +5551,7 @@ function quotaWarnings(snapshot, provider, nowMs) {
5495
5551
  }
5496
5552
 
5497
5553
  // src/usage/poolPick.ts
5498
- var import_node_path18 = __toESM(require("node:path"), 1);
5554
+ var import_node_path19 = __toESM(require("node:path"), 1);
5499
5555
  var import_zod9 = require("zod");
5500
5556
 
5501
5557
  // src/usage/plan.ts
@@ -5797,7 +5853,7 @@ function recordStickyPick(fs12, picksFile, directory, identity, nowMs) {
5797
5853
  const current = readPicksFile(fs12, picksFile).file.picks;
5798
5854
  const kept = Object.entries(current).filter(([, entry]) => nowMs - Date.parse(entry.at) <= USAGE_RETENTION_MS);
5799
5855
  const next = { schemaVersion: SCHEMA_VERSION, picks: { ...Object.fromEntries(kept), [directory]: { identity, at: new Date(nowMs).toISOString() } } };
5800
- fs12.mkdirPrivate(import_node_path18.default.dirname(picksFile));
5856
+ fs12.mkdirPrivate(import_node_path19.default.dirname(picksFile));
5801
5857
  fs12.writeFilePrivate(picksFile, `${JSON.stringify(next, null, 2)}
5802
5858
  `);
5803
5859
  }
@@ -5894,14 +5950,14 @@ var import_node_child_process = require("node:child_process");
5894
5950
  var import_node_crypto8 = require("node:crypto");
5895
5951
  var import_node_fs6 = __toESM(require("node:fs"), 1);
5896
5952
  var import_node_os3 = __toESM(require("node:os"), 1);
5897
- var import_node_path20 = __toESM(require("node:path"), 1);
5953
+ var import_node_path21 = __toESM(require("node:path"), 1);
5898
5954
  var import_node_sea = require("node:sea");
5899
5955
 
5900
5956
  // src/versionDiscovery.ts
5901
5957
  var import_node_os2 = __toESM(require("node:os"), 1);
5902
- var import_node_path19 = __toESM(require("node:path"), 1);
5958
+ var import_node_path20 = __toESM(require("node:path"), 1);
5903
5959
  function defaultVersionsDir() {
5904
- return import_node_path19.default.join(import_node_os2.default.homedir(), ".local", "share", "claude", "versions");
5960
+ return import_node_path20.default.join(import_node_os2.default.homedir(), ".local", "share", "claude", "versions");
5905
5961
  }
5906
5962
  var NUMERIC_DOTTED_VERSION_RE = /^\d+(?:\.\d+)*$/;
5907
5963
  function isNumericDottedVersion(name) {
@@ -5943,14 +5999,14 @@ function discoverClaudeBinary(options) {
5943
5999
  const highestVersion = pickHighestVersion(entries);
5944
6000
  if (highestVersion !== void 0) {
5945
6001
  return {
5946
- path: import_node_path19.default.join(versionsDir, highestVersion),
6002
+ path: import_node_path20.default.join(versionsDir, highestVersion),
5947
6003
  source: "versions-dir",
5948
6004
  version: highestVersion
5949
6005
  };
5950
6006
  }
5951
- const ownInstallDirs = new Set(options.ownInstallDirs.map((dir) => import_node_path19.default.resolve(dir)));
6007
+ const ownInstallDirs = new Set(options.ownInstallDirs.map((dir) => import_node_path20.default.resolve(dir)));
5952
6008
  for (const dir of options.pathDirs) {
5953
- if (ownInstallDirs.has(import_node_path19.default.resolve(dir))) {
6009
+ if (ownInstallDirs.has(import_node_path20.default.resolve(dir))) {
5954
6010
  continue;
5955
6011
  }
5956
6012
  const found = options.findExecutableInDir(dir, "claude");
@@ -6121,7 +6177,7 @@ var realRunPort = {
6121
6177
  }
6122
6178
  };
6123
6179
  function expandHome2(filePath) {
6124
- return filePath.startsWith("~/") ? import_node_path20.default.join(import_node_os3.default.homedir(), filePath.slice(1)) : filePath;
6180
+ return filePath.startsWith("~/") ? import_node_path21.default.join(import_node_os3.default.homedir(), filePath.slice(1)) : filePath;
6125
6181
  }
6126
6182
  var MACOS_GUI_SESSION_MANAGER = "Aqua";
6127
6183
  function hasDesktopSession() {
@@ -6194,7 +6250,7 @@ function spawnDaemonThrough(executable) {
6194
6250
  return (paths, subcommand, logPath) => spawnDetachedDaemon({ command: executable, args: [subcommand] }, paths, subcommand, logPath);
6195
6251
  }
6196
6252
  function spawnDetachedDaemon(invocation, paths, subcommand, logPath) {
6197
- import_node_fs6.default.mkdirSync(import_node_path20.default.dirname(logPath), { recursive: true });
6253
+ import_node_fs6.default.mkdirSync(import_node_path21.default.dirname(logPath), { recursive: true });
6198
6254
  const logFd = import_node_fs6.default.openSync(logPath, "a");
6199
6255
  try {
6200
6256
  const child = (0, import_node_child_process.spawn)(invocation.command, invocation.args, detachedDaemonSpawnOptions(logFd, { ...process.env, AGENT_SHIM_HOME: paths.root }));
@@ -6210,6 +6266,29 @@ function spawnDetachedDaemon(invocation, paths, subcommand, logPath) {
6210
6266
  function spawnHeadroomSupervisor(paths, spawnDaemon) {
6211
6267
  return spawnDaemon(paths, "__headroom-supervisor", paths.headroomLogPath);
6212
6268
  }
6269
+ var SOCKET_PERMISSION_BITS = 511;
6270
+ var realHeadroomSocketTrust = {
6271
+ platform: process.platform,
6272
+ currentUid: () => {
6273
+ if (process.getuid === void 0) {
6274
+ throw new Error(`no POSIX user id on ${process.platform}`);
6275
+ }
6276
+ return process.getuid();
6277
+ },
6278
+ lstat: (target) => {
6279
+ let stat;
6280
+ try {
6281
+ stat = import_node_fs6.default.lstatSync(target);
6282
+ } catch (error) {
6283
+ if (isEnoent3(error)) {
6284
+ return void 0;
6285
+ }
6286
+ throw error;
6287
+ }
6288
+ const kind = stat.isSymbolicLink() ? "symlink" : stat.isDirectory() ? "dir" : stat.isSocket() ? "socket" : "other";
6289
+ return { kind, uid: stat.uid, mode: stat.mode & SOCKET_PERMISSION_BITS };
6290
+ }
6291
+ };
6213
6292
  function realHeadroomPort(paths, options) {
6214
6293
  return {
6215
6294
  ensure: () => {
@@ -6226,7 +6305,7 @@ function realHeadroomPort(paths, options) {
6226
6305
  }
6227
6306
  });
6228
6307
  return {
6229
- port: up.port,
6308
+ socketPath: up.socketPath,
6230
6309
  projectId: resolveGitRoot(realRunPort, options.cwd) ?? options.cwd
6231
6310
  };
6232
6311
  },
@@ -6252,7 +6331,7 @@ function listVersionsDir(dir) {
6252
6331
  throw error;
6253
6332
  }
6254
6333
  return entries.filter((entry) => entry.isFile()).map((entry) => {
6255
- const fullPath = import_node_path20.default.join(dir, entry.name);
6334
+ const fullPath = import_node_path21.default.join(dir, entry.name);
6256
6335
  const stat = import_node_fs6.default.statSync(fullPath);
6257
6336
  return {
6258
6337
  name: entry.name,
@@ -6267,7 +6346,7 @@ function windowsPathExtensions(pathext) {
6267
6346
  return (pathext ?? WINDOWS_DEFAULT_PATHEXT).split(";").map((ext) => ext.trim()).filter((ext) => ext.length > 0);
6268
6347
  }
6269
6348
  function resolveExecutableCandidate(dir, name, env) {
6270
- const candidate = import_node_path20.default.join(dir, name);
6349
+ const candidate = import_node_path21.default.join(dir, name);
6271
6350
  if (env.platform === "win32") {
6272
6351
  const extensions = windowsPathExtensions(env.pathext);
6273
6352
  const alreadyHasRecognisedExtension = extensions.some((ext) => candidate.toLowerCase().endsWith(ext.toLowerCase()));
@@ -6316,13 +6395,13 @@ function resolveOwnExecutablePath(env) {
6316
6395
  if (env.argv1 !== void 0 && !env.argv1.includes("/") && !env.argv1.includes("\\")) {
6317
6396
  return searchPathForExecutable(env.pathDirs, env.argv1, env.findExecutableInDir) ?? env.execPath;
6318
6397
  }
6319
- const candidate = env.argv1 === void 0 ? env.execPath : import_node_path20.default.resolve(env.cwd, env.argv1);
6320
- const candidateDir = import_node_path20.default.dirname(candidate);
6321
- const candidateDirOnPath = env.pathDirs.some((dir) => import_node_path20.default.resolve(dir) === candidateDir);
6398
+ const candidate = env.argv1 === void 0 ? env.execPath : import_node_path21.default.resolve(env.cwd, env.argv1);
6399
+ const candidateDir = import_node_path21.default.dirname(candidate);
6400
+ const candidateDirOnPath = env.pathDirs.some((dir) => import_node_path21.default.resolve(dir) === candidateDir);
6322
6401
  if (candidateDirOnPath) {
6323
6402
  return candidate;
6324
6403
  }
6325
- const viaPath = searchPathForExecutable(env.pathDirs, import_node_path20.default.basename(candidate), env.findExecutableInDir);
6404
+ const viaPath = searchPathForExecutable(env.pathDirs, import_node_path21.default.basename(candidate), env.findExecutableInDir);
6326
6405
  return viaPath ?? candidate;
6327
6406
  }
6328
6407
  function realOwnExecutablePath() {
@@ -6330,21 +6409,21 @@ function realOwnExecutablePath() {
6330
6409
  argv1: process.argv[1],
6331
6410
  execPath: process.execPath,
6332
6411
  cwd: process.cwd(),
6333
- pathDirs: (process.env.PATH ?? "").split(import_node_path20.default.delimiter).filter((dir) => dir !== ""),
6412
+ pathDirs: (process.env.PATH ?? "").split(import_node_path21.default.delimiter).filter((dir) => dir !== ""),
6334
6413
  findExecutableInDir
6335
6414
  });
6336
6415
  }
6337
6416
  function realResolveClaudeBinary(ownInstallDirs) {
6338
6417
  return () => discoverClaudeBinary({
6339
6418
  listVersionsDir,
6340
- pathDirs: (process.env.PATH ?? "").split(import_node_path20.default.delimiter).filter((dir) => dir !== ""),
6419
+ pathDirs: (process.env.PATH ?? "").split(import_node_path21.default.delimiter).filter((dir) => dir !== ""),
6341
6420
  findExecutableInDir,
6342
6421
  ownInstallDirs: [...ownInstallDirs]
6343
6422
  });
6344
6423
  }
6345
6424
 
6346
6425
  // src/checkReport.ts
6347
- var import_node_path21 = __toESM(require("node:path"), 1);
6426
+ var import_node_path22 = __toESM(require("node:path"), 1);
6348
6427
  var import_zod10 = require("zod");
6349
6428
 
6350
6429
  // src/cli/bool.ts
@@ -6712,10 +6791,10 @@ function collectCheckReport(params) {
6712
6791
  }).input;
6713
6792
  const providerName = cascadeProviderName(cascade);
6714
6793
  const provider = providerName === void 0 ? void 0 : loadCheckProvider(paths, providerName);
6715
- const farmRoot = identityDecision.name === void 0 ? void 0 : import_node_path21.default.join(paths.identitiesDir, identityDecision.name);
6794
+ const farmRoot = identityDecision.name === void 0 ? void 0 : import_node_path22.default.join(paths.identitiesDir, identityDecision.name);
6716
6795
  const settingsFiles = {
6717
- "settings.json": realFsPort.readFileUtf8(import_node_path21.default.join(claudeHome, "settings.json")),
6718
- "settings.local.json": realFsPort.readFileUtf8(import_node_path21.default.join(claudeHome, "settings.local.json"))
6796
+ "settings.json": realFsPort.readFileUtf8(import_node_path22.default.join(claudeHome, "settings.json")),
6797
+ "settings.local.json": realFsPort.readFileUtf8(import_node_path22.default.join(claudeHome, "settings.local.json"))
6719
6798
  };
6720
6799
  const report = runCheck({
6721
6800
  cwd,
@@ -6745,7 +6824,7 @@ function collectCheckReport(params) {
6745
6824
 
6746
6825
  // src/claudeShim.ts
6747
6826
  var import_node_fs7 = __toESM(require("node:fs"), 1);
6748
- var import_node_path22 = __toESM(require("node:path"), 1);
6827
+ var import_node_path23 = __toESM(require("node:path"), 1);
6749
6828
  var import_zod11 = require("zod");
6750
6829
  var ClaudeShimStateSchema = import_zod11.z.strictObject({
6751
6830
  targetPath: import_zod11.z.string().min(1),
@@ -6756,29 +6835,29 @@ function commandFilename(ownExecutablePath, commandName) {
6756
6835
  return ownExecutablePath.toLowerCase().endsWith(".exe") ? `${commandName}.exe` : commandName;
6757
6836
  }
6758
6837
  function resolveOwnInstallDirs(paths, ownExecutablePath) {
6759
- const dirs = [import_node_path22.default.dirname(ownExecutablePath)];
6838
+ const dirs = [import_node_path23.default.dirname(ownExecutablePath)];
6760
6839
  const state = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
6761
6840
  if (state !== void 0) {
6762
- dirs.push(import_node_path22.default.dirname(state.targetPath));
6841
+ dirs.push(import_node_path23.default.dirname(state.targetPath));
6763
6842
  }
6764
6843
  return dirs;
6765
6844
  }
6766
6845
  var nodeLinkFs = { link: import_node_fs7.default.linkSync, copyFile: import_node_fs7.default.copyFileSync, chmod: import_node_fs7.default.chmodSync };
6767
6846
  function findPathShadow(params) {
6768
- const resolvedTargetDir = import_node_path22.default.resolve(params.targetDir);
6847
+ const resolvedTargetDir = import_node_path23.default.resolve(params.targetDir);
6769
6848
  for (const dir of params.pathDirs) {
6770
6849
  const found = params.findExecutableInDir(dir, params.targetFilename);
6771
6850
  if (found === void 0) {
6772
6851
  continue;
6773
6852
  }
6774
- return import_node_path22.default.resolve(dir) === resolvedTargetDir ? { status: "ok" } : { status: "shadowed", by: found };
6853
+ return import_node_path23.default.resolve(dir) === resolvedTargetDir ? { status: "ok" } : { status: "shadowed", by: found };
6775
6854
  }
6776
- return params.pathDirs.some((dir) => import_node_path22.default.resolve(dir) === resolvedTargetDir) ? { status: "ok" } : { status: "not-on-path" };
6855
+ return params.pathDirs.some((dir) => import_node_path23.default.resolve(dir) === resolvedTargetDir) ? { status: "ok" } : { status: "not-on-path" };
6777
6856
  }
6778
6857
 
6779
6858
  // src/doctorReport.ts
6780
6859
  var import_node_fs8 = __toESM(require("node:fs"), 1);
6781
- var import_node_path23 = __toESM(require("node:path"), 1);
6860
+ var import_node_path24 = __toESM(require("node:path"), 1);
6782
6861
  function refinePathShadow(status, ownExecutablePath, realpath) {
6783
6862
  if (status.status !== "shadowed") {
6784
6863
  return status;
@@ -6802,7 +6881,7 @@ function validateJson(schema, input) {
6802
6881
  return { ok: true, data: result.data };
6803
6882
  }
6804
6883
  function pushPathResolution(push, resolution) {
6805
- const ownDir = import_node_path23.default.dirname(resolution.ownExecutablePath);
6884
+ const ownDir = import_node_path24.default.dirname(resolution.ownExecutablePath);
6806
6885
  switch (resolution.agentShim.status) {
6807
6886
  case "ok":
6808
6887
  push("path-resolution", "pass", `\`agent-shim\` on PATH resolves to this running executable, ${resolution.ownExecutablePath}.`, "agent-shim");
@@ -6870,14 +6949,14 @@ function pushProvider(push, entry) {
6870
6949
  }
6871
6950
  function pushLegacyName(push, params) {
6872
6951
  const legacyVariables = Object.keys(params.env).filter((name) => name.startsWith(LEGACY_ENV_PREFIX) && params.env[name] !== void 0).sort();
6873
- if (legacyVariables.length === 0 && import_node_path23.default.basename(params.rootPath) !== LEGACY_HOME_DIRNAME) {
6952
+ if (legacyVariables.length === 0 && import_node_path24.default.basename(params.rootPath) !== LEGACY_HOME_DIRNAME) {
6874
6953
  push("legacy-name", "pass", "Nothing here still uses the former `claude-use` name.");
6875
6954
  return;
6876
6955
  }
6877
6956
  for (const name of legacyVariables) {
6878
6957
  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);
6879
6958
  }
6880
- if (import_node_path23.default.basename(params.rootPath) === LEGACY_HOME_DIRNAME) {
6959
+ if (import_node_path24.default.basename(params.rootPath) === LEGACY_HOME_DIRNAME) {
6881
6960
  push(
6882
6961
  "legacy-name",
6883
6962
  "warn",
@@ -7067,7 +7146,7 @@ function runDoctor(params) {
7067
7146
  "warn",
7068
7147
  `Headroom state names supervisor pid ${String(state.supervisorPid)}, which is not running; the next launch through headroom will start a replacement.`
7069
7148
  );
7070
- } else if (state.headroomPid === void 0 || state.port === void 0) {
7149
+ } else if (state.headroomPid === void 0 || state.socketPath === void 0) {
7071
7150
  push(
7072
7151
  "headroom",
7073
7152
  "warn",
@@ -7083,7 +7162,7 @@ function runDoctor(params) {
7083
7162
  push(
7084
7163
  "headroom",
7085
7164
  "pass",
7086
- `Headroom daemon is up on 127.0.0.1:${String(state.port)} (supervisor ${String(state.supervisorPid)}, daemon ${String(state.headroomPid)}).`
7165
+ `Headroom daemon is up on unix socket ${state.socketPath} (supervisor ${String(state.supervisorPid)}, daemon ${String(state.headroomPid)}).`
7087
7166
  );
7088
7167
  }
7089
7168
  if (state.lastError !== void 0 && supervisorAlive) {
@@ -7185,18 +7264,18 @@ function collectDoctorReport(params) {
7185
7264
  const { paths } = params;
7186
7265
  const identityNames = import_node_fs8.default.existsSync(paths.identitiesDir) ? import_node_fs8.default.readdirSync(paths.identitiesDir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && isIdentityDirectoryName(entry.name)).map((entry) => entry.name).sort() : [];
7187
7266
  const identities = identityNames.map((name) => {
7188
- const farmRoot = import_node_path23.default.join(paths.identitiesDir, name);
7189
- const identityPath = import_node_path23.default.join(farmRoot, "identity.json");
7267
+ const farmRoot = import_node_path24.default.join(paths.identitiesDir, name);
7268
+ const identityPath = import_node_path24.default.join(farmRoot, "identity.json");
7190
7269
  return { name, path: identityPath, raw: realFsPort.readFileUtf8(identityPath), farmRoot };
7191
7270
  });
7192
7271
  const profileNames = import_node_fs8.default.existsSync(paths.configProfilesDir) ? import_node_fs8.default.readdirSync(paths.configProfilesDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
7193
7272
  const configProfiles = profileNames.map((name) => {
7194
- const profilePath = import_node_path23.default.join(paths.configProfilesDir, `${name}.json`);
7273
+ const profilePath = import_node_path24.default.join(paths.configProfilesDir, `${name}.json`);
7195
7274
  return { name, path: profilePath, raw: realFsPort.readFileUtf8(profilePath) };
7196
7275
  });
7197
7276
  const providerNames = import_node_fs8.default.existsSync(paths.providersDir) ? import_node_fs8.default.readdirSync(paths.providersDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
7198
7277
  const providers = providerNames.map((name) => {
7199
- const providerPath = import_node_path23.default.join(paths.providersDir, `${name}.json`);
7278
+ const providerPath = import_node_path24.default.join(paths.providersDir, `${name}.json`);
7200
7279
  return { name, path: providerPath, raw: realFsPort.readFileUtf8(providerPath) };
7201
7280
  });
7202
7281
  const ownExecutablePath = realOwnExecutablePath();
@@ -7208,12 +7287,12 @@ function collectDoctorReport(params) {
7208
7287
  binaryDiscovery = { ok: false, message: error instanceof Error ? error.message : String(error) };
7209
7288
  }
7210
7289
  const shimState = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
7211
- const pathDirs = (params.env.PATH ?? "").split(import_node_path23.default.delimiter).filter((dir) => dir !== "");
7290
+ const pathDirs = (params.env.PATH ?? "").split(import_node_path24.default.delimiter).filter((dir) => dir !== "");
7212
7291
  const claudeShimShadow = shimState === void 0 ? void 0 : refinePathShadow(
7213
7292
  findPathShadow({
7214
7293
  pathDirs,
7215
- targetDir: import_node_path23.default.dirname(shimState.targetPath),
7216
- targetFilename: import_node_path23.default.basename(shimState.targetPath),
7294
+ targetDir: import_node_path24.default.dirname(shimState.targetPath),
7295
+ targetFilename: import_node_path24.default.basename(shimState.targetPath),
7217
7296
  findExecutableInDir
7218
7297
  }),
7219
7298
  shimState.targetPath,
@@ -7236,7 +7315,7 @@ function collectDoctorReport(params) {
7236
7315
  agentShim: refinePathShadow(
7237
7316
  findPathShadow({
7238
7317
  pathDirs,
7239
- targetDir: import_node_path23.default.dirname(ownExecutablePath),
7318
+ targetDir: import_node_path24.default.dirname(ownExecutablePath),
7240
7319
  targetFilename: commandFilename(ownExecutablePath, "agent-shim"),
7241
7320
  findExecutableInDir
7242
7321
  }),
@@ -7257,7 +7336,7 @@ function collectDoctorReport(params) {
7257
7336
 
7258
7337
  // src/launcher.ts
7259
7338
  var import_node_crypto9 = require("node:crypto");
7260
- var import_node_path25 = __toESM(require("node:path"), 1);
7339
+ var import_node_path26 = __toESM(require("node:path"), 1);
7261
7340
 
7262
7341
  // src/launcher/argv.ts
7263
7342
  var ConflictingIdentityError = class extends UsageError {
@@ -7509,7 +7588,7 @@ function buildCliOverride(params) {
7509
7588
  }
7510
7589
 
7511
7590
  // src/launcher/flags.ts
7512
- var import_node_path24 = __toESM(require("node:path"), 1);
7591
+ var import_node_path25 = __toESM(require("node:path"), 1);
7513
7592
 
7514
7593
  // src/headroom/headers.ts
7515
7594
  function mergeAnthropicCustomHeaders(existing, additions) {
@@ -7579,7 +7658,7 @@ function buildEnv(params) {
7579
7658
  const parentCustomHeaders = params.baseEnv.ANTHROPIC_CUSTOM_HEADERS;
7580
7659
  let providerCustomHeaders;
7581
7660
  if (!params.configDirEscapeHatch && params.resolvedIdentityName !== void 0) {
7582
- env.CLAUDE_CONFIG_DIR = import_node_path24.default.join(params.identitiesDir, params.resolvedIdentityName);
7661
+ env.CLAUDE_CONFIG_DIR = import_node_path25.default.join(params.identitiesDir, params.resolvedIdentityName);
7583
7662
  }
7584
7663
  if (params.provider !== void 0) {
7585
7664
  const providerEnv = params.provider.definition.env ?? {};
@@ -7600,9 +7679,6 @@ function buildEnv(params) {
7600
7679
  env[variable] = value;
7601
7680
  }
7602
7681
  }
7603
- if (params.headroom !== void 0) {
7604
- env.HEADROOM_PROXY_URL = `http://127.0.0.1:${String(params.headroom.port)}`;
7605
- }
7606
7682
  if (params.frontdoor !== void 0) {
7607
7683
  env.ANTHROPIC_CUSTOM_HEADERS = mergeAnthropicCustomHeaders(
7608
7684
  [
@@ -7743,7 +7819,7 @@ function prepareLaunch(params) {
7743
7819
  identityDefaultConfigProfile: loadedIdentity?.config.defaultConfigProfile,
7744
7820
  globalDefaultConfigProfile: params.globalDefaultConfigProfile
7745
7821
  });
7746
- if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(import_node_path25.default.join(paths.configProfilesDir, `${configProfileDecision.name}.json`)) === void 0) {
7822
+ if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(import_node_path26.default.join(paths.configProfilesDir, `${configProfileDecision.name}.json`)) === void 0) {
7747
7823
  log.error(
7748
7824
  `agent-shim: no configuration profile named "${configProfileDecision.name}" (selected via ${configProfileDecision.source}). Run \`agent-shim profile add ${configProfileDecision.name}\` first.`
7749
7825
  );
@@ -7879,7 +7955,7 @@ function prepareLaunch(params) {
7879
7955
  if (resolvedFlags.headroom && headroomPort !== void 0) {
7880
7956
  headroom = headroomPort.ensure();
7881
7957
  const via = resolvedProvider === void 0 ? `OAuth via the door's CONNECT surface on 127.0.0.1:${String(frontDoor?.connectPort ?? 0)}` : `provider ${resolvedProvider.name}`;
7882
- log.info(`agent-shim: routing through the front door on 127.0.0.1:${String(frontDoor?.port ?? 0)} with headroom on 127.0.0.1:${String(headroom.port)} (${via}, project ${headroom.projectId})`);
7958
+ 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})`);
7883
7959
  } else if (resolvedFlags.headroom) {
7884
7960
  log.error("agent-shim: headroom routing was requested but this launcher has no headroom port wired; refusing to launch without it.");
7885
7961
  proc.exit(1);
@@ -7919,7 +7995,7 @@ var import_node_crypto11 = require("node:crypto");
7919
7995
  // src/realCredentialCache.ts
7920
7996
  var import_node_child_process2 = require("node:child_process");
7921
7997
  var import_node_fs9 = __toESM(require("node:fs"), 1);
7922
- var import_node_path26 = __toESM(require("node:path"), 1);
7998
+ var import_node_path27 = __toESM(require("node:path"), 1);
7923
7999
  var KEYCHAIN_CACHE_SERVICE = "agent-shim-credential-cache";
7924
8000
  var CACHE_DIR_MODE = 448;
7925
8001
  var CACHE_FILE_MODE = 384;
@@ -7946,8 +8022,8 @@ function security(args, stdin) {
7946
8022
  return { status: result.status, stdout: result.stdout };
7947
8023
  }
7948
8024
  function createRealCredentialCache(root) {
7949
- const dir = import_node_path26.default.join(root, "credential-cache");
7950
- const filePath = (owner) => import_node_path26.default.join(dir, cacheFileNameFor(owner));
8025
+ const dir = import_node_path27.default.join(root, "credential-cache");
8026
+ const filePath = (owner) => import_node_path27.default.join(dir, cacheFileNameFor(owner));
7951
8027
  return {
7952
8028
  read(store, owner) {
7953
8029
  if (store === "file") {
@@ -8063,11 +8139,11 @@ function probeFrontDoorSync(port, caPem) {
8063
8139
 
8064
8140
  // src/frontdoor/trust.ts
8065
8141
  var import_node_crypto10 = require("node:crypto");
8066
- var import_node_path27 = __toESM(require("node:path"), 1);
8142
+ var import_node_path28 = __toESM(require("node:path"), 1);
8067
8143
  var BUNDLE_NAME_HEX_DIGITS = 16;
8068
8144
  function resolveTrustBundle(params) {
8069
- const { caCertFile, bundlesDir, inherited, fs: fs12 } = params;
8070
- if (inherited === void 0 || inherited === "" || import_node_path27.default.resolve(inherited) === import_node_path27.default.resolve(caCertFile)) {
8145
+ const { caCertFile, bundlesDir, variable, inherited, fs: fs12 } = params;
8146
+ if (inherited === void 0 || inherited === "" || import_node_path28.default.resolve(inherited) === import_node_path28.default.resolve(caCertFile)) {
8071
8147
  return { path: caCertFile };
8072
8148
  }
8073
8149
  const caPem = fs12.readFileUtf8(caCertFile);
@@ -8077,7 +8153,7 @@ function resolveTrustBundle(params) {
8077
8153
  } catch (error) {
8078
8154
  return {
8079
8155
  path: caCertFile,
8080
- warning: `agent-shim: NODE_EXTRA_CA_CERTS names ${inherited}, which could not be read (${error instanceof Error ? error.message : String(error)}); the child trusts agent-shim's front-door CA on top of the system store, and nothing from that file`
8156
+ warning: `agent-shim: ${variable} names ${inherited}, which could not be read (${error instanceof Error ? error.message : String(error)}); the child trusts agent-shim's front-door CA on top of the system store, and nothing from that file`
8081
8157
  };
8082
8158
  }
8083
8159
  if (inheritedPem.includes(caPem.trim())) {
@@ -8085,7 +8161,7 @@ function resolveTrustBundle(params) {
8085
8161
  }
8086
8162
  const combined = `${inheritedPem.trimEnd()}
8087
8163
  ${caPem}`;
8088
- const bundle = import_node_path27.default.join(bundlesDir, `${(0, import_node_crypto10.createHash)("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
8164
+ const bundle = import_node_path28.default.join(bundlesDir, `${(0, import_node_crypto10.createHash)("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
8089
8165
  if (!fs12.exists(bundle)) {
8090
8166
  fs12.mkdirp(bundlesDir);
8091
8167
  fs12.writeFileAtomic(bundle, combined);
@@ -8123,7 +8199,7 @@ function realFrontDoorPort(paths, spawnDaemon) {
8123
8199
  verifyListener: (port) => probeFrontDoorSync(port, import_node_fs10.default.readFileSync(paths.frontdoorCaCertFile, "utf8"))
8124
8200
  }
8125
8201
  });
8126
- const trust = resolveTrustBundle({ caCertFile: paths.frontdoorCaCertFile, bundlesDir: paths.frontdoorCaBundlesDir, inherited: inheritedExtraCaCerts, fs: realTrustBundleFs });
8202
+ const trust = resolveTrustBundle({ caCertFile: paths.frontdoorCaCertFile, bundlesDir: paths.frontdoorCaBundlesDir, variable: "NODE_EXTRA_CA_CERTS", inherited: inheritedExtraCaCerts, fs: realTrustBundleFs });
8127
8203
  return {
8128
8204
  port: up.port,
8129
8205
  connectPort: up.connectPort,