claude-use 11.56.1 → 11.57.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
@@ -198,8 +198,8 @@ var init_statusline = __esm({
198
198
  import_zod = require("zod");
199
199
  init_blank();
200
200
  init_graphemes();
201
- STATUSLINE_HEADER_SEGMENTS = ["model", "provider", "route", "account", "identity", "headroom", "project", "vcs", "effort", "advisor", "version", "outputStyle"];
202
- STATUSLINE_ROWS = ["context", "quota", "addedDirs", "gitFiles"];
201
+ STATUSLINE_HEADER_SEGMENTS = ["model", "provider", "route", "account", "identity", "headroom", "project", "vcs", "effort", "advisor", "version", "outputStyle", "cost", "dailyCost"];
202
+ STATUSLINE_ROWS = ["context", "quota", "addedDirs", "gitFiles", "memory", "environment"];
203
203
  STATUSLINE_COLOUR_NAMES = [
204
204
  "default",
205
205
  "dim",
@@ -290,6 +290,12 @@ var init_statusline = __esm({
290
290
  hourCycle: import_zod.z.enum(STATUSLINE_HOUR_CYCLES).describe("The hour cycle of a wall-clock time: `auto` follows the system locale, `h23` and `h24` are 24-hour time (`h24` writes midnight as 24:00), and `h12` and `h11` are 12-hour time with am or pm (`h11` writes the hour after midnight as 0)."),
291
291
  seconds: import_zod.z.boolean().describe("Whether a wall-clock time includes seconds (`14:30:07`).")
292
292
  },
293
+ cost: {
294
+ routed: import_zod.z.boolean().describe("Whether the cost segments draw for a session routed through a provider or a cloud platform's model id, where the client's own figure is not what was billed; the figure drawn is then priced from the door's usage log with `agent-shim model price`, else the client's own when it is above zero.")
295
+ },
296
+ environment: {
297
+ threshold: import_zod.z.number().int().min(0).describe("The fewest configuration items in total (CLAUDE.md files, rules, MCP servers and hook events) that must exist for the environment row to draw its counts.")
298
+ },
293
299
  colours: {
294
300
  context: colourValue.describe("The colour of the context bar and its figures below the warning threshold."),
295
301
  usage: colourValue.describe("The colour of the quota bars and their figures below the warning threshold."),
@@ -334,6 +340,8 @@ var init_statusline = __esm({
334
340
  bar: import_zod.z.strictObject(SHAPES.bar).partial().optional(),
335
341
  usage: import_zod.z.strictObject(SHAPES.usage).partial().optional(),
336
342
  clock: import_zod.z.strictObject(SHAPES.clock).partial().optional(),
343
+ cost: import_zod.z.strictObject(SHAPES.cost).partial().optional(),
344
+ environment: import_zod.z.strictObject(SHAPES.environment).partial().optional(),
337
345
  colours: import_zod.z.strictObject(SHAPES.colours).partial().optional(),
338
346
  project: import_zod.z.strictObject(SHAPES.project).partial().optional(),
339
347
  git: import_zod.z.strictObject(SHAPES.git).partial().optional(),
@@ -351,6 +359,8 @@ var init_statusline = __esm({
351
359
  bar: import_zod.z.strictObject(SHAPES.bar),
352
360
  usage: import_zod.z.strictObject(SHAPES.usage),
353
361
  clock: import_zod.z.strictObject(SHAPES.clock),
362
+ cost: import_zod.z.strictObject(SHAPES.cost),
363
+ environment: import_zod.z.strictObject(SHAPES.environment),
354
364
  colours: import_zod.z.strictObject(SHAPES.colours),
355
365
  project: import_zod.z.strictObject(SHAPES.project),
356
366
  git: import_zod.z.strictObject(SHAPES.git),
@@ -368,6 +378,8 @@ var init_statusline = __esm({
368
378
  bar: { width: 10, filled: "\u2588", empty: "\u2591" },
369
379
  usage: { value: "used", bar: true, compact: false, resetLabel: false, modelScoped: false, timeFormat: "relative", threshold: 0, sevenDayThreshold: 0 },
370
380
  clock: { hourCycle: "auto", seconds: false },
381
+ cost: { routed: false },
382
+ environment: { threshold: 0 },
371
383
  colours: {
372
384
  context: "green",
373
385
  usage: "green",
@@ -4450,7 +4462,7 @@ var init_package = __esm({
4450
4462
  "package.json"() {
4451
4463
  package_default = {
4452
4464
  name: "claude-use",
4453
- version: "11.56.1",
4465
+ version: "11.57.1",
4454
4466
  description: "A profile manager and launcher for Claude Code that lets one person run multiple logins from one machine while controlling what gets shared between them.",
4455
4467
  license: "MIT",
4456
4468
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -4554,6 +4566,20 @@ var init_package = __esm({
4554
4566
  }
4555
4567
  });
4556
4568
 
4569
+ // src/blockingSpawn.ts
4570
+ function spawnSyncBlocking(operation, command, args, options) {
4571
+ refuseToBlockInRole(operation);
4572
+ return (0, import_node_child_process2.spawnSync)(command, args, options ?? {});
4573
+ }
4574
+ var import_node_child_process2;
4575
+ var init_blockingSpawn = __esm({
4576
+ "src/blockingSpawn.ts"() {
4577
+ "use strict";
4578
+ import_node_child_process2 = require("node:child_process");
4579
+ init_processRole();
4580
+ }
4581
+ });
4582
+
4557
4583
  // src/frontdoor/supervisorProcesses.ts
4558
4584
  function parseFrontDoorSupervisorPids(psOutput) {
4559
4585
  const pids = [];
@@ -5705,27 +5731,23 @@ function realIsProcessAlive(pid) {
5705
5731
  }
5706
5732
  }
5707
5733
  function realIsProcessZombie(pid) {
5708
- refuseToBlockInRole("a synchronous process-table read");
5709
- const result = (0, import_node_child_process2.spawnSync)("ps", ["-o", "stat=", "-p", String(pid)], { encoding: "utf8" });
5734
+ const result = spawnSyncBlocking("a process-table read", "ps", ["-o", "stat=", "-p", String(pid)], { encoding: "utf8" });
5710
5735
  return result.status === 0 && result.stdout.trim().startsWith("Z");
5711
5736
  }
5712
5737
  function realIsProcessRunning(pid) {
5713
5738
  return realIsProcessAlive(pid) && !realIsProcessZombie(pid);
5714
5739
  }
5715
5740
  function realIsFrontDoorSupervisor(pid) {
5716
- refuseToBlockInRole("a synchronous process-table read");
5717
- const result = (0, import_node_child_process2.spawnSync)("ps", ["-o", "pid=,command=", "-p", String(pid)], { encoding: "utf8" });
5741
+ const result = spawnSyncBlocking("a process-table read", "ps", ["-o", "pid=,command=", "-p", String(pid)], { encoding: "utf8" });
5718
5742
  return result.status === 0 && parseFrontDoorSupervisorPids(result.stdout).includes(pid);
5719
5743
  }
5720
5744
  function realProcessCommandLine(pid) {
5721
- refuseToBlockInRole("a synchronous process-table read");
5722
- const result = (0, import_node_child_process2.spawnSync)("ps", ["-o", "command=", "-p", String(pid)], { encoding: "utf8", timeout: PS_TIMEOUT_MS });
5745
+ const result = spawnSyncBlocking("a process-table read", "ps", ["-o", "command=", "-p", String(pid)], { encoding: "utf8", timeout: PS_TIMEOUT_MS });
5723
5746
  return result.status === 0 ? result.stdout.trim() : void 0;
5724
5747
  }
5725
5748
  function realFrontDoorLiveness(pids) {
5726
- refuseToBlockInRole("a synchronous process-table read");
5727
5749
  return frontDoorLivenessOf(pids, (asked) => {
5728
- const result = (0, import_node_child_process2.spawnSync)("ps", ["-o", "pid=,stat=,command=", "-p", asked.map(String).join(",")], { encoding: "utf8", timeout: PS_TIMEOUT_MS });
5750
+ const result = spawnSyncBlocking("a process-table read", "ps", ["-o", "pid=,stat=,command=", "-p", asked.map(String).join(",")], { encoding: "utf8", timeout: PS_TIMEOUT_MS });
5729
5751
  return { status: result.status, stdout: result.stdout, stderr: result.stderr, ...result.error === void 0 ? {} : { error: result.error } };
5730
5752
  });
5731
5753
  }
@@ -5734,7 +5756,7 @@ function expandHome2(filePath) {
5734
5756
  }
5735
5757
  function hasDesktopSession() {
5736
5758
  if (process.platform === "darwin") {
5737
- const result = (0, import_node_child_process2.spawnSync)("launchctl", ["managername"], { encoding: "utf8" });
5759
+ const result = spawnSyncBlocking("a desktop-session check", "launchctl", ["managername"], { encoding: "utf8" });
5738
5760
  return result.status === 0 && result.stdout.trim() === MACOS_GUI_SESSION_MANAGER;
5739
5761
  }
5740
5762
  return hasDisplayServer();
@@ -5780,7 +5802,7 @@ function spawnDetachedDaemon(invocation, paths, subcommand, logPath) {
5780
5802
  import_node_fs2.default.mkdirSync(import_node_path14.default.dirname(logPath), { recursive: true });
5781
5803
  const logFd = import_node_fs2.default.openSync(logPath, "a");
5782
5804
  try {
5783
- const child = (0, import_node_child_process2.spawn)(invocation.command, invocation.args, detachedDaemonSpawnOptions(logFd, { ...process.env, AGENT_SHIM_HOME: paths.root }));
5805
+ const child = (0, import_node_child_process3.spawn)(invocation.command, invocation.args, detachedDaemonSpawnOptions(logFd, { ...process.env, AGENT_SHIM_HOME: paths.root }));
5784
5806
  child.unref();
5785
5807
  if (child.pid === void 0) {
5786
5808
  throw new Error(`spawning ${subcommand} returned no pid`);
@@ -5930,12 +5952,13 @@ function realResolveClaudeBinary(isOwnBinary) {
5930
5952
  function realInstalledClaudeVersions() {
5931
5953
  return installedVersions(listVersionsDir(defaultVersionsDir()));
5932
5954
  }
5933
- var import_node_child_process2, import_node_crypto8, import_node_fs2, import_node_os2, import_node_path14, import_node_sea, realFsPort, OWNER_ONLY_DIR_MODE, OWNER_ONLY_FILE_MODE, PERMISSION_BITS, realFarmFs, INT32_BYTE_LENGTH, KEY_POLL_MS, CTRL_C_BYTE, realHoldPort, PS_TIMEOUT_MS, realRunPort, MACOS_GUI_SESSION_MANAGER, realCredentialPort, SOCKET_PERMISSION_BITS, realHeadroomSocketTrust, realSpawnPort, realProcPort, realLogPort, EXECUTE_BITS_MASK, WINDOWS_DEFAULT_PATHEXT;
5955
+ var import_node_child_process3, import_node_crypto8, import_node_fs2, import_node_os2, import_node_path14, import_node_sea, realFsPort, OWNER_ONLY_DIR_MODE, OWNER_ONLY_FILE_MODE, PERMISSION_BITS, realFarmFs, INT32_BYTE_LENGTH, KEY_POLL_MS, CTRL_C_BYTE, realHoldPort, PS_TIMEOUT_MS, realRunPort, MACOS_GUI_SESSION_MANAGER, realCredentialPort, SOCKET_PERMISSION_BITS, realHeadroomSocketTrust, realSpawnPort, realProcPort, realLogPort, EXECUTE_BITS_MASK, WINDOWS_DEFAULT_PATHEXT;
5934
5956
  var init_realPorts = __esm({
5935
5957
  "src/realPorts.ts"() {
5936
5958
  "use strict";
5959
+ init_blockingSpawn();
5937
5960
  init_processRole();
5938
- import_node_child_process2 = require("node:child_process");
5961
+ import_node_child_process3 = require("node:child_process");
5939
5962
  import_node_crypto8 = require("node:crypto");
5940
5963
  import_node_fs2 = __toESM(require("node:fs"), 1);
5941
5964
  import_node_os2 = __toESM(require("node:os"), 1);
@@ -6107,7 +6130,7 @@ var init_realPorts = __esm({
6107
6130
  PS_TIMEOUT_MS = 2e3;
6108
6131
  realRunPort = {
6109
6132
  run(command, args) {
6110
- const result = (0, import_node_child_process2.spawnSync)(command, [...args], { encoding: "utf8" });
6133
+ const result = spawnSyncBlocking("an external command", command, args, { encoding: "utf8" });
6111
6134
  return { status: result.status, stdout: result.stdout, stderr: result.stderr };
6112
6135
  }
6113
6136
  };
@@ -6130,7 +6153,7 @@ var init_realPorts = __esm({
6130
6153
  },
6131
6154
  runCommand(argv, options) {
6132
6155
  const [command, ...args] = argv;
6133
- const result = (0, import_node_child_process2.spawnSync)(command, args, {
6156
+ const result = spawnSyncBlocking("a credential command", command, args, {
6134
6157
  encoding: "utf8",
6135
6158
  timeout: options.timeoutMs,
6136
6159
  stdio: options.interactive ? ["inherit", "pipe", "inherit"] : ["ignore", "pipe", "pipe"]
@@ -6169,7 +6192,7 @@ var init_realPorts = __esm({
6169
6192
  };
6170
6193
  realSpawnPort = {
6171
6194
  spawnSync(command, args, options) {
6172
- const result = (0, import_node_child_process2.spawnSync)(command, args, options);
6195
+ const result = spawnSyncBlocking("a spawned program", command, args, options);
6173
6196
  return { status: result.status, signal: result.signal, ...result.error === void 0 ? {} : { error: result.error } };
6174
6197
  }
6175
6198
  };
@@ -6391,7 +6414,7 @@ var init_identity = __esm({
6391
6414
  });
6392
6415
 
6393
6416
  // src/usage/schema.ts
6394
- var import_zod11, USAGE_SCHEMA_VERSION, VersionSchema, InstantSchema, TokenCountSchema, TokenUsageSchema, LIMIT_KINDS, LimitClassificationSchema, UsageRecordSchema, QuotaWindowSchema, ExtraUsageSpendSchema, UnifiedRateLimitSchema, RateLimitStateSchema, LimitEventSchema, ProviderQuotaWindowSchema, ProviderAccountSchema, ProviderQuotaSchema, ProviderUsageStateSchema, AccountMetadataSchema, UsageSnapshotSchema;
6417
+ var import_zod11, USAGE_SCHEMA_VERSION, VersionSchema, InstantSchema, CLIENT_SESSION_ID_PATTERN, TokenCountSchema, TokenUsageSchema, LIMIT_KINDS, LimitClassificationSchema, UsageRecordSchema, QuotaWindowSchema, ExtraUsageSpendSchema, UnifiedRateLimitSchema, RateLimitStateSchema, LimitEventSchema, ProviderQuotaWindowSchema, ProviderAccountSchema, ProviderQuotaSchema, ProviderUsageStateSchema, AccountMetadataSchema, UsageSnapshotSchema;
6395
6418
  var init_schema2 = __esm({
6396
6419
  "src/usage/schema.ts"() {
6397
6420
  "use strict";
@@ -6399,6 +6422,7 @@ var init_schema2 = __esm({
6399
6422
  USAGE_SCHEMA_VERSION = 1;
6400
6423
  VersionSchema = import_zod11.z.literal(USAGE_SCHEMA_VERSION);
6401
6424
  InstantSchema = import_zod11.z.iso.datetime();
6425
+ CLIENT_SESSION_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
6402
6426
  TokenCountSchema = import_zod11.z.number().int().nonnegative();
6403
6427
  TokenUsageSchema = import_zod11.z.strictObject({
6404
6428
  inputTokens: TokenCountSchema.optional(),
@@ -6428,6 +6452,8 @@ var init_schema2 = __esm({
6428
6452
  provider: import_zod11.z.string(),
6429
6453
  /** The launch's session id, generated per launch. */
6430
6454
  sessionId: import_zod11.z.string().optional(),
6455
+ /** The client's own id for the conversation, from the request's `x-claude-code-session-id` header: it changes when the conversation is cleared inside one launch, which `sessionId` does not, so it is what ties a request to the client's per-conversation figures. Absent when the client sent none. */
6456
+ clientSessionId: import_zod11.z.string().regex(CLIENT_SESSION_ID_PATTERN).optional(),
6431
6457
  /** The project the launch ran in (its git repository root), when the launch sent one: headroom launches do. */
6432
6458
  project: import_zod11.z.string().optional(),
6433
6459
  /** Whether the request crossed headroom on its way upstream. Absent on a record written before the door recorded it, and false when the request went direct. */
@@ -7983,6 +8009,7 @@ function buildLayoutPaths(root) {
7983
8009
  usageDir: import_node_path23.default.join(root, "usage"),
7984
8010
  usageLogDir: import_node_path23.default.join(root, "usage", "log"),
7985
8011
  usageSnapshotsDir: import_node_path23.default.join(root, "usage", "snapshots"),
8012
+ statuslineDir: import_node_path23.default.join(root, "statusline"),
7986
8013
  catalogueDir: import_node_path23.default.join(root, "catalogues"),
7987
8014
  usagePicksFile: import_node_path23.default.join(root, "usage", "picks.json"),
7988
8015
  usageAnchorsFile: import_node_path23.default.join(root, "usage", "anchors.json"),
@@ -8103,7 +8130,7 @@ function requireKeychain() {
8103
8130
  }
8104
8131
  }
8105
8132
  function security(args, stdin) {
8106
- const result = (0, import_node_child_process3.spawnSync)("security", args, { encoding: "utf8", ...stdin === void 0 ? {} : { input: stdin }, stdio: ["pipe", "pipe", "ignore"] });
8133
+ const result = spawnSyncBlocking("a keychain call", "security", args, { encoding: "utf8", ...stdin === void 0 ? {} : { input: stdin }, stdio: ["pipe", "pipe", "ignore"] });
8107
8134
  return { status: result.status, stdout: result.stdout };
8108
8135
  }
8109
8136
  function createRealCredentialCache(root) {
@@ -8154,13 +8181,13 @@ function createRealCredentialCache(root) {
8154
8181
  function realCredentialCacheEnv(paths) {
8155
8182
  return { port: createRealCredentialCache(paths.root), platform: process.platform, now: () => Date.now() };
8156
8183
  }
8157
- var import_node_child_process3, import_node_fs5, import_node_path24, KEYCHAIN_CACHE_SERVICE, CACHE_DIR_MODE, CACHE_FILE_MODE;
8184
+ var import_node_fs5, import_node_path24, KEYCHAIN_CACHE_SERVICE, CACHE_DIR_MODE, CACHE_FILE_MODE;
8158
8185
  var init_realCredentialCache = __esm({
8159
8186
  "src/realCredentialCache.ts"() {
8160
8187
  "use strict";
8161
- import_node_child_process3 = require("node:child_process");
8162
8188
  import_node_fs5 = __toESM(require("node:fs"), 1);
8163
8189
  import_node_path24 = __toESM(require("node:path"), 1);
8190
+ init_blockingSpawn();
8164
8191
  init_credentialCache();
8165
8192
  KEYCHAIN_CACHE_SERVICE = "agent-shim-credential-cache";
8166
8193
  CACHE_DIR_MODE = 448;
@@ -11527,13 +11554,13 @@ function resolveLaunch(params) {
11527
11554
  environment
11528
11555
  };
11529
11556
  }
11530
- function runLaunchPlan(plan, spawn4) {
11557
+ function runLaunchPlan(plan, spawn3) {
11531
11558
  try {
11532
11559
  if (plan.hold() === "cancelled") {
11533
11560
  return LAUNCH_CANCELLED_EXIT;
11534
11561
  }
11535
11562
  plan.markChildStarted();
11536
- const result = spawn4.spawnSync(plan.bin, plan.args, { stdio: "inherit", env: plan.env });
11563
+ const result = spawn3.spawnSync(plan.bin, plan.args, { stdio: "inherit", env: plan.env });
11537
11564
  if (result.error !== void 0) {
11538
11565
  throw result.error;
11539
11566
  }
@@ -11743,14 +11770,21 @@ var init_realFrontDoorPort = __esm({
11743
11770
  }
11744
11771
  });
11745
11772
 
11773
+ // src/replayRun.ts
11774
+ var init_replayRun = __esm({
11775
+ "src/replayRun.ts"() {
11776
+ "use strict";
11777
+ }
11778
+ });
11779
+
11746
11780
  // src/launchWiring.ts
11747
- function buildFarmRuntime(paths, cwd) {
11781
+ function buildFarmRuntime(paths, cwd, run = realRunPort) {
11748
11782
  const home = import_node_os7.default.homedir();
11749
11783
  const read = cosmiconfigReader();
11750
11784
  const classification = loadClassification(paths);
11751
11785
  const loaded = loadCascadeInput({ paths, home, cwd, read });
11752
11786
  const selections = readDirectorySelections(loaded);
11753
- const git = resolveGitBranch(realRunPort, cwd);
11787
+ const git = resolveGitBranch(run, cwd);
11754
11788
  const updateMode = resolveUpdateMode(loaded.globalConfig);
11755
11789
  return {
11756
11790
  runtime: {
@@ -11797,7 +11831,7 @@ function realPrepareLaunchParams(paths, options) {
11797
11831
  frontdoor: realFrontDoorPort(paths, options.spawnDaemon),
11798
11832
  credentials: { ...realCredentialPort, cache: realCredentialCacheEnv(paths) },
11799
11833
  hold: realHoldPort,
11800
- hasStoredLogin: (identity) => identitySignIn(realFarmFs, { platform: process.platform, run: realRunPort }, { farmRoot: import_node_path42.default.join(paths.identitiesDir, identity), hasCredentialBlock: false }).state !== "signed-out",
11834
+ hasStoredLogin: (identity) => identitySignIn(realFarmFs, { platform: process.platform, run: options.run ?? realRunPort }, { farmRoot: import_node_path42.default.join(paths.identitiesDir, identity), hasCredentialBlock: false }).state !== "signed-out",
11801
11835
  ...farm.directoryIdentity === void 0 ? {} : { directoryPinnedIdentity: farm.directoryIdentity },
11802
11836
  ...farm.directoryConfigProfile === void 0 ? {} : { directoryRuleConfigProfile: farm.directoryConfigProfile },
11803
11837
  ...farm.globalDefaultConfigProfile === void 0 ? {} : { globalDefaultConfigProfile: farm.globalDefaultConfigProfile },
@@ -11830,7 +11864,7 @@ function prepareClaudeLaunch(options) {
11830
11864
  const spawnDaemon = daemonSpawnerFor(options.agentShim);
11831
11865
  return prepareLaunch(realPrepareLaunchParams(paths, { proc, log, spawnDaemon, farm: buildFarmRuntime(paths, options.cwd) }));
11832
11866
  }
11833
- function resolveClaudeLaunch(options) {
11867
+ function resolveClaudeLaunch(options, run = realRunPort) {
11834
11868
  const paths = options.paths ?? resolveLayoutPaths();
11835
11869
  const refusals = [];
11836
11870
  const warnings = [];
@@ -11854,7 +11888,7 @@ function resolveClaudeLaunch(options) {
11854
11888
  const spawnDaemon = () => {
11855
11889
  throw new Error("resolving a launch starts no daemon");
11856
11890
  };
11857
- return { resolution: resolveLaunch(realPrepareLaunchParams(paths, { proc, log, spawnDaemon, farm: buildFarmRuntime(paths, options.cwd) })), warnings };
11891
+ return { resolution: resolveLaunch(realPrepareLaunchParams(paths, { proc, log, spawnDaemon, run, farm: buildFarmRuntime(paths, options.cwd, run) })), warnings };
11858
11892
  }
11859
11893
  var import_node_os7, import_node_path42, import_node_crypto13, LaunchRefusedError;
11860
11894
  var init_launchWiring = __esm({
@@ -11873,6 +11907,7 @@ var init_launchWiring = __esm({
11873
11907
  init_launcher();
11874
11908
  init_launchHook();
11875
11909
  init_cascade();
11910
+ init_replayRun();
11876
11911
  init_paths();
11877
11912
  init_signIn();
11878
11913
  init_realPorts();
@@ -18297,9 +18332,9 @@ function createLaunchApiRouter(deps) {
18297
18332
  // A POST because the launch's environment and arguments are a body, but the answer changes nothing.
18298
18333
  spec: (current) => ({ ...current, [READ_ONLY_OPERATION_EXTENSION]: true })
18299
18334
  })
18300
- ).input(LaunchResolveInputSchema).output(LaunchResolveOutputSchema).handler(({ input }) => {
18335
+ ).input(LaunchResolveInputSchema).output(LaunchResolveOutputSchema).handler(async ({ input }) => {
18301
18336
  try {
18302
- const { resolution, warnings } = deps.resolveLaunch({ path: input.path, argv: input.argv ?? [], env: input.env ?? {} });
18337
+ const { resolution, warnings } = await deps.resolveLaunch({ path: input.path, argv: input.argv ?? [], env: input.env ?? {} });
18303
18338
  return { ...resolution, warnings };
18304
18339
  } catch (error) {
18305
18340
  if (error instanceof CliError) {
package/dist/index.mjs CHANGED
@@ -176,8 +176,8 @@ var init_statusline = __esm({
176
176
  "use strict";
177
177
  init_blank();
178
178
  init_graphemes();
179
- STATUSLINE_HEADER_SEGMENTS = ["model", "provider", "route", "account", "identity", "headroom", "project", "vcs", "effort", "advisor", "version", "outputStyle"];
180
- STATUSLINE_ROWS = ["context", "quota", "addedDirs", "gitFiles"];
179
+ STATUSLINE_HEADER_SEGMENTS = ["model", "provider", "route", "account", "identity", "headroom", "project", "vcs", "effort", "advisor", "version", "outputStyle", "cost", "dailyCost"];
180
+ STATUSLINE_ROWS = ["context", "quota", "addedDirs", "gitFiles", "memory", "environment"];
181
181
  STATUSLINE_COLOUR_NAMES = [
182
182
  "default",
183
183
  "dim",
@@ -268,6 +268,12 @@ var init_statusline = __esm({
268
268
  hourCycle: z.enum(STATUSLINE_HOUR_CYCLES).describe("The hour cycle of a wall-clock time: `auto` follows the system locale, `h23` and `h24` are 24-hour time (`h24` writes midnight as 24:00), and `h12` and `h11` are 12-hour time with am or pm (`h11` writes the hour after midnight as 0)."),
269
269
  seconds: z.boolean().describe("Whether a wall-clock time includes seconds (`14:30:07`).")
270
270
  },
271
+ cost: {
272
+ routed: z.boolean().describe("Whether the cost segments draw for a session routed through a provider or a cloud platform's model id, where the client's own figure is not what was billed; the figure drawn is then priced from the door's usage log with `agent-shim model price`, else the client's own when it is above zero.")
273
+ },
274
+ environment: {
275
+ threshold: z.number().int().min(0).describe("The fewest configuration items in total (CLAUDE.md files, rules, MCP servers and hook events) that must exist for the environment row to draw its counts.")
276
+ },
271
277
  colours: {
272
278
  context: colourValue.describe("The colour of the context bar and its figures below the warning threshold."),
273
279
  usage: colourValue.describe("The colour of the quota bars and their figures below the warning threshold."),
@@ -312,6 +318,8 @@ var init_statusline = __esm({
312
318
  bar: z.strictObject(SHAPES.bar).partial().optional(),
313
319
  usage: z.strictObject(SHAPES.usage).partial().optional(),
314
320
  clock: z.strictObject(SHAPES.clock).partial().optional(),
321
+ cost: z.strictObject(SHAPES.cost).partial().optional(),
322
+ environment: z.strictObject(SHAPES.environment).partial().optional(),
315
323
  colours: z.strictObject(SHAPES.colours).partial().optional(),
316
324
  project: z.strictObject(SHAPES.project).partial().optional(),
317
325
  git: z.strictObject(SHAPES.git).partial().optional(),
@@ -329,6 +337,8 @@ var init_statusline = __esm({
329
337
  bar: z.strictObject(SHAPES.bar),
330
338
  usage: z.strictObject(SHAPES.usage),
331
339
  clock: z.strictObject(SHAPES.clock),
340
+ cost: z.strictObject(SHAPES.cost),
341
+ environment: z.strictObject(SHAPES.environment),
332
342
  colours: z.strictObject(SHAPES.colours),
333
343
  project: z.strictObject(SHAPES.project),
334
344
  git: z.strictObject(SHAPES.git),
@@ -346,6 +356,8 @@ var init_statusline = __esm({
346
356
  bar: { width: 10, filled: "\u2588", empty: "\u2591" },
347
357
  usage: { value: "used", bar: true, compact: false, resetLabel: false, modelScoped: false, timeFormat: "relative", threshold: 0, sevenDayThreshold: 0 },
348
358
  clock: { hourCycle: "auto", seconds: false },
359
+ cost: { routed: false },
360
+ environment: { threshold: 0 },
349
361
  colours: {
350
362
  context: "green",
351
363
  usage: "green",
@@ -4426,7 +4438,7 @@ var init_package = __esm({
4426
4438
  "package.json"() {
4427
4439
  package_default = {
4428
4440
  name: "claude-use",
4429
- version: "11.56.1",
4441
+ version: "11.57.1",
4430
4442
  description: "A profile manager and launcher for Claude Code that lets one person run multiple logins from one machine while controlling what gets shared between them.",
4431
4443
  license: "MIT",
4432
4444
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -4530,6 +4542,22 @@ var init_package = __esm({
4530
4542
  }
4531
4543
  });
4532
4544
 
4545
+ // src/blockingSpawn.ts
4546
+ import {
4547
+ execFileSync,
4548
+ spawnSync
4549
+ } from "node:child_process";
4550
+ function spawnSyncBlocking(operation, command, args, options) {
4551
+ refuseToBlockInRole(operation);
4552
+ return spawnSync(command, args, options ?? {});
4553
+ }
4554
+ var init_blockingSpawn = __esm({
4555
+ "src/blockingSpawn.ts"() {
4556
+ "use strict";
4557
+ init_processRole();
4558
+ }
4559
+ });
4560
+
4533
4561
  // src/frontdoor/supervisorProcesses.ts
4534
4562
  function parseFrontDoorSupervisorPids(psOutput) {
4535
4563
  const pids = [];
@@ -5661,7 +5689,7 @@ var init_logStyle = __esm({
5661
5689
  });
5662
5690
 
5663
5691
  // src/realPorts.ts
5664
- import { execFile, spawn as spawn2, spawnSync } from "node:child_process";
5692
+ import { execFile, spawn as spawn2 } from "node:child_process";
5665
5693
  import { createHash as createHash5 } from "node:crypto";
5666
5694
  import fs3 from "node:fs";
5667
5695
  import os3 from "node:os";
@@ -5686,27 +5714,23 @@ function realIsProcessAlive(pid) {
5686
5714
  }
5687
5715
  }
5688
5716
  function realIsProcessZombie(pid) {
5689
- refuseToBlockInRole("a synchronous process-table read");
5690
- const result = spawnSync("ps", ["-o", "stat=", "-p", String(pid)], { encoding: "utf8" });
5717
+ const result = spawnSyncBlocking("a process-table read", "ps", ["-o", "stat=", "-p", String(pid)], { encoding: "utf8" });
5691
5718
  return result.status === 0 && result.stdout.trim().startsWith("Z");
5692
5719
  }
5693
5720
  function realIsProcessRunning(pid) {
5694
5721
  return realIsProcessAlive(pid) && !realIsProcessZombie(pid);
5695
5722
  }
5696
5723
  function realIsFrontDoorSupervisor(pid) {
5697
- refuseToBlockInRole("a synchronous process-table read");
5698
- const result = spawnSync("ps", ["-o", "pid=,command=", "-p", String(pid)], { encoding: "utf8" });
5724
+ const result = spawnSyncBlocking("a process-table read", "ps", ["-o", "pid=,command=", "-p", String(pid)], { encoding: "utf8" });
5699
5725
  return result.status === 0 && parseFrontDoorSupervisorPids(result.stdout).includes(pid);
5700
5726
  }
5701
5727
  function realProcessCommandLine(pid) {
5702
- refuseToBlockInRole("a synchronous process-table read");
5703
- const result = spawnSync("ps", ["-o", "command=", "-p", String(pid)], { encoding: "utf8", timeout: PS_TIMEOUT_MS });
5728
+ const result = spawnSyncBlocking("a process-table read", "ps", ["-o", "command=", "-p", String(pid)], { encoding: "utf8", timeout: PS_TIMEOUT_MS });
5704
5729
  return result.status === 0 ? result.stdout.trim() : void 0;
5705
5730
  }
5706
5731
  function realFrontDoorLiveness(pids) {
5707
- refuseToBlockInRole("a synchronous process-table read");
5708
5732
  return frontDoorLivenessOf(pids, (asked) => {
5709
- const result = spawnSync("ps", ["-o", "pid=,stat=,command=", "-p", asked.map(String).join(",")], { encoding: "utf8", timeout: PS_TIMEOUT_MS });
5733
+ const result = spawnSyncBlocking("a process-table read", "ps", ["-o", "pid=,stat=,command=", "-p", asked.map(String).join(",")], { encoding: "utf8", timeout: PS_TIMEOUT_MS });
5710
5734
  return { status: result.status, stdout: result.stdout, stderr: result.stderr, ...result.error === void 0 ? {} : { error: result.error } };
5711
5735
  });
5712
5736
  }
@@ -5715,7 +5739,7 @@ function expandHome2(filePath) {
5715
5739
  }
5716
5740
  function hasDesktopSession() {
5717
5741
  if (process.platform === "darwin") {
5718
- const result = spawnSync("launchctl", ["managername"], { encoding: "utf8" });
5742
+ const result = spawnSyncBlocking("a desktop-session check", "launchctl", ["managername"], { encoding: "utf8" });
5719
5743
  return result.status === 0 && result.stdout.trim() === MACOS_GUI_SESSION_MANAGER;
5720
5744
  }
5721
5745
  return hasDisplayServer();
@@ -5915,6 +5939,7 @@ var realFsPort, OWNER_ONLY_DIR_MODE, OWNER_ONLY_FILE_MODE, PERMISSION_BITS, real
5915
5939
  var init_realPorts = __esm({
5916
5940
  "src/realPorts.ts"() {
5917
5941
  "use strict";
5942
+ init_blockingSpawn();
5918
5943
  init_processRole();
5919
5944
  init_load();
5920
5945
  init_versionDiscovery();
@@ -6082,7 +6107,7 @@ var init_realPorts = __esm({
6082
6107
  PS_TIMEOUT_MS = 2e3;
6083
6108
  realRunPort = {
6084
6109
  run(command, args) {
6085
- const result = spawnSync(command, [...args], { encoding: "utf8" });
6110
+ const result = spawnSyncBlocking("an external command", command, args, { encoding: "utf8" });
6086
6111
  return { status: result.status, stdout: result.stdout, stderr: result.stderr };
6087
6112
  }
6088
6113
  };
@@ -6105,7 +6130,7 @@ var init_realPorts = __esm({
6105
6130
  },
6106
6131
  runCommand(argv, options) {
6107
6132
  const [command, ...args] = argv;
6108
- const result = spawnSync(command, args, {
6133
+ const result = spawnSyncBlocking("a credential command", command, args, {
6109
6134
  encoding: "utf8",
6110
6135
  timeout: options.timeoutMs,
6111
6136
  stdio: options.interactive ? ["inherit", "pipe", "inherit"] : ["ignore", "pipe", "pipe"]
@@ -6144,7 +6169,7 @@ var init_realPorts = __esm({
6144
6169
  };
6145
6170
  realSpawnPort = {
6146
6171
  spawnSync(command, args, options) {
6147
- const result = spawnSync(command, args, options);
6172
+ const result = spawnSyncBlocking("a spawned program", command, args, options);
6148
6173
  return { status: result.status, signal: result.signal, ...result.error === void 0 ? {} : { error: result.error } };
6149
6174
  }
6150
6175
  };
@@ -6366,13 +6391,14 @@ var init_identity = __esm({
6366
6391
 
6367
6392
  // src/usage/schema.ts
6368
6393
  import { z as z11 } from "zod";
6369
- var USAGE_SCHEMA_VERSION, VersionSchema, InstantSchema, TokenCountSchema, TokenUsageSchema, LIMIT_KINDS, LimitClassificationSchema, UsageRecordSchema, QuotaWindowSchema, ExtraUsageSpendSchema, UnifiedRateLimitSchema, RateLimitStateSchema, LimitEventSchema, ProviderQuotaWindowSchema, ProviderAccountSchema, ProviderQuotaSchema, ProviderUsageStateSchema, AccountMetadataSchema, UsageSnapshotSchema;
6394
+ var USAGE_SCHEMA_VERSION, VersionSchema, InstantSchema, CLIENT_SESSION_ID_PATTERN, TokenCountSchema, TokenUsageSchema, LIMIT_KINDS, LimitClassificationSchema, UsageRecordSchema, QuotaWindowSchema, ExtraUsageSpendSchema, UnifiedRateLimitSchema, RateLimitStateSchema, LimitEventSchema, ProviderQuotaWindowSchema, ProviderAccountSchema, ProviderQuotaSchema, ProviderUsageStateSchema, AccountMetadataSchema, UsageSnapshotSchema;
6370
6395
  var init_schema2 = __esm({
6371
6396
  "src/usage/schema.ts"() {
6372
6397
  "use strict";
6373
6398
  USAGE_SCHEMA_VERSION = 1;
6374
6399
  VersionSchema = z11.literal(USAGE_SCHEMA_VERSION);
6375
6400
  InstantSchema = z11.iso.datetime();
6401
+ CLIENT_SESSION_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
6376
6402
  TokenCountSchema = z11.number().int().nonnegative();
6377
6403
  TokenUsageSchema = z11.strictObject({
6378
6404
  inputTokens: TokenCountSchema.optional(),
@@ -6402,6 +6428,8 @@ var init_schema2 = __esm({
6402
6428
  provider: z11.string(),
6403
6429
  /** The launch's session id, generated per launch. */
6404
6430
  sessionId: z11.string().optional(),
6431
+ /** The client's own id for the conversation, from the request's `x-claude-code-session-id` header: it changes when the conversation is cleared inside one launch, which `sessionId` does not, so it is what ties a request to the client's per-conversation figures. Absent when the client sent none. */
6432
+ clientSessionId: z11.string().regex(CLIENT_SESSION_ID_PATTERN).optional(),
6405
6433
  /** The project the launch ran in (its git repository root), when the launch sent one: headroom launches do. */
6406
6434
  project: z11.string().optional(),
6407
6435
  /** Whether the request crossed headroom on its way upstream. Absent on a record written before the door recorded it, and false when the request went direct. */
@@ -7959,6 +7987,7 @@ function buildLayoutPaths(root) {
7959
7987
  usageDir: path23.join(root, "usage"),
7960
7988
  usageLogDir: path23.join(root, "usage", "log"),
7961
7989
  usageSnapshotsDir: path23.join(root, "usage", "snapshots"),
7990
+ statuslineDir: path23.join(root, "statusline"),
7962
7991
  catalogueDir: path23.join(root, "catalogues"),
7963
7992
  usagePicksFile: path23.join(root, "usage", "picks.json"),
7964
7993
  usageAnchorsFile: path23.join(root, "usage", "anchors.json"),
@@ -8056,7 +8085,6 @@ var init_credentialCache = __esm({
8056
8085
  });
8057
8086
 
8058
8087
  // src/realCredentialCache.ts
8059
- import { spawn as spawn3, spawnSync as spawnSync2 } from "node:child_process";
8060
8088
  import fs6 from "node:fs";
8061
8089
  import path24 from "node:path";
8062
8090
  function cacheFileNameFor(owner) {
@@ -8078,7 +8106,7 @@ function requireKeychain() {
8078
8106
  }
8079
8107
  }
8080
8108
  function security(args, stdin) {
8081
- const result = spawnSync2("security", args, { encoding: "utf8", ...stdin === void 0 ? {} : { input: stdin }, stdio: ["pipe", "pipe", "ignore"] });
8109
+ const result = spawnSyncBlocking("a keychain call", "security", args, { encoding: "utf8", ...stdin === void 0 ? {} : { input: stdin }, stdio: ["pipe", "pipe", "ignore"] });
8082
8110
  return { status: result.status, stdout: result.stdout };
8083
8111
  }
8084
8112
  function createRealCredentialCache(root) {
@@ -8133,6 +8161,7 @@ var KEYCHAIN_CACHE_SERVICE, CACHE_DIR_MODE, CACHE_FILE_MODE;
8133
8161
  var init_realCredentialCache = __esm({
8134
8162
  "src/realCredentialCache.ts"() {
8135
8163
  "use strict";
8164
+ init_blockingSpawn();
8136
8165
  init_credentialCache();
8137
8166
  KEYCHAIN_CACHE_SERVICE = "agent-shim-credential-cache";
8138
8167
  CACHE_DIR_MODE = 448;
@@ -11501,13 +11530,13 @@ function resolveLaunch(params) {
11501
11530
  environment
11502
11531
  };
11503
11532
  }
11504
- function runLaunchPlan(plan, spawn4) {
11533
+ function runLaunchPlan(plan, spawn3) {
11505
11534
  try {
11506
11535
  if (plan.hold() === "cancelled") {
11507
11536
  return LAUNCH_CANCELLED_EXIT;
11508
11537
  }
11509
11538
  plan.markChildStarted();
11510
- const result = spawn4.spawnSync(plan.bin, plan.args, { stdio: "inherit", env: plan.env });
11539
+ const result = spawn3.spawnSync(plan.bin, plan.args, { stdio: "inherit", env: plan.env });
11511
11540
  if (result.error !== void 0) {
11512
11541
  throw result.error;
11513
11542
  }
@@ -11712,17 +11741,24 @@ var init_realFrontDoorPort = __esm({
11712
11741
  }
11713
11742
  });
11714
11743
 
11744
+ // src/replayRun.ts
11745
+ var init_replayRun = __esm({
11746
+ "src/replayRun.ts"() {
11747
+ "use strict";
11748
+ }
11749
+ });
11750
+
11715
11751
  // src/launchWiring.ts
11716
11752
  import os8 from "node:os";
11717
11753
  import path42 from "node:path";
11718
11754
  import { randomUUID as randomUUID5 } from "node:crypto";
11719
- function buildFarmRuntime(paths, cwd) {
11755
+ function buildFarmRuntime(paths, cwd, run = realRunPort) {
11720
11756
  const home = os8.homedir();
11721
11757
  const read = cosmiconfigReader();
11722
11758
  const classification = loadClassification(paths);
11723
11759
  const loaded = loadCascadeInput({ paths, home, cwd, read });
11724
11760
  const selections = readDirectorySelections(loaded);
11725
- const git = resolveGitBranch(realRunPort, cwd);
11761
+ const git = resolveGitBranch(run, cwd);
11726
11762
  const updateMode = resolveUpdateMode(loaded.globalConfig);
11727
11763
  return {
11728
11764
  runtime: {
@@ -11769,7 +11805,7 @@ function realPrepareLaunchParams(paths, options) {
11769
11805
  frontdoor: realFrontDoorPort(paths, options.spawnDaemon),
11770
11806
  credentials: { ...realCredentialPort, cache: realCredentialCacheEnv(paths) },
11771
11807
  hold: realHoldPort,
11772
- hasStoredLogin: (identity) => identitySignIn(realFarmFs, { platform: process.platform, run: realRunPort }, { farmRoot: path42.join(paths.identitiesDir, identity), hasCredentialBlock: false }).state !== "signed-out",
11808
+ hasStoredLogin: (identity) => identitySignIn(realFarmFs, { platform: process.platform, run: options.run ?? realRunPort }, { farmRoot: path42.join(paths.identitiesDir, identity), hasCredentialBlock: false }).state !== "signed-out",
11773
11809
  ...farm.directoryIdentity === void 0 ? {} : { directoryPinnedIdentity: farm.directoryIdentity },
11774
11810
  ...farm.directoryConfigProfile === void 0 ? {} : { directoryRuleConfigProfile: farm.directoryConfigProfile },
11775
11811
  ...farm.globalDefaultConfigProfile === void 0 ? {} : { globalDefaultConfigProfile: farm.globalDefaultConfigProfile },
@@ -11802,7 +11838,7 @@ function prepareClaudeLaunch(options) {
11802
11838
  const spawnDaemon = daemonSpawnerFor(options.agentShim);
11803
11839
  return prepareLaunch(realPrepareLaunchParams(paths, { proc, log, spawnDaemon, farm: buildFarmRuntime(paths, options.cwd) }));
11804
11840
  }
11805
- function resolveClaudeLaunch(options) {
11841
+ function resolveClaudeLaunch(options, run = realRunPort) {
11806
11842
  const paths = options.paths ?? resolveLayoutPaths();
11807
11843
  const refusals = [];
11808
11844
  const warnings = [];
@@ -11826,7 +11862,7 @@ function resolveClaudeLaunch(options) {
11826
11862
  const spawnDaemon = () => {
11827
11863
  throw new Error("resolving a launch starts no daemon");
11828
11864
  };
11829
- return { resolution: resolveLaunch(realPrepareLaunchParams(paths, { proc, log, spawnDaemon, farm: buildFarmRuntime(paths, options.cwd) })), warnings };
11865
+ return { resolution: resolveLaunch(realPrepareLaunchParams(paths, { proc, log, spawnDaemon, run, farm: buildFarmRuntime(paths, options.cwd, run) })), warnings };
11830
11866
  }
11831
11867
  var LaunchRefusedError;
11832
11868
  var init_launchWiring = __esm({
@@ -11842,6 +11878,7 @@ var init_launchWiring = __esm({
11842
11878
  init_launcher();
11843
11879
  init_launchHook();
11844
11880
  init_cascade();
11881
+ init_replayRun();
11845
11882
  init_paths();
11846
11883
  init_signIn();
11847
11884
  init_realPorts();
@@ -17882,9 +17919,9 @@ function createLaunchApiRouter(deps) {
17882
17919
  // A POST because the launch's environment and arguments are a body, but the answer changes nothing.
17883
17920
  spec: (current) => ({ ...current, [READ_ONLY_OPERATION_EXTENSION]: true })
17884
17921
  })
17885
- ).input(LaunchResolveInputSchema).output(LaunchResolveOutputSchema).handler(({ input }) => {
17922
+ ).input(LaunchResolveInputSchema).output(LaunchResolveOutputSchema).handler(async ({ input }) => {
17886
17923
  try {
17887
- const { resolution, warnings } = deps.resolveLaunch({ path: input.path, argv: input.argv ?? [], env: input.env ?? {} });
17924
+ const { resolution, warnings } = await deps.resolveLaunch({ path: input.path, argv: input.argv ?? [], env: input.env ?? {} });
17888
17925
  return { ...resolution, warnings };
17889
17926
  } catch (error) {
17890
17927
  if (error instanceof CliError) {