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.mjs CHANGED
@@ -247,7 +247,7 @@ var HeadroomGlobalConfigSchema = HeadroomGlobalConfigObjectSchema.superRefine((c
247
247
  context.addIssue({ code: "custom", path: ["readMaturation"], message: "readMaturation needs rolloutChannel beta or dev" });
248
248
  }
249
249
  });
250
- var HEADROOM_DEFAULT_SOURCE = "headroom-ai[proxy] @ git+https://github.com/ExaDev/headroom@ecd1c351fcfed97499721e86852e148436ff2ee6";
250
+ var HEADROOM_DEFAULT_SOURCE = "headroom-ai[proxy] @ git+https://github.com/ExaDev/headroom@53525f479f2f48e8ef6b08cf729601feab7d2382";
251
251
  var HEADROOM_DEFAULT_IDLE_SHUTDOWN_MINUTES = 15;
252
252
  var FrontDoorGlobalConfigSchema = z.strictObject({
253
253
  /** How long the front door may sit with no registered sessions before it closes and exits. Defaults to FRONTDOOR_DEFAULT_IDLE_SHUTDOWN_MINUTES. */
@@ -2484,7 +2484,7 @@ function providerBaseUrl(port, provider) {
2484
2484
  // src/frontdoor/state.ts
2485
2485
  import path7 from "node:path";
2486
2486
  import { z as z3 } from "zod";
2487
- var FRONT_DOOR_PROTOCOL = 1;
2487
+ var FRONT_DOOR_PROTOCOL = 2;
2488
2488
  var FrontDoorSessionSchema = z3.strictObject({ pid: z3.number().int().positive(), startedAt: z3.number(), token: z3.string().min(1) });
2489
2489
  var FrontDoorStateSchema = z3.strictObject({
2490
2490
  /**
@@ -2709,8 +2709,8 @@ function parseConnectTarget(authority) {
2709
2709
  function isInterceptedHost(host, interceptHosts) {
2710
2710
  return interceptHosts.includes(host);
2711
2711
  }
2712
- function servedByPipeline(path28) {
2713
- return path28?.startsWith(ROUTED_PATH_PREFIX) === true;
2712
+ function servedByPipeline(path29) {
2713
+ return path29?.startsWith(ROUTED_PATH_PREFIX) === true;
2714
2714
  }
2715
2715
  var HOP_BY_HOP_HEADERS = /* @__PURE__ */ new Set([
2716
2716
  "connection",
@@ -3276,17 +3276,16 @@ import { createHash as createHash2 } from "node:crypto";
3276
3276
  import path8 from "node:path";
3277
3277
  import { z as z4 } from "zod";
3278
3278
  var HEADROOM_ANTHROPIC_UPSTREAM = "https://api.anthropic.com";
3279
+ var HEADROOM_STATE_SCHEMA_VERSION = 2;
3279
3280
  var HeadroomStateSchema = z4.strictObject({
3280
3281
  /** The supervisor process owning the daemon. Alive means someone is keeping headroom running. */
3281
3282
  supervisorPid: z4.number().int().positive().optional(),
3282
3283
  /** The headroom proxy process itself. Absent while the supervisor is between restarts. */
3283
3284
  headroomPid: z4.number().int().positive().optional(),
3284
- /** 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. */
3285
- port: z4.number().int().positive().optional(),
3286
3285
  /**
3287
- * 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.
3286
+ * 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.
3288
3287
  */
3289
- lastPort: z4.number().int().positive().optional(),
3288
+ socketPath: z4.string().min(1).optional(),
3290
3289
  /** The `headroom --version` output of the running install. */
3291
3290
  version: z4.string().optional(),
3292
3291
  /** Hash of the allowlist the running proxy was started with, so a provider-file change is detected as drift. */
@@ -3793,10 +3792,10 @@ function ensureHeadroom(params) {
3793
3792
  for (; ; ) {
3794
3793
  const state = readHeadroomState(ports.fs, paths.headroomStateFile);
3795
3794
  if (state?.supervisorPid !== void 0 && ports.isRunning(state.supervisorPid)) {
3796
- const daemonUp = state.port !== void 0 && state.headroomPid !== void 0 && ports.isRunning(state.headroomPid);
3797
- if (daemonUp && state.port !== void 0) {
3795
+ const daemonUp = state.socketPath !== void 0 && state.headroomPid !== void 0 && ports.isRunning(state.headroomPid);
3796
+ if (daemonUp && state.socketPath !== void 0) {
3798
3797
  writeSession(ports.fs, paths.headroomSessionsDir, { pid: params.launcherPid, startedAt: ports.now(), supervisorPid: state.supervisorPid });
3799
- return { port: state.port };
3798
+ return { socketPath: state.socketPath };
3800
3799
  }
3801
3800
  if (state.lastError !== void 0) {
3802
3801
  throw new HeadroomStartError(
@@ -3860,6 +3859,71 @@ function hashSettings(settings) {
3860
3859
  return createHash3("sha256").update(JSON.stringify([...settingsArgs(settings), JSON.stringify(settingsEnv(settings))])).digest("hex");
3861
3860
  }
3862
3861
 
3862
+ // src/headroom/socket.ts
3863
+ import path11 from "node:path";
3864
+ var GROUP_OR_OTHER_BITS = 63;
3865
+ var OCTAL_RADIX = 8;
3866
+ var MODE_DIGITS = 4;
3867
+ var HEADROOM_SOCKET_SUFFIX = ".sock";
3868
+ var HEADROOM_SOCKET_NAME = /^(\d+)\.sock$/;
3869
+ var UNIX_SOCKET_PATH_MAX_BYTES = 103;
3870
+ var PLATFORMS_WITHOUT_UNIX_SOCKETS = ["win32"];
3871
+ function headroomSocketPath(paths, supervisorPid) {
3872
+ return path11.join(paths.headroomSocketDir, `${String(supervisorPid)}${HEADROOM_SOCKET_SUFFIX}`);
3873
+ }
3874
+ function platformRefusal(platform) {
3875
+ 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;
3876
+ }
3877
+ function ownerOnlyRefusal(label, target, stat, expected, uid) {
3878
+ if (stat === void 0) {
3879
+ return `the headroom ${label} ${target} does not exist`;
3880
+ }
3881
+ if (stat.kind === "symlink") {
3882
+ return `the headroom ${label} ${target} is a symlink; it must be the real ${expected === "dir" ? "directory" : "socket"}`;
3883
+ }
3884
+ if (stat.kind !== expected) {
3885
+ return `the headroom ${label} ${target} is not a ${expected === "dir" ? "directory" : "socket"}`;
3886
+ }
3887
+ if (stat.uid !== uid) {
3888
+ return `the headroom ${label} ${target} is owned by uid ${String(stat.uid)}, not by this user (uid ${String(uid)})`;
3889
+ }
3890
+ if ((stat.mode & GROUP_OR_OTHER_BITS) !== 0) {
3891
+ 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`;
3892
+ }
3893
+ return void 0;
3894
+ }
3895
+ function prepareHeadroomSocket(fs12, ports, paths, supervisorPid) {
3896
+ const unsupported = platformRefusal(ports.platform);
3897
+ if (unsupported !== void 0) {
3898
+ return { refused: unsupported };
3899
+ }
3900
+ const socketPath = headroomSocketPath(paths, supervisorPid);
3901
+ const length = Buffer.byteLength(socketPath, "utf8");
3902
+ if (length > UNIX_SOCKET_PATH_MAX_BYTES) {
3903
+ return {
3904
+ 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`
3905
+ };
3906
+ }
3907
+ if (ports.lstat(paths.headroomSocketDir)?.kind === "symlink") {
3908
+ return { refused: `the headroom socket directory ${paths.headroomSocketDir} is a symlink; it must be the real directory` };
3909
+ }
3910
+ fs12.mkdirPrivate(paths.headroomSocketDir);
3911
+ const refusal = ownerOnlyRefusal("socket directory", paths.headroomSocketDir, ports.lstat(paths.headroomSocketDir), "dir", ports.currentUid());
3912
+ return refusal === void 0 ? { socketPath } : { refused: refusal };
3913
+ }
3914
+ function pruneStaleHeadroomSockets(fs12, paths, isRunning) {
3915
+ const removed = [];
3916
+ for (const name of fs12.readdir(paths.headroomSocketDir)) {
3917
+ const pid = HEADROOM_SOCKET_NAME.exec(name)?.[1];
3918
+ if (pid === void 0 || isRunning(Number.parseInt(pid, 10))) {
3919
+ continue;
3920
+ }
3921
+ fs12.removeRecursive(path11.join(paths.headroomSocketDir, name));
3922
+ removed.push(name);
3923
+ }
3924
+ return removed;
3925
+ }
3926
+
3863
3927
  // src/headroom/source.ts
3864
3928
  import { z as z6 } from "zod";
3865
3929
  var GIT_SPEC_RE = /git\+[^@\s]+(?:@([^\s#]+))?/;
@@ -3955,8 +4019,6 @@ async function runSupervisor(initialConfig, ports, options = {}) {
3955
4019
  return 0;
3956
4020
  }
3957
4021
  let installedSource = previousState?.installedSource;
3958
- let lastPort = previousState?.lastPort;
3959
- const sticky = () => lastPort === void 0 ? {} : { lastPort };
3960
4022
  const ownsState = () => {
3961
4023
  const owner = readHeadroomState(fs12, paths.headroomStateFile)?.supervisorPid;
3962
4024
  return owner === void 0 || owner === ports.ownPid || !ports.isRunning(owner);
@@ -3969,7 +4031,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
3969
4031
  return true;
3970
4032
  };
3971
4033
  const fail = (message) => {
3972
- if (writeOwnState({ lastError: message, ...sticky() })) {
4034
+ if (writeOwnState({ lastError: message })) {
3973
4035
  fs12.removeRecursive(paths.headroomLockFile);
3974
4036
  }
3975
4037
  ports.log(`agent-shim headroom supervisor: ${message}`);
@@ -3992,11 +4054,17 @@ async function runSupervisor(initialConfig, ports, options = {}) {
3992
4054
  installedSource = config.source;
3993
4055
  return true;
3994
4056
  };
4057
+ const socket = prepareHeadroomSocket(fs12, ports.socketTrust, paths, ports.ownPid);
4058
+ if (socket.refused !== void 0) {
4059
+ return fail(socket.refused);
4060
+ }
4061
+ const { socketPath } = socket;
4062
+ pruneStaleHeadroomSockets(fs12, paths, ports.isRunning);
3995
4063
  if (!ensureInstalled()) {
3996
4064
  return fail(`could not install headroom from ${config.source}: install failed (is uv installed and on PATH?)`);
3997
4065
  }
3998
4066
  const version = ports.headroomVersion() ?? "unknown";
3999
- writeOwnState({ supervisorPid: ports.ownPid, version, installedSource, ...sticky() });
4067
+ writeOwnState({ supervisorPid: ports.ownPid, version, installedSource });
4000
4068
  ports.log(`agent-shim headroom supervisor ${String(ports.ownPid)}: managing headroom on allowlist [${allowlistOf(ports).join(", ")}]`);
4001
4069
  const orphanPid = previousState?.headroomPid;
4002
4070
  if (orphanPid !== void 0 && ports.isRunning(orphanPid)) {
@@ -4022,7 +4090,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
4022
4090
  pruneDeadSessions(fs12, paths.headroomSessionsDir, ports.isRunning);
4023
4091
  const ownsNow = ownsState();
4024
4092
  if (!ownsNow && !superseded) {
4025
- ports.log("agent-shim headroom supervisor: another supervisor now owns state.json; serving this daemon's own sessions until they end");
4093
+ ports.log("agent-shim headroom supervisor: another supervisor now owns the state file; serving this daemon's own sessions until they end");
4026
4094
  }
4027
4095
  superseded = !ownsNow;
4028
4096
  const crashed = headroomPid !== void 0 && !ports.isRunning(headroomPid);
@@ -4035,8 +4103,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
4035
4103
  writeOwnState({
4036
4104
  supervisorPid: ports.ownPid,
4037
4105
  version,
4038
- installedSource,
4039
- ...sticky()
4106
+ installedSource
4040
4107
  });
4041
4108
  }
4042
4109
  if (consecutiveFailures >= HEADROOM_START_RETRY_BUDGET) {
@@ -4045,41 +4112,32 @@ async function runSupervisor(initialConfig, ports, options = {}) {
4045
4112
  if (installedSource !== config.source && !ensureInstalled()) {
4046
4113
  return fail(`could not install headroom from ${config.source}: install failed (is uv installed and on PATH?)`);
4047
4114
  }
4048
- const previousSticky = lastPort;
4049
- const port = lastPort !== void 0 && await ports.isPortFree(lastPort) ? lastPort : await ports.freePort();
4050
- const pid = ports.spawnHeadroom(port, allowlist, config.settings);
4051
- const ready = await waitUntilReady(ports, port);
4115
+ const pid = ports.spawnHeadroom(socketPath, allowlist, config.settings);
4116
+ const ready = await waitUntilReady(ports, socketPath);
4052
4117
  if (ready) {
4053
4118
  consecutiveFailures = 0;
4054
4119
  headroomPid = pid;
4055
4120
  runningHash = allowlistHash;
4056
4121
  runningSettingsHash = settingsHash;
4057
- lastPort = port;
4058
- if (previousSticky !== void 0 && port !== previousSticky) {
4059
- ports.log(
4060
- `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)`
4061
- );
4062
- }
4063
4122
  const recorded = writeOwnState({
4064
4123
  supervisorPid: ports.ownPid,
4065
4124
  headroomPid: pid,
4066
- port,
4125
+ socketPath,
4067
4126
  version,
4068
4127
  allowlistHash,
4069
4128
  settingsHash,
4070
- installedSource: config.source,
4071
- ...sticky()
4129
+ installedSource: config.source
4072
4130
  });
4073
4131
  if (recorded) {
4074
4132
  fs12.removeRecursive(paths.headroomLockFile);
4075
4133
  }
4076
4134
  idleSince = void 0;
4077
- ports.log(`agent-shim headroom supervisor: headroom pid ${String(pid)} ready on 127.0.0.1:${String(port)}`);
4135
+ ports.log(`agent-shim headroom supervisor: headroom pid ${String(pid)} ready on unix socket ${socketPath}`);
4078
4136
  } else {
4079
4137
  ports.stopProcess(pid);
4080
4138
  consecutiveFailures += 1;
4081
4139
  ports.log(
4082
- `agent-shim headroom supervisor: headroom did not become ready on port ${String(port)} (attempt ${String(consecutiveFailures)} of ${String(HEADROOM_START_RETRY_BUDGET)})`
4140
+ `agent-shim headroom supervisor: headroom did not become ready on unix socket ${socketPath} (attempt ${String(consecutiveFailures)} of ${String(HEADROOM_START_RETRY_BUDGET)})`
4083
4141
  );
4084
4142
  await ports.sleep(backoffForAttempt(consecutiveFailures));
4085
4143
  continue;
@@ -4104,10 +4162,7 @@ async function runSupervisor(initialConfig, ports, options = {}) {
4104
4162
  `agent-shim headroom supervisor: no sessions for ${String(config.idleShutdownMinutes)} minute(s); stopping headroom and exiting`
4105
4163
  );
4106
4164
  ports.stopProcess(headroomPid);
4107
- writeOwnState({
4108
- version,
4109
- ...sticky()
4110
- });
4165
+ writeOwnState({ version });
4111
4166
  return 0;
4112
4167
  }
4113
4168
  } else {
@@ -4124,10 +4179,10 @@ function currentHeadroomAllowlist(fs12, paths) {
4124
4179
  function allowlistOf(ports) {
4125
4180
  return currentHeadroomAllowlist(ports.fs, ports.paths);
4126
4181
  }
4127
- async function waitUntilReady(ports, port) {
4182
+ async function waitUntilReady(ports, socketPath) {
4128
4183
  const deadline = ports.now() + HEADROOM_READY_TIMEOUT_MS;
4129
4184
  for (; ; ) {
4130
- if (await ports.ready(port)) {
4185
+ if (await ports.ready(socketPath)) {
4131
4186
  return true;
4132
4187
  }
4133
4188
  if (ports.now() >= deadline) {
@@ -4187,14 +4242,14 @@ function evaluateAmbientCredentialGuard(params) {
4187
4242
  // src/paths.ts
4188
4243
  import fs3 from "node:fs";
4189
4244
  import os from "node:os";
4190
- import path11 from "node:path";
4245
+ import path12 from "node:path";
4191
4246
  function resolveAgentShimHome(env = process.env, home = os.homedir(), isDirectory = isExistingDirectory) {
4192
4247
  const fromEnv = env.AGENT_SHIM_HOME;
4193
4248
  if (fromEnv !== void 0 && fromEnv !== "") {
4194
4249
  return fromEnv;
4195
4250
  }
4196
- const current = path11.join(home, HOME_DIRNAME);
4197
- const legacy = path11.join(home, LEGACY_HOME_DIRNAME);
4251
+ const current = path12.join(home, HOME_DIRNAME);
4252
+ const legacy = path12.join(home, LEGACY_HOME_DIRNAME);
4198
4253
  return !isDirectory(current) && isDirectory(legacy) ? legacy : current;
4199
4254
  }
4200
4255
  function isExistingDirectory(candidate) {
@@ -4205,38 +4260,39 @@ function resolveClaudeHome() {
4205
4260
  if (fromEnv !== void 0 && fromEnv !== "") {
4206
4261
  return fromEnv;
4207
4262
  }
4208
- return path11.join(os.homedir(), ".claude");
4263
+ return path12.join(os.homedir(), ".claude");
4209
4264
  }
4210
4265
  function buildLayoutPaths(root) {
4211
4266
  return {
4212
4267
  root,
4213
- identitiesDir: path11.join(root, "identities"),
4214
- configProfilesDir: path11.join(root, "config-profiles"),
4215
- providersDir: path11.join(root, "providers"),
4216
- directoryRulesFile: path11.join(root, "directory-rules.json"),
4217
- activeIdentityFile: path11.join(root, "active-identity"),
4218
- globalConfigFile: path11.join(root, "config.json"),
4219
- categoriesLocalFile: path11.join(root, "categories.local.json"),
4220
- claudeShimFile: path11.join(root, "claude-shim.json"),
4221
- headroomDir: path11.join(root, "headroom"),
4222
- headroomStateFile: path11.join(root, "headroom", "state.json"),
4223
- headroomLockFile: path11.join(root, "headroom", "start.lock"),
4224
- headroomSessionsDir: path11.join(root, "headroom", "sessions"),
4225
- logsDir: path11.join(root, "logs"),
4226
- headroomLogPath: path11.join(root, "logs", "headroom.log"),
4227
- frontdoorDir: path11.join(root, "frontdoor"),
4228
- frontdoorCaDir: path11.join(root, "frontdoor", "ca"),
4229
- frontdoorCaCertFile: path11.join(root, "frontdoor", "ca", "ca.pem"),
4230
- frontdoorCaKeyFile: path11.join(root, "frontdoor", "ca", "ca.key"),
4231
- frontdoorCaBundlesDir: path11.join(root, "frontdoor", "ca", "bundles"),
4232
- frontdoorStateFile: path11.join(root, "frontdoor", "state.json"),
4233
- frontdoorLockFile: path11.join(root, "frontdoor", "start.lock"),
4234
- frontdoorSessionsDir: path11.join(root, "frontdoor", "sessions"),
4235
- frontdoorLogPath: path11.join(root, "logs", "frontdoor.log"),
4236
- usageDir: path11.join(root, "usage"),
4237
- usageLogDir: path11.join(root, "usage", "log"),
4238
- usageSnapshotsDir: path11.join(root, "usage", "snapshots"),
4239
- usagePicksFile: path11.join(root, "usage", "picks.json")
4268
+ identitiesDir: path12.join(root, "identities"),
4269
+ configProfilesDir: path12.join(root, "config-profiles"),
4270
+ providersDir: path12.join(root, "providers"),
4271
+ directoryRulesFile: path12.join(root, "directory-rules.json"),
4272
+ activeIdentityFile: path12.join(root, "active-identity"),
4273
+ globalConfigFile: path12.join(root, "config.json"),
4274
+ categoriesLocalFile: path12.join(root, "categories.local.json"),
4275
+ claudeShimFile: path12.join(root, "claude-shim.json"),
4276
+ headroomDir: path12.join(root, "headroom"),
4277
+ headroomStateFile: path12.join(root, "headroom", `state.v${String(HEADROOM_STATE_SCHEMA_VERSION)}.json`),
4278
+ headroomSocketDir: path12.join(root, "headroom", "run"),
4279
+ headroomLockFile: path12.join(root, "headroom", "start.lock"),
4280
+ headroomSessionsDir: path12.join(root, "headroom", "sessions"),
4281
+ logsDir: path12.join(root, "logs"),
4282
+ headroomLogPath: path12.join(root, "logs", "headroom.log"),
4283
+ frontdoorDir: path12.join(root, "frontdoor"),
4284
+ frontdoorCaDir: path12.join(root, "frontdoor", "ca"),
4285
+ frontdoorCaCertFile: path12.join(root, "frontdoor", "ca", "ca.pem"),
4286
+ frontdoorCaKeyFile: path12.join(root, "frontdoor", "ca", "ca.key"),
4287
+ frontdoorCaBundlesDir: path12.join(root, "frontdoor", "ca", "bundles"),
4288
+ frontdoorStateFile: path12.join(root, "frontdoor", "state.json"),
4289
+ frontdoorLockFile: path12.join(root, "frontdoor", "start.lock"),
4290
+ frontdoorSessionsDir: path12.join(root, "frontdoor", "sessions"),
4291
+ frontdoorLogPath: path12.join(root, "logs", "frontdoor.log"),
4292
+ usageDir: path12.join(root, "usage"),
4293
+ usageLogDir: path12.join(root, "usage", "log"),
4294
+ usageSnapshotsDir: path12.join(root, "usage", "snapshots"),
4295
+ usagePicksFile: path12.join(root, "usage", "picks.json")
4240
4296
  };
4241
4297
  }
4242
4298
  function resolveLayoutPaths() {
@@ -4245,10 +4301,10 @@ function resolveLayoutPaths() {
4245
4301
 
4246
4302
  // src/identityStore.ts
4247
4303
  import fs5 from "node:fs";
4248
- import path14 from "node:path";
4304
+ import path15 from "node:path";
4249
4305
 
4250
4306
  // src/launcher/identity.ts
4251
- import path12 from "node:path";
4307
+ import path13 from "node:path";
4252
4308
  function poolNameOf(selector) {
4253
4309
  return selector.startsWith(POOL_SELECTOR_PREFIX) ? selector.slice(POOL_SELECTOR_PREFIX.length) : void 0;
4254
4310
  }
@@ -4297,12 +4353,12 @@ function decideConfigProfile(params) {
4297
4353
  return { source: "none" };
4298
4354
  }
4299
4355
  function loadIdentity(identitiesDir, name, fs12) {
4300
- return loadConfigFile(path12.join(identitiesDir, name, "identity.json"), IdentitySchema, fs12.readConfigFile);
4356
+ return loadConfigFile(path13.join(identitiesDir, name, "identity.json"), IdentitySchema, fs12.readConfigFile);
4301
4357
  }
4302
4358
 
4303
4359
  // src/configProfilesStore.ts
4304
4360
  import fs4 from "node:fs";
4305
- import path13 from "node:path";
4361
+ import path14 from "node:path";
4306
4362
  var ProfileNotFoundError = class extends CliError {
4307
4363
  constructor(profileName) {
4308
4364
  super(`No configuration profile named "${profileName}". Run \`agent-shim profile add ${profileName}\` first.`);
@@ -4328,7 +4384,7 @@ var InvalidCategoryNameError = class extends CliError {
4328
4384
  categoryName;
4329
4385
  };
4330
4386
  function profileJsonPath(paths, name) {
4331
- return path13.join(paths.configProfilesDir, `${name}.json`);
4387
+ return path14.join(paths.configProfilesDir, `${name}.json`);
4332
4388
  }
4333
4389
  function profileExists(paths, name) {
4334
4390
  return fs4.existsSync(profileJsonPath(paths, name));
@@ -4516,7 +4572,7 @@ var InvalidIdentityNameError = class extends CliError {
4516
4572
  attemptedName;
4517
4573
  };
4518
4574
  function identityJsonPath(paths, name) {
4519
- return path14.join(paths.identitiesDir, name, "identity.json");
4575
+ return path15.join(paths.identitiesDir, name, "identity.json");
4520
4576
  }
4521
4577
  function identityExists(paths, name) {
4522
4578
  return fs5.existsSync(identityJsonPath(paths, name));
@@ -4617,7 +4673,7 @@ function setIdentityCredential(paths, identityName, change) {
4617
4673
  });
4618
4674
  }
4619
4675
  function belongsToIdentity(entry, name) {
4620
- return entry === name || entry === path14.basename(identityLockPath("", name)) || entry.startsWith(`.${name}.scratch.`) || entry.startsWith(`.${name}.previous.`);
4676
+ return entry === name || entry === path15.basename(identityLockPath("", name)) || entry.startsWith(`.${name}.scratch.`) || entry.startsWith(`.${name}.previous.`);
4621
4677
  }
4622
4678
  function removeIdentity(paths, name) {
4623
4679
  if (!identityExists(paths, name)) {
@@ -4625,7 +4681,7 @@ function removeIdentity(paths, name) {
4625
4681
  }
4626
4682
  for (const entry of fs5.readdirSync(paths.identitiesDir)) {
4627
4683
  if (belongsToIdentity(entry, name)) {
4628
- fs5.rmSync(path14.join(paths.identitiesDir, entry), { recursive: true, force: true });
4684
+ fs5.rmSync(path15.join(paths.identitiesDir, entry), { recursive: true, force: true });
4629
4685
  }
4630
4686
  }
4631
4687
  if (readActiveIdentity(paths) === name) {
@@ -4635,7 +4691,7 @@ function removeIdentity(paths, name) {
4635
4691
 
4636
4692
  // src/providersStore.ts
4637
4693
  import fs6 from "node:fs";
4638
- import path15 from "node:path";
4694
+ import path16 from "node:path";
4639
4695
 
4640
4696
  // src/credentialCache.ts
4641
4697
  import { z as z7 } from "zod";
@@ -4672,7 +4728,7 @@ var CREDENTIAL_COMMAND_TIMEOUT_MS = 1e4;
4672
4728
  var CREDENTIAL_INTERACTIVE_TIMEOUT_MS = 12e4;
4673
4729
  var GROUP_OTHER_PERMISSION_BITS = 63;
4674
4730
  var PERMISSION_BITS = 511;
4675
- var OCTAL_RADIX = 8;
4731
+ var OCTAL_RADIX2 = 8;
4676
4732
  function commandArgv(source) {
4677
4733
  if ("command" in source) {
4678
4734
  return source.command;
@@ -4765,7 +4821,7 @@ function trySource(source, params) {
4765
4821
  }
4766
4822
  if (read.mode !== void 0 && (read.mode & GROUP_OTHER_PERMISSION_BITS) !== 0) {
4767
4823
  return none(
4768
- `is readable or writable by group or others (mode ${(read.mode & PERMISSION_BITS).toString(OCTAL_RADIX)}); run \`chmod 600 ${source.file}\``,
4824
+ `is readable or writable by group or others (mode ${(read.mode & PERMISSION_BITS).toString(OCTAL_RADIX2)}); run \`chmod 600 ${source.file}\``,
4769
4825
  true
4770
4826
  );
4771
4827
  }
@@ -4861,7 +4917,7 @@ var InvalidProviderNameError = class extends CliError {
4861
4917
  };
4862
4918
  var PROVIDER_NAME_RE = /^[A-Za-z0-9][A-Za-z0-9._@-]*$/;
4863
4919
  function providerJsonPath(paths, name) {
4864
- return path15.join(paths.providersDir, `${name}.json`);
4920
+ return path16.join(paths.providersDir, `${name}.json`);
4865
4921
  }
4866
4922
  function providerExists(paths, name) {
4867
4923
  return fs6.existsSync(providerJsonPath(paths, name));
@@ -4937,7 +4993,7 @@ function readProvider(paths, name) {
4937
4993
  return parseProviderFile(filePath, raw);
4938
4994
  }
4939
4995
  function loadProvider(providersDir, name, port) {
4940
- const filePath = path15.join(providersDir, `${name}.json`);
4996
+ const filePath = path16.join(providersDir, `${name}.json`);
4941
4997
  const raw = port.readConfigFile(filePath);
4942
4998
  return raw === void 0 ? void 0 : parseProviderFile(filePath, raw);
4943
4999
  }
@@ -5192,21 +5248,21 @@ function removeDirectoryRule(paths, rulePath) {
5192
5248
  import os4 from "node:os";
5193
5249
 
5194
5250
  // src/launcher/cascade.ts
5195
- import path17 from "node:path";
5251
+ import path18 from "node:path";
5196
5252
 
5197
5253
  // src/pathNorm.ts
5198
- import path16 from "node:path";
5254
+ import path17 from "node:path";
5199
5255
  function expandTilde(value, home) {
5200
5256
  if (value === "~") {
5201
5257
  return home;
5202
5258
  }
5203
5259
  if (value.startsWith("~/")) {
5204
- return path16.join(home, value.slice(2));
5260
+ return path17.join(home, value.slice(2));
5205
5261
  }
5206
5262
  return value;
5207
5263
  }
5208
5264
  function normaliseRulePath(rulePath, home) {
5209
- return path16.resolve(expandTilde(rulePath, home));
5265
+ return path17.resolve(expandTilde(rulePath, home));
5210
5266
  }
5211
5267
 
5212
5268
  // src/launcher/cascade.ts
@@ -5216,7 +5272,7 @@ function loadCascadeInput(params) {
5216
5272
  const globalConfig = loadConfigFile(params.paths.globalConfigFile, GlobalConfigSchema, params.read);
5217
5273
  const directoryRules = loadConfigFile(params.paths.directoryRulesFile, DirectoryRulesSchema, params.read);
5218
5274
  const loadProfile = (name) => {
5219
- const filepath = path17.join(params.paths.configProfilesDir, `${name}.json`);
5275
+ const filepath = path18.join(params.paths.configProfilesDir, `${name}.json`);
5220
5276
  const loaded = loadConfigFile(filepath, ConfigProfileSchema, params.read);
5221
5277
  if (loaded === void 0) {
5222
5278
  return void 0;
@@ -5231,8 +5287,8 @@ function loadCascadeInput(params) {
5231
5287
  });
5232
5288
  const levels = [];
5233
5289
  for (const dir of dirs) {
5234
- const portable = loadConfigFile(path17.join(dir, PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(path17.join(dir, LEGACY_PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read);
5235
- const portableLocal = loadConfigFile(path17.join(dir, PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(path17.join(dir, LEGACY_PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read);
5290
+ const portable = loadConfigFile(path18.join(dir, PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(path18.join(dir, LEGACY_PORTABLE_CONFIG_FILENAME), PortableConfigSchema, params.read);
5291
+ const portableLocal = loadConfigFile(path18.join(dir, PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read) ?? loadConfigFile(path18.join(dir, LEGACY_PORTABLE_LOCAL_CONFIG_FILENAME), PortableConfigSchema, params.read);
5236
5292
  const rules = (directoryRules?.config.rules ?? []).map((rule, index) => ({ rule, index })).filter(({ rule }) => normaliseRulePath(rule.path, params.home) === dir).map(({ rule, index }) => {
5237
5293
  const entryOrder = directoryRules?.ruleEntryOrders[index];
5238
5294
  return {
@@ -5329,7 +5385,7 @@ function quotaWarnings(snapshot, provider, nowMs) {
5329
5385
  }
5330
5386
 
5331
5387
  // src/usage/poolPick.ts
5332
- import path18 from "node:path";
5388
+ import path19 from "node:path";
5333
5389
  import { z as z9 } from "zod";
5334
5390
 
5335
5391
  // src/usage/plan.ts
@@ -5631,7 +5687,7 @@ function recordStickyPick(fs12, picksFile, directory, identity, nowMs) {
5631
5687
  const current = readPicksFile(fs12, picksFile).file.picks;
5632
5688
  const kept = Object.entries(current).filter(([, entry]) => nowMs - Date.parse(entry.at) <= USAGE_RETENTION_MS);
5633
5689
  const next = { schemaVersion: SCHEMA_VERSION, picks: { ...Object.fromEntries(kept), [directory]: { identity, at: new Date(nowMs).toISOString() } } };
5634
- fs12.mkdirPrivate(path18.dirname(picksFile));
5690
+ fs12.mkdirPrivate(path19.dirname(picksFile));
5635
5691
  fs12.writeFilePrivate(picksFile, `${JSON.stringify(next, null, 2)}
5636
5692
  `);
5637
5693
  }
@@ -5728,14 +5784,14 @@ import { spawn, spawnSync } from "node:child_process";
5728
5784
  import { createHash as createHash4 } from "node:crypto";
5729
5785
  import fs7 from "node:fs";
5730
5786
  import os3 from "node:os";
5731
- import path20 from "node:path";
5787
+ import path21 from "node:path";
5732
5788
  import { isSea } from "node:sea";
5733
5789
 
5734
5790
  // src/versionDiscovery.ts
5735
5791
  import os2 from "node:os";
5736
- import path19 from "node:path";
5792
+ import path20 from "node:path";
5737
5793
  function defaultVersionsDir() {
5738
- return path19.join(os2.homedir(), ".local", "share", "claude", "versions");
5794
+ return path20.join(os2.homedir(), ".local", "share", "claude", "versions");
5739
5795
  }
5740
5796
  var NUMERIC_DOTTED_VERSION_RE = /^\d+(?:\.\d+)*$/;
5741
5797
  function isNumericDottedVersion(name) {
@@ -5777,14 +5833,14 @@ function discoverClaudeBinary(options) {
5777
5833
  const highestVersion = pickHighestVersion(entries);
5778
5834
  if (highestVersion !== void 0) {
5779
5835
  return {
5780
- path: path19.join(versionsDir, highestVersion),
5836
+ path: path20.join(versionsDir, highestVersion),
5781
5837
  source: "versions-dir",
5782
5838
  version: highestVersion
5783
5839
  };
5784
5840
  }
5785
- const ownInstallDirs = new Set(options.ownInstallDirs.map((dir) => path19.resolve(dir)));
5841
+ const ownInstallDirs = new Set(options.ownInstallDirs.map((dir) => path20.resolve(dir)));
5786
5842
  for (const dir of options.pathDirs) {
5787
- if (ownInstallDirs.has(path19.resolve(dir))) {
5843
+ if (ownInstallDirs.has(path20.resolve(dir))) {
5788
5844
  continue;
5789
5845
  }
5790
5846
  const found = options.findExecutableInDir(dir, "claude");
@@ -5955,7 +6011,7 @@ var realRunPort = {
5955
6011
  }
5956
6012
  };
5957
6013
  function expandHome2(filePath) {
5958
- return filePath.startsWith("~/") ? path20.join(os3.homedir(), filePath.slice(1)) : filePath;
6014
+ return filePath.startsWith("~/") ? path21.join(os3.homedir(), filePath.slice(1)) : filePath;
5959
6015
  }
5960
6016
  var MACOS_GUI_SESSION_MANAGER = "Aqua";
5961
6017
  function hasDesktopSession() {
@@ -6028,7 +6084,7 @@ function spawnDaemonThrough(executable) {
6028
6084
  return (paths, subcommand, logPath) => spawnDetachedDaemon({ command: executable, args: [subcommand] }, paths, subcommand, logPath);
6029
6085
  }
6030
6086
  function spawnDetachedDaemon(invocation, paths, subcommand, logPath) {
6031
- fs7.mkdirSync(path20.dirname(logPath), { recursive: true });
6087
+ fs7.mkdirSync(path21.dirname(logPath), { recursive: true });
6032
6088
  const logFd = fs7.openSync(logPath, "a");
6033
6089
  try {
6034
6090
  const child = spawn(invocation.command, invocation.args, detachedDaemonSpawnOptions(logFd, { ...process.env, AGENT_SHIM_HOME: paths.root }));
@@ -6044,6 +6100,29 @@ function spawnDetachedDaemon(invocation, paths, subcommand, logPath) {
6044
6100
  function spawnHeadroomSupervisor(paths, spawnDaemon) {
6045
6101
  return spawnDaemon(paths, "__headroom-supervisor", paths.headroomLogPath);
6046
6102
  }
6103
+ var SOCKET_PERMISSION_BITS = 511;
6104
+ var realHeadroomSocketTrust = {
6105
+ platform: process.platform,
6106
+ currentUid: () => {
6107
+ if (process.getuid === void 0) {
6108
+ throw new Error(`no POSIX user id on ${process.platform}`);
6109
+ }
6110
+ return process.getuid();
6111
+ },
6112
+ lstat: (target) => {
6113
+ let stat;
6114
+ try {
6115
+ stat = fs7.lstatSync(target);
6116
+ } catch (error) {
6117
+ if (isEnoent3(error)) {
6118
+ return void 0;
6119
+ }
6120
+ throw error;
6121
+ }
6122
+ const kind = stat.isSymbolicLink() ? "symlink" : stat.isDirectory() ? "dir" : stat.isSocket() ? "socket" : "other";
6123
+ return { kind, uid: stat.uid, mode: stat.mode & SOCKET_PERMISSION_BITS };
6124
+ }
6125
+ };
6047
6126
  function realHeadroomPort(paths, options) {
6048
6127
  return {
6049
6128
  ensure: () => {
@@ -6060,7 +6139,7 @@ function realHeadroomPort(paths, options) {
6060
6139
  }
6061
6140
  });
6062
6141
  return {
6063
- port: up.port,
6142
+ socketPath: up.socketPath,
6064
6143
  projectId: resolveGitRoot(realRunPort, options.cwd) ?? options.cwd
6065
6144
  };
6066
6145
  },
@@ -6086,7 +6165,7 @@ function listVersionsDir(dir) {
6086
6165
  throw error;
6087
6166
  }
6088
6167
  return entries.filter((entry) => entry.isFile()).map((entry) => {
6089
- const fullPath = path20.join(dir, entry.name);
6168
+ const fullPath = path21.join(dir, entry.name);
6090
6169
  const stat = fs7.statSync(fullPath);
6091
6170
  return {
6092
6171
  name: entry.name,
@@ -6101,7 +6180,7 @@ function windowsPathExtensions(pathext) {
6101
6180
  return (pathext ?? WINDOWS_DEFAULT_PATHEXT).split(";").map((ext) => ext.trim()).filter((ext) => ext.length > 0);
6102
6181
  }
6103
6182
  function resolveExecutableCandidate(dir, name, env) {
6104
- const candidate = path20.join(dir, name);
6183
+ const candidate = path21.join(dir, name);
6105
6184
  if (env.platform === "win32") {
6106
6185
  const extensions = windowsPathExtensions(env.pathext);
6107
6186
  const alreadyHasRecognisedExtension = extensions.some((ext) => candidate.toLowerCase().endsWith(ext.toLowerCase()));
@@ -6150,13 +6229,13 @@ function resolveOwnExecutablePath(env) {
6150
6229
  if (env.argv1 !== void 0 && !env.argv1.includes("/") && !env.argv1.includes("\\")) {
6151
6230
  return searchPathForExecutable(env.pathDirs, env.argv1, env.findExecutableInDir) ?? env.execPath;
6152
6231
  }
6153
- const candidate = env.argv1 === void 0 ? env.execPath : path20.resolve(env.cwd, env.argv1);
6154
- const candidateDir = path20.dirname(candidate);
6155
- const candidateDirOnPath = env.pathDirs.some((dir) => path20.resolve(dir) === candidateDir);
6232
+ const candidate = env.argv1 === void 0 ? env.execPath : path21.resolve(env.cwd, env.argv1);
6233
+ const candidateDir = path21.dirname(candidate);
6234
+ const candidateDirOnPath = env.pathDirs.some((dir) => path21.resolve(dir) === candidateDir);
6156
6235
  if (candidateDirOnPath) {
6157
6236
  return candidate;
6158
6237
  }
6159
- const viaPath = searchPathForExecutable(env.pathDirs, path20.basename(candidate), env.findExecutableInDir);
6238
+ const viaPath = searchPathForExecutable(env.pathDirs, path21.basename(candidate), env.findExecutableInDir);
6160
6239
  return viaPath ?? candidate;
6161
6240
  }
6162
6241
  function realOwnExecutablePath() {
@@ -6164,21 +6243,21 @@ function realOwnExecutablePath() {
6164
6243
  argv1: process.argv[1],
6165
6244
  execPath: process.execPath,
6166
6245
  cwd: process.cwd(),
6167
- pathDirs: (process.env.PATH ?? "").split(path20.delimiter).filter((dir) => dir !== ""),
6246
+ pathDirs: (process.env.PATH ?? "").split(path21.delimiter).filter((dir) => dir !== ""),
6168
6247
  findExecutableInDir
6169
6248
  });
6170
6249
  }
6171
6250
  function realResolveClaudeBinary(ownInstallDirs) {
6172
6251
  return () => discoverClaudeBinary({
6173
6252
  listVersionsDir,
6174
- pathDirs: (process.env.PATH ?? "").split(path20.delimiter).filter((dir) => dir !== ""),
6253
+ pathDirs: (process.env.PATH ?? "").split(path21.delimiter).filter((dir) => dir !== ""),
6175
6254
  findExecutableInDir,
6176
6255
  ownInstallDirs: [...ownInstallDirs]
6177
6256
  });
6178
6257
  }
6179
6258
 
6180
6259
  // src/checkReport.ts
6181
- import path21 from "node:path";
6260
+ import path22 from "node:path";
6182
6261
  import { z as z10 } from "zod";
6183
6262
 
6184
6263
  // src/cli/bool.ts
@@ -6546,10 +6625,10 @@ function collectCheckReport(params) {
6546
6625
  }).input;
6547
6626
  const providerName = cascadeProviderName(cascade);
6548
6627
  const provider = providerName === void 0 ? void 0 : loadCheckProvider(paths, providerName);
6549
- const farmRoot = identityDecision.name === void 0 ? void 0 : path21.join(paths.identitiesDir, identityDecision.name);
6628
+ const farmRoot = identityDecision.name === void 0 ? void 0 : path22.join(paths.identitiesDir, identityDecision.name);
6550
6629
  const settingsFiles = {
6551
- "settings.json": realFsPort.readFileUtf8(path21.join(claudeHome, "settings.json")),
6552
- "settings.local.json": realFsPort.readFileUtf8(path21.join(claudeHome, "settings.local.json"))
6630
+ "settings.json": realFsPort.readFileUtf8(path22.join(claudeHome, "settings.json")),
6631
+ "settings.local.json": realFsPort.readFileUtf8(path22.join(claudeHome, "settings.local.json"))
6553
6632
  };
6554
6633
  const report = runCheck({
6555
6634
  cwd,
@@ -6579,7 +6658,7 @@ function collectCheckReport(params) {
6579
6658
 
6580
6659
  // src/claudeShim.ts
6581
6660
  import fs8 from "node:fs";
6582
- import path22 from "node:path";
6661
+ import path23 from "node:path";
6583
6662
  import { z as z11 } from "zod";
6584
6663
  var ClaudeShimStateSchema = z11.strictObject({
6585
6664
  targetPath: z11.string().min(1),
@@ -6590,29 +6669,29 @@ function commandFilename(ownExecutablePath, commandName) {
6590
6669
  return ownExecutablePath.toLowerCase().endsWith(".exe") ? `${commandName}.exe` : commandName;
6591
6670
  }
6592
6671
  function resolveOwnInstallDirs(paths, ownExecutablePath) {
6593
- const dirs = [path22.dirname(ownExecutablePath)];
6672
+ const dirs = [path23.dirname(ownExecutablePath)];
6594
6673
  const state = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
6595
6674
  if (state !== void 0) {
6596
- dirs.push(path22.dirname(state.targetPath));
6675
+ dirs.push(path23.dirname(state.targetPath));
6597
6676
  }
6598
6677
  return dirs;
6599
6678
  }
6600
6679
  var nodeLinkFs = { link: fs8.linkSync, copyFile: fs8.copyFileSync, chmod: fs8.chmodSync };
6601
6680
  function findPathShadow(params) {
6602
- const resolvedTargetDir = path22.resolve(params.targetDir);
6681
+ const resolvedTargetDir = path23.resolve(params.targetDir);
6603
6682
  for (const dir of params.pathDirs) {
6604
6683
  const found = params.findExecutableInDir(dir, params.targetFilename);
6605
6684
  if (found === void 0) {
6606
6685
  continue;
6607
6686
  }
6608
- return path22.resolve(dir) === resolvedTargetDir ? { status: "ok" } : { status: "shadowed", by: found };
6687
+ return path23.resolve(dir) === resolvedTargetDir ? { status: "ok" } : { status: "shadowed", by: found };
6609
6688
  }
6610
- return params.pathDirs.some((dir) => path22.resolve(dir) === resolvedTargetDir) ? { status: "ok" } : { status: "not-on-path" };
6689
+ return params.pathDirs.some((dir) => path23.resolve(dir) === resolvedTargetDir) ? { status: "ok" } : { status: "not-on-path" };
6611
6690
  }
6612
6691
 
6613
6692
  // src/doctorReport.ts
6614
6693
  import fs9 from "node:fs";
6615
- import path23 from "node:path";
6694
+ import path24 from "node:path";
6616
6695
  function refinePathShadow(status, ownExecutablePath, realpath) {
6617
6696
  if (status.status !== "shadowed") {
6618
6697
  return status;
@@ -6636,7 +6715,7 @@ function validateJson(schema, input) {
6636
6715
  return { ok: true, data: result.data };
6637
6716
  }
6638
6717
  function pushPathResolution(push, resolution) {
6639
- const ownDir = path23.dirname(resolution.ownExecutablePath);
6718
+ const ownDir = path24.dirname(resolution.ownExecutablePath);
6640
6719
  switch (resolution.agentShim.status) {
6641
6720
  case "ok":
6642
6721
  push("path-resolution", "pass", `\`agent-shim\` on PATH resolves to this running executable, ${resolution.ownExecutablePath}.`, "agent-shim");
@@ -6704,14 +6783,14 @@ function pushProvider(push, entry) {
6704
6783
  }
6705
6784
  function pushLegacyName(push, params) {
6706
6785
  const legacyVariables = Object.keys(params.env).filter((name) => name.startsWith(LEGACY_ENV_PREFIX) && params.env[name] !== void 0).sort();
6707
- if (legacyVariables.length === 0 && path23.basename(params.rootPath) !== LEGACY_HOME_DIRNAME) {
6786
+ if (legacyVariables.length === 0 && path24.basename(params.rootPath) !== LEGACY_HOME_DIRNAME) {
6708
6787
  push("legacy-name", "pass", "Nothing here still uses the former `claude-use` name.");
6709
6788
  return;
6710
6789
  }
6711
6790
  for (const name of legacyVariables) {
6712
6791
  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);
6713
6792
  }
6714
- if (path23.basename(params.rootPath) === LEGACY_HOME_DIRNAME) {
6793
+ if (path24.basename(params.rootPath) === LEGACY_HOME_DIRNAME) {
6715
6794
  push(
6716
6795
  "legacy-name",
6717
6796
  "warn",
@@ -6901,7 +6980,7 @@ function runDoctor(params) {
6901
6980
  "warn",
6902
6981
  `Headroom state names supervisor pid ${String(state.supervisorPid)}, which is not running; the next launch through headroom will start a replacement.`
6903
6982
  );
6904
- } else if (state.headroomPid === void 0 || state.port === void 0) {
6983
+ } else if (state.headroomPid === void 0 || state.socketPath === void 0) {
6905
6984
  push(
6906
6985
  "headroom",
6907
6986
  "warn",
@@ -6917,7 +6996,7 @@ function runDoctor(params) {
6917
6996
  push(
6918
6997
  "headroom",
6919
6998
  "pass",
6920
- `Headroom daemon is up on 127.0.0.1:${String(state.port)} (supervisor ${String(state.supervisorPid)}, daemon ${String(state.headroomPid)}).`
6999
+ `Headroom daemon is up on unix socket ${state.socketPath} (supervisor ${String(state.supervisorPid)}, daemon ${String(state.headroomPid)}).`
6921
7000
  );
6922
7001
  }
6923
7002
  if (state.lastError !== void 0 && supervisorAlive) {
@@ -7019,18 +7098,18 @@ function collectDoctorReport(params) {
7019
7098
  const { paths } = params;
7020
7099
  const identityNames = fs9.existsSync(paths.identitiesDir) ? fs9.readdirSync(paths.identitiesDir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && isIdentityDirectoryName(entry.name)).map((entry) => entry.name).sort() : [];
7021
7100
  const identities = identityNames.map((name) => {
7022
- const farmRoot = path23.join(paths.identitiesDir, name);
7023
- const identityPath = path23.join(farmRoot, "identity.json");
7101
+ const farmRoot = path24.join(paths.identitiesDir, name);
7102
+ const identityPath = path24.join(farmRoot, "identity.json");
7024
7103
  return { name, path: identityPath, raw: realFsPort.readFileUtf8(identityPath), farmRoot };
7025
7104
  });
7026
7105
  const profileNames = fs9.existsSync(paths.configProfilesDir) ? fs9.readdirSync(paths.configProfilesDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
7027
7106
  const configProfiles = profileNames.map((name) => {
7028
- const profilePath = path23.join(paths.configProfilesDir, `${name}.json`);
7107
+ const profilePath = path24.join(paths.configProfilesDir, `${name}.json`);
7029
7108
  return { name, path: profilePath, raw: realFsPort.readFileUtf8(profilePath) };
7030
7109
  });
7031
7110
  const providerNames = fs9.existsSync(paths.providersDir) ? fs9.readdirSync(paths.providersDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
7032
7111
  const providers = providerNames.map((name) => {
7033
- const providerPath = path23.join(paths.providersDir, `${name}.json`);
7112
+ const providerPath = path24.join(paths.providersDir, `${name}.json`);
7034
7113
  return { name, path: providerPath, raw: realFsPort.readFileUtf8(providerPath) };
7035
7114
  });
7036
7115
  const ownExecutablePath = realOwnExecutablePath();
@@ -7042,12 +7121,12 @@ function collectDoctorReport(params) {
7042
7121
  binaryDiscovery = { ok: false, message: error instanceof Error ? error.message : String(error) };
7043
7122
  }
7044
7123
  const shimState = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
7045
- const pathDirs = (params.env.PATH ?? "").split(path23.delimiter).filter((dir) => dir !== "");
7124
+ const pathDirs = (params.env.PATH ?? "").split(path24.delimiter).filter((dir) => dir !== "");
7046
7125
  const claudeShimShadow = shimState === void 0 ? void 0 : refinePathShadow(
7047
7126
  findPathShadow({
7048
7127
  pathDirs,
7049
- targetDir: path23.dirname(shimState.targetPath),
7050
- targetFilename: path23.basename(shimState.targetPath),
7128
+ targetDir: path24.dirname(shimState.targetPath),
7129
+ targetFilename: path24.basename(shimState.targetPath),
7051
7130
  findExecutableInDir
7052
7131
  }),
7053
7132
  shimState.targetPath,
@@ -7070,7 +7149,7 @@ function collectDoctorReport(params) {
7070
7149
  agentShim: refinePathShadow(
7071
7150
  findPathShadow({
7072
7151
  pathDirs,
7073
- targetDir: path23.dirname(ownExecutablePath),
7152
+ targetDir: path24.dirname(ownExecutablePath),
7074
7153
  targetFilename: commandFilename(ownExecutablePath, "agent-shim"),
7075
7154
  findExecutableInDir
7076
7155
  }),
@@ -7091,7 +7170,7 @@ function collectDoctorReport(params) {
7091
7170
 
7092
7171
  // src/launcher.ts
7093
7172
  import { randomUUID as randomUUID4 } from "node:crypto";
7094
- import path25 from "node:path";
7173
+ import path26 from "node:path";
7095
7174
 
7096
7175
  // src/launcher/argv.ts
7097
7176
  var ConflictingIdentityError = class extends UsageError {
@@ -7343,7 +7422,7 @@ function buildCliOverride(params) {
7343
7422
  }
7344
7423
 
7345
7424
  // src/launcher/flags.ts
7346
- import path24 from "node:path";
7425
+ import path25 from "node:path";
7347
7426
 
7348
7427
  // src/headroom/headers.ts
7349
7428
  function mergeAnthropicCustomHeaders(existing, additions) {
@@ -7413,7 +7492,7 @@ function buildEnv(params) {
7413
7492
  const parentCustomHeaders = params.baseEnv.ANTHROPIC_CUSTOM_HEADERS;
7414
7493
  let providerCustomHeaders;
7415
7494
  if (!params.configDirEscapeHatch && params.resolvedIdentityName !== void 0) {
7416
- env.CLAUDE_CONFIG_DIR = path24.join(params.identitiesDir, params.resolvedIdentityName);
7495
+ env.CLAUDE_CONFIG_DIR = path25.join(params.identitiesDir, params.resolvedIdentityName);
7417
7496
  }
7418
7497
  if (params.provider !== void 0) {
7419
7498
  const providerEnv = params.provider.definition.env ?? {};
@@ -7434,9 +7513,6 @@ function buildEnv(params) {
7434
7513
  env[variable] = value;
7435
7514
  }
7436
7515
  }
7437
- if (params.headroom !== void 0) {
7438
- env.HEADROOM_PROXY_URL = `http://127.0.0.1:${String(params.headroom.port)}`;
7439
- }
7440
7516
  if (params.frontdoor !== void 0) {
7441
7517
  env.ANTHROPIC_CUSTOM_HEADERS = mergeAnthropicCustomHeaders(
7442
7518
  [
@@ -7577,7 +7653,7 @@ function prepareLaunch(params) {
7577
7653
  identityDefaultConfigProfile: loadedIdentity?.config.defaultConfigProfile,
7578
7654
  globalDefaultConfigProfile: params.globalDefaultConfigProfile
7579
7655
  });
7580
- if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(path25.join(paths.configProfilesDir, `${configProfileDecision.name}.json`)) === void 0) {
7656
+ if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(path26.join(paths.configProfilesDir, `${configProfileDecision.name}.json`)) === void 0) {
7581
7657
  log.error(
7582
7658
  `agent-shim: no configuration profile named "${configProfileDecision.name}" (selected via ${configProfileDecision.source}). Run \`agent-shim profile add ${configProfileDecision.name}\` first.`
7583
7659
  );
@@ -7713,7 +7789,7 @@ function prepareLaunch(params) {
7713
7789
  if (resolvedFlags.headroom && headroomPort !== void 0) {
7714
7790
  headroom = headroomPort.ensure();
7715
7791
  const via = resolvedProvider === void 0 ? `OAuth via the door's CONNECT surface on 127.0.0.1:${String(frontDoor?.connectPort ?? 0)}` : `provider ${resolvedProvider.name}`;
7716
- 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})`);
7792
+ 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})`);
7717
7793
  } else if (resolvedFlags.headroom) {
7718
7794
  log.error("agent-shim: headroom routing was requested but this launcher has no headroom port wired; refusing to launch without it.");
7719
7795
  proc.exit(1);
@@ -7753,7 +7829,7 @@ import { randomUUID as randomUUID5 } from "node:crypto";
7753
7829
  // src/realCredentialCache.ts
7754
7830
  import { spawnSync as spawnSync2 } from "node:child_process";
7755
7831
  import fs10 from "node:fs";
7756
- import path26 from "node:path";
7832
+ import path27 from "node:path";
7757
7833
  var KEYCHAIN_CACHE_SERVICE = "agent-shim-credential-cache";
7758
7834
  var CACHE_DIR_MODE = 448;
7759
7835
  var CACHE_FILE_MODE = 384;
@@ -7780,8 +7856,8 @@ function security(args, stdin) {
7780
7856
  return { status: result.status, stdout: result.stdout };
7781
7857
  }
7782
7858
  function createRealCredentialCache(root) {
7783
- const dir = path26.join(root, "credential-cache");
7784
- const filePath = (owner) => path26.join(dir, cacheFileNameFor(owner));
7859
+ const dir = path27.join(root, "credential-cache");
7860
+ const filePath = (owner) => path27.join(dir, cacheFileNameFor(owner));
7785
7861
  return {
7786
7862
  read(store, owner) {
7787
7863
  if (store === "file") {
@@ -7897,11 +7973,11 @@ function probeFrontDoorSync(port, caPem) {
7897
7973
 
7898
7974
  // src/frontdoor/trust.ts
7899
7975
  import { createHash as createHash5 } from "node:crypto";
7900
- import path27 from "node:path";
7976
+ import path28 from "node:path";
7901
7977
  var BUNDLE_NAME_HEX_DIGITS = 16;
7902
7978
  function resolveTrustBundle(params) {
7903
- const { caCertFile, bundlesDir, inherited, fs: fs12 } = params;
7904
- if (inherited === void 0 || inherited === "" || path27.resolve(inherited) === path27.resolve(caCertFile)) {
7979
+ const { caCertFile, bundlesDir, variable, inherited, fs: fs12 } = params;
7980
+ if (inherited === void 0 || inherited === "" || path28.resolve(inherited) === path28.resolve(caCertFile)) {
7905
7981
  return { path: caCertFile };
7906
7982
  }
7907
7983
  const caPem = fs12.readFileUtf8(caCertFile);
@@ -7911,7 +7987,7 @@ function resolveTrustBundle(params) {
7911
7987
  } catch (error) {
7912
7988
  return {
7913
7989
  path: caCertFile,
7914
- 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`
7990
+ 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`
7915
7991
  };
7916
7992
  }
7917
7993
  if (inheritedPem.includes(caPem.trim())) {
@@ -7919,7 +7995,7 @@ function resolveTrustBundle(params) {
7919
7995
  }
7920
7996
  const combined = `${inheritedPem.trimEnd()}
7921
7997
  ${caPem}`;
7922
- const bundle = path27.join(bundlesDir, `${createHash5("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
7998
+ const bundle = path28.join(bundlesDir, `${createHash5("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
7923
7999
  if (!fs12.exists(bundle)) {
7924
8000
  fs12.mkdirp(bundlesDir);
7925
8001
  fs12.writeFileAtomic(bundle, combined);
@@ -7957,7 +8033,7 @@ function realFrontDoorPort(paths, spawnDaemon) {
7957
8033
  verifyListener: (port) => probeFrontDoorSync(port, fs11.readFileSync(paths.frontdoorCaCertFile, "utf8"))
7958
8034
  }
7959
8035
  });
7960
- const trust = resolveTrustBundle({ caCertFile: paths.frontdoorCaCertFile, bundlesDir: paths.frontdoorCaBundlesDir, inherited: inheritedExtraCaCerts, fs: realTrustBundleFs });
8036
+ const trust = resolveTrustBundle({ caCertFile: paths.frontdoorCaCertFile, bundlesDir: paths.frontdoorCaBundlesDir, variable: "NODE_EXTRA_CA_CERTS", inherited: inheritedExtraCaCerts, fs: realTrustBundleFs });
7961
8037
  return {
7962
8038
  port: up.port,
7963
8039
  connectPort: up.connectPort,