claude-use 11.57.0 → 11.58.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -190,7 +190,7 @@ function resolveStatusline(settings) {
190
190
  }
191
191
  return resolved;
192
192
  }
193
- var import_string_width2, import_zod, STATUSLINE_HEADER_SEGMENTS, STATUSLINE_ROWS, STATUSLINE_COLOUR_NAMES, DEFAULT_HEADER_SEGMENTS, DEFAULT_ROWS, STATUSLINE_PATH_LEVELS, STATUSLINE_USAGE_VALUES, STATUSLINE_TIME_FORMATS, STATUSLINE_HOUR_CYCLES, MAX_PERCENT, MAX_STATUSLINE_PALETTE_INDEX, MAX_STATUSLINE_LABEL_COLUMNS, MAX_BAR_CELLS, MAX_ACCOUNT_USER_CHARS, MAX_DISPLAY_TEXT_CHARS, LABEL_RE2, OPTIONAL_LABEL_RE, colourValue, barCharacter, labelText, overrideText, wholePercent, thresholdPercent, SHAPES, StatuslineSchema, ResolvedStatuslineSchema, STATUSLINE_DEFAULTS, STATUSLINE_ENV;
193
+ var import_string_width2, import_zod, STATUSLINE_HEADER_SEGMENTS, STATUSLINE_ROWS, STATUSLINE_SESSION_TIME_PARTS, PROMPT_CACHE_TTL_SECONDS, STATUSLINE_COLOUR_NAMES, DEFAULT_HEADER_SEGMENTS, DEFAULT_ROWS, STATUSLINE_PATH_LEVELS, STATUSLINE_USAGE_VALUES, STATUSLINE_TIME_FORMATS, STATUSLINE_HOUR_CYCLES, MAX_PERCENT, MAX_STATUSLINE_PALETTE_INDEX, MAX_STATUSLINE_LABEL_COLUMNS, MAX_BAR_CELLS, MAX_ACCOUNT_USER_CHARS, MAX_DISPLAY_TEXT_CHARS, LABEL_RE2, OPTIONAL_LABEL_RE, colourValue, barCharacter, labelText, overrideText, wholePercent, thresholdPercent, SHAPES, StatuslineSchema, ResolvedStatuslineSchema, STATUSLINE_DEFAULTS, STATUSLINE_ENV;
194
194
  var init_statusline = __esm({
195
195
  "src/config/statusline.ts"() {
196
196
  "use strict";
@@ -198,8 +198,10 @@ 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", "cost", "dailyCost"];
202
- STATUSLINE_ROWS = ["context", "quota", "addedDirs", "gitFiles", "memory", "environment"];
201
+ STATUSLINE_HEADER_SEGMENTS = ["model", "provider", "route", "account", "identity", "headroom", "project", "vcs", "effort", "advisor", "version", "outputStyle", "cost", "dailyCost", "sessionName", "duration", "speed"];
202
+ STATUSLINE_ROWS = ["context", "quota", "addedDirs", "gitFiles", "memory", "environment", "sessionTime", "promptCache", "compactions"];
203
+ STATUSLINE_SESSION_TIME_PARTS = ["started", "lastReply"];
204
+ PROMPT_CACHE_TTL_SECONDS = { fiveMinutes: 300, oneHour: 3600 };
203
205
  STATUSLINE_COLOUR_NAMES = [
204
206
  "default",
205
207
  "dim",
@@ -296,6 +298,12 @@ var init_statusline = __esm({
296
298
  environment: {
297
299
  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
300
  },
301
+ sessionTime: {
302
+ parts: distinctList(import_zod.z.enum(STATUSLINE_SESSION_TIME_PARTS)).describe("The parts of the sessionTime row to draw, in drawing order: when the session started, and how long ago the last response was written; a part left out is hidden, and an empty list hides the row.")
303
+ },
304
+ promptCache: {
305
+ ttlSeconds: import_zod.z.number().int().min(1).describe("How long the prompt cache lives, in seconds, when the transcript has not yet shown which tier the session writes (five minutes or one hour); the tier the transcript shows takes over once it does.")
306
+ },
299
307
  colours: {
300
308
  context: colourValue.describe("The colour of the context bar and its figures below the warning threshold."),
301
309
  usage: colourValue.describe("The colour of the quota bars and their figures below the warning threshold."),
@@ -342,6 +350,8 @@ var init_statusline = __esm({
342
350
  clock: import_zod.z.strictObject(SHAPES.clock).partial().optional(),
343
351
  cost: import_zod.z.strictObject(SHAPES.cost).partial().optional(),
344
352
  environment: import_zod.z.strictObject(SHAPES.environment).partial().optional(),
353
+ sessionTime: import_zod.z.strictObject(SHAPES.sessionTime).partial().optional(),
354
+ promptCache: import_zod.z.strictObject(SHAPES.promptCache).partial().optional(),
345
355
  colours: import_zod.z.strictObject(SHAPES.colours).partial().optional(),
346
356
  project: import_zod.z.strictObject(SHAPES.project).partial().optional(),
347
357
  git: import_zod.z.strictObject(SHAPES.git).partial().optional(),
@@ -361,6 +371,8 @@ var init_statusline = __esm({
361
371
  clock: import_zod.z.strictObject(SHAPES.clock),
362
372
  cost: import_zod.z.strictObject(SHAPES.cost),
363
373
  environment: import_zod.z.strictObject(SHAPES.environment),
374
+ sessionTime: import_zod.z.strictObject(SHAPES.sessionTime),
375
+ promptCache: import_zod.z.strictObject(SHAPES.promptCache),
364
376
  colours: import_zod.z.strictObject(SHAPES.colours),
365
377
  project: import_zod.z.strictObject(SHAPES.project),
366
378
  git: import_zod.z.strictObject(SHAPES.git),
@@ -380,6 +392,8 @@ var init_statusline = __esm({
380
392
  clock: { hourCycle: "auto", seconds: false },
381
393
  cost: { routed: false },
382
394
  environment: { threshold: 0 },
395
+ sessionTime: { parts: [...STATUSLINE_SESSION_TIME_PARTS] },
396
+ promptCache: { ttlSeconds: PROMPT_CACHE_TTL_SECONDS.fiveMinutes },
383
397
  colours: {
384
398
  context: "green",
385
399
  usage: "green",
@@ -4462,7 +4476,7 @@ var init_package = __esm({
4462
4476
  "package.json"() {
4463
4477
  package_default = {
4464
4478
  name: "claude-use",
4465
- version: "11.57.0",
4479
+ version: "11.58.0",
4466
4480
  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.",
4467
4481
  license: "MIT",
4468
4482
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -4566,6 +4580,20 @@ var init_package = __esm({
4566
4580
  }
4567
4581
  });
4568
4582
 
4583
+ // src/blockingSpawn.ts
4584
+ function spawnSyncBlocking(operation, command, args, options) {
4585
+ refuseToBlockInRole(operation);
4586
+ return (0, import_node_child_process2.spawnSync)(command, args, options ?? {});
4587
+ }
4588
+ var import_node_child_process2;
4589
+ var init_blockingSpawn = __esm({
4590
+ "src/blockingSpawn.ts"() {
4591
+ "use strict";
4592
+ import_node_child_process2 = require("node:child_process");
4593
+ init_processRole();
4594
+ }
4595
+ });
4596
+
4569
4597
  // src/frontdoor/supervisorProcesses.ts
4570
4598
  function parseFrontDoorSupervisorPids(psOutput) {
4571
4599
  const pids = [];
@@ -5717,27 +5745,23 @@ function realIsProcessAlive(pid) {
5717
5745
  }
5718
5746
  }
5719
5747
  function realIsProcessZombie(pid) {
5720
- refuseToBlockInRole("a synchronous process-table read");
5721
- const result = (0, import_node_child_process2.spawnSync)("ps", ["-o", "stat=", "-p", String(pid)], { encoding: "utf8" });
5748
+ const result = spawnSyncBlocking("a process-table read", "ps", ["-o", "stat=", "-p", String(pid)], { encoding: "utf8" });
5722
5749
  return result.status === 0 && result.stdout.trim().startsWith("Z");
5723
5750
  }
5724
5751
  function realIsProcessRunning(pid) {
5725
5752
  return realIsProcessAlive(pid) && !realIsProcessZombie(pid);
5726
5753
  }
5727
5754
  function realIsFrontDoorSupervisor(pid) {
5728
- refuseToBlockInRole("a synchronous process-table read");
5729
- const result = (0, import_node_child_process2.spawnSync)("ps", ["-o", "pid=,command=", "-p", String(pid)], { encoding: "utf8" });
5755
+ const result = spawnSyncBlocking("a process-table read", "ps", ["-o", "pid=,command=", "-p", String(pid)], { encoding: "utf8" });
5730
5756
  return result.status === 0 && parseFrontDoorSupervisorPids(result.stdout).includes(pid);
5731
5757
  }
5732
5758
  function realProcessCommandLine(pid) {
5733
- refuseToBlockInRole("a synchronous process-table read");
5734
- const result = (0, import_node_child_process2.spawnSync)("ps", ["-o", "command=", "-p", String(pid)], { encoding: "utf8", timeout: PS_TIMEOUT_MS });
5759
+ const result = spawnSyncBlocking("a process-table read", "ps", ["-o", "command=", "-p", String(pid)], { encoding: "utf8", timeout: PS_TIMEOUT_MS });
5735
5760
  return result.status === 0 ? result.stdout.trim() : void 0;
5736
5761
  }
5737
5762
  function realFrontDoorLiveness(pids) {
5738
- refuseToBlockInRole("a synchronous process-table read");
5739
5763
  return frontDoorLivenessOf(pids, (asked) => {
5740
- const result = (0, import_node_child_process2.spawnSync)("ps", ["-o", "pid=,stat=,command=", "-p", asked.map(String).join(",")], { encoding: "utf8", timeout: PS_TIMEOUT_MS });
5764
+ const result = spawnSyncBlocking("a process-table read", "ps", ["-o", "pid=,stat=,command=", "-p", asked.map(String).join(",")], { encoding: "utf8", timeout: PS_TIMEOUT_MS });
5741
5765
  return { status: result.status, stdout: result.stdout, stderr: result.stderr, ...result.error === void 0 ? {} : { error: result.error } };
5742
5766
  });
5743
5767
  }
@@ -5746,7 +5770,7 @@ function expandHome2(filePath) {
5746
5770
  }
5747
5771
  function hasDesktopSession() {
5748
5772
  if (process.platform === "darwin") {
5749
- const result = (0, import_node_child_process2.spawnSync)("launchctl", ["managername"], { encoding: "utf8" });
5773
+ const result = spawnSyncBlocking("a desktop-session check", "launchctl", ["managername"], { encoding: "utf8" });
5750
5774
  return result.status === 0 && result.stdout.trim() === MACOS_GUI_SESSION_MANAGER;
5751
5775
  }
5752
5776
  return hasDisplayServer();
@@ -5792,7 +5816,7 @@ function spawnDetachedDaemon(invocation, paths, subcommand, logPath) {
5792
5816
  import_node_fs2.default.mkdirSync(import_node_path14.default.dirname(logPath), { recursive: true });
5793
5817
  const logFd = import_node_fs2.default.openSync(logPath, "a");
5794
5818
  try {
5795
- const child = (0, import_node_child_process2.spawn)(invocation.command, invocation.args, detachedDaemonSpawnOptions(logFd, { ...process.env, AGENT_SHIM_HOME: paths.root }));
5819
+ const child = (0, import_node_child_process3.spawn)(invocation.command, invocation.args, detachedDaemonSpawnOptions(logFd, { ...process.env, AGENT_SHIM_HOME: paths.root }));
5796
5820
  child.unref();
5797
5821
  if (child.pid === void 0) {
5798
5822
  throw new Error(`spawning ${subcommand} returned no pid`);
@@ -5942,12 +5966,13 @@ function realResolveClaudeBinary(isOwnBinary) {
5942
5966
  function realInstalledClaudeVersions() {
5943
5967
  return installedVersions(listVersionsDir(defaultVersionsDir()));
5944
5968
  }
5945
- 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;
5969
+ 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;
5946
5970
  var init_realPorts = __esm({
5947
5971
  "src/realPorts.ts"() {
5948
5972
  "use strict";
5973
+ init_blockingSpawn();
5949
5974
  init_processRole();
5950
- import_node_child_process2 = require("node:child_process");
5975
+ import_node_child_process3 = require("node:child_process");
5951
5976
  import_node_crypto8 = require("node:crypto");
5952
5977
  import_node_fs2 = __toESM(require("node:fs"), 1);
5953
5978
  import_node_os2 = __toESM(require("node:os"), 1);
@@ -6119,7 +6144,7 @@ var init_realPorts = __esm({
6119
6144
  PS_TIMEOUT_MS = 2e3;
6120
6145
  realRunPort = {
6121
6146
  run(command, args) {
6122
- const result = (0, import_node_child_process2.spawnSync)(command, [...args], { encoding: "utf8" });
6147
+ const result = spawnSyncBlocking("an external command", command, args, { encoding: "utf8" });
6123
6148
  return { status: result.status, stdout: result.stdout, stderr: result.stderr };
6124
6149
  }
6125
6150
  };
@@ -6142,7 +6167,7 @@ var init_realPorts = __esm({
6142
6167
  },
6143
6168
  runCommand(argv, options) {
6144
6169
  const [command, ...args] = argv;
6145
- const result = (0, import_node_child_process2.spawnSync)(command, args, {
6170
+ const result = spawnSyncBlocking("a credential command", command, args, {
6146
6171
  encoding: "utf8",
6147
6172
  timeout: options.timeoutMs,
6148
6173
  stdio: options.interactive ? ["inherit", "pipe", "inherit"] : ["ignore", "pipe", "pipe"]
@@ -6181,7 +6206,7 @@ var init_realPorts = __esm({
6181
6206
  };
6182
6207
  realSpawnPort = {
6183
6208
  spawnSync(command, args, options) {
6184
- const result = (0, import_node_child_process2.spawnSync)(command, args, options);
6209
+ const result = spawnSyncBlocking("a spawned program", command, args, options);
6185
6210
  return { status: result.status, signal: result.signal, ...result.error === void 0 ? {} : { error: result.error } };
6186
6211
  }
6187
6212
  };
@@ -8119,7 +8144,7 @@ function requireKeychain() {
8119
8144
  }
8120
8145
  }
8121
8146
  function security(args, stdin) {
8122
- const result = (0, import_node_child_process3.spawnSync)("security", args, { encoding: "utf8", ...stdin === void 0 ? {} : { input: stdin }, stdio: ["pipe", "pipe", "ignore"] });
8147
+ const result = spawnSyncBlocking("a keychain call", "security", args, { encoding: "utf8", ...stdin === void 0 ? {} : { input: stdin }, stdio: ["pipe", "pipe", "ignore"] });
8123
8148
  return { status: result.status, stdout: result.stdout };
8124
8149
  }
8125
8150
  function createRealCredentialCache(root) {
@@ -8170,13 +8195,13 @@ function createRealCredentialCache(root) {
8170
8195
  function realCredentialCacheEnv(paths) {
8171
8196
  return { port: createRealCredentialCache(paths.root), platform: process.platform, now: () => Date.now() };
8172
8197
  }
8173
- var import_node_child_process3, import_node_fs5, import_node_path24, KEYCHAIN_CACHE_SERVICE, CACHE_DIR_MODE, CACHE_FILE_MODE;
8198
+ var import_node_fs5, import_node_path24, KEYCHAIN_CACHE_SERVICE, CACHE_DIR_MODE, CACHE_FILE_MODE;
8174
8199
  var init_realCredentialCache = __esm({
8175
8200
  "src/realCredentialCache.ts"() {
8176
8201
  "use strict";
8177
- import_node_child_process3 = require("node:child_process");
8178
8202
  import_node_fs5 = __toESM(require("node:fs"), 1);
8179
8203
  import_node_path24 = __toESM(require("node:path"), 1);
8204
+ init_blockingSpawn();
8180
8205
  init_credentialCache();
8181
8206
  KEYCHAIN_CACHE_SERVICE = "agent-shim-credential-cache";
8182
8207
  CACHE_DIR_MODE = 448;
@@ -11543,13 +11568,13 @@ function resolveLaunch(params) {
11543
11568
  environment
11544
11569
  };
11545
11570
  }
11546
- function runLaunchPlan(plan, spawn4) {
11571
+ function runLaunchPlan(plan, spawn3) {
11547
11572
  try {
11548
11573
  if (plan.hold() === "cancelled") {
11549
11574
  return LAUNCH_CANCELLED_EXIT;
11550
11575
  }
11551
11576
  plan.markChildStarted();
11552
- const result = spawn4.spawnSync(plan.bin, plan.args, { stdio: "inherit", env: plan.env });
11577
+ const result = spawn3.spawnSync(plan.bin, plan.args, { stdio: "inherit", env: plan.env });
11553
11578
  if (result.error !== void 0) {
11554
11579
  throw result.error;
11555
11580
  }
@@ -11759,14 +11784,21 @@ var init_realFrontDoorPort = __esm({
11759
11784
  }
11760
11785
  });
11761
11786
 
11787
+ // src/replayRun.ts
11788
+ var init_replayRun = __esm({
11789
+ "src/replayRun.ts"() {
11790
+ "use strict";
11791
+ }
11792
+ });
11793
+
11762
11794
  // src/launchWiring.ts
11763
- function buildFarmRuntime(paths, cwd) {
11795
+ function buildFarmRuntime(paths, cwd, run = realRunPort) {
11764
11796
  const home = import_node_os7.default.homedir();
11765
11797
  const read = cosmiconfigReader();
11766
11798
  const classification = loadClassification(paths);
11767
11799
  const loaded = loadCascadeInput({ paths, home, cwd, read });
11768
11800
  const selections = readDirectorySelections(loaded);
11769
- const git = resolveGitBranch(realRunPort, cwd);
11801
+ const git = resolveGitBranch(run, cwd);
11770
11802
  const updateMode = resolveUpdateMode(loaded.globalConfig);
11771
11803
  return {
11772
11804
  runtime: {
@@ -11813,7 +11845,7 @@ function realPrepareLaunchParams(paths, options) {
11813
11845
  frontdoor: realFrontDoorPort(paths, options.spawnDaemon),
11814
11846
  credentials: { ...realCredentialPort, cache: realCredentialCacheEnv(paths) },
11815
11847
  hold: realHoldPort,
11816
- hasStoredLogin: (identity) => identitySignIn(realFarmFs, { platform: process.platform, run: realRunPort }, { farmRoot: import_node_path42.default.join(paths.identitiesDir, identity), hasCredentialBlock: false }).state !== "signed-out",
11848
+ 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",
11817
11849
  ...farm.directoryIdentity === void 0 ? {} : { directoryPinnedIdentity: farm.directoryIdentity },
11818
11850
  ...farm.directoryConfigProfile === void 0 ? {} : { directoryRuleConfigProfile: farm.directoryConfigProfile },
11819
11851
  ...farm.globalDefaultConfigProfile === void 0 ? {} : { globalDefaultConfigProfile: farm.globalDefaultConfigProfile },
@@ -11846,7 +11878,7 @@ function prepareClaudeLaunch(options) {
11846
11878
  const spawnDaemon = daemonSpawnerFor(options.agentShim);
11847
11879
  return prepareLaunch(realPrepareLaunchParams(paths, { proc, log, spawnDaemon, farm: buildFarmRuntime(paths, options.cwd) }));
11848
11880
  }
11849
- function resolveClaudeLaunch(options) {
11881
+ function resolveClaudeLaunch(options, run = realRunPort) {
11850
11882
  const paths = options.paths ?? resolveLayoutPaths();
11851
11883
  const refusals = [];
11852
11884
  const warnings = [];
@@ -11870,7 +11902,7 @@ function resolveClaudeLaunch(options) {
11870
11902
  const spawnDaemon = () => {
11871
11903
  throw new Error("resolving a launch starts no daemon");
11872
11904
  };
11873
- return { resolution: resolveLaunch(realPrepareLaunchParams(paths, { proc, log, spawnDaemon, farm: buildFarmRuntime(paths, options.cwd) })), warnings };
11905
+ return { resolution: resolveLaunch(realPrepareLaunchParams(paths, { proc, log, spawnDaemon, run, farm: buildFarmRuntime(paths, options.cwd, run) })), warnings };
11874
11906
  }
11875
11907
  var import_node_os7, import_node_path42, import_node_crypto13, LaunchRefusedError;
11876
11908
  var init_launchWiring = __esm({
@@ -11889,6 +11921,7 @@ var init_launchWiring = __esm({
11889
11921
  init_launcher();
11890
11922
  init_launchHook();
11891
11923
  init_cascade();
11924
+ init_replayRun();
11892
11925
  init_paths();
11893
11926
  init_signIn();
11894
11927
  init_realPorts();
@@ -18313,9 +18346,9 @@ function createLaunchApiRouter(deps) {
18313
18346
  // A POST because the launch's environment and arguments are a body, but the answer changes nothing.
18314
18347
  spec: (current) => ({ ...current, [READ_ONLY_OPERATION_EXTENSION]: true })
18315
18348
  })
18316
- ).input(LaunchResolveInputSchema).output(LaunchResolveOutputSchema).handler(({ input }) => {
18349
+ ).input(LaunchResolveInputSchema).output(LaunchResolveOutputSchema).handler(async ({ input }) => {
18317
18350
  try {
18318
- const { resolution, warnings } = deps.resolveLaunch({ path: input.path, argv: input.argv ?? [], env: input.env ?? {} });
18351
+ const { resolution, warnings } = await deps.resolveLaunch({ path: input.path, argv: input.argv ?? [], env: input.env ?? {} });
18319
18352
  return { ...resolution, warnings };
18320
18353
  } catch (error) {
18321
18354
  if (error instanceof CliError) {
package/dist/index.mjs CHANGED
@@ -170,14 +170,16 @@ function resolveStatusline(settings) {
170
170
  }
171
171
  return resolved;
172
172
  }
173
- var STATUSLINE_HEADER_SEGMENTS, STATUSLINE_ROWS, STATUSLINE_COLOUR_NAMES, DEFAULT_HEADER_SEGMENTS, DEFAULT_ROWS, STATUSLINE_PATH_LEVELS, STATUSLINE_USAGE_VALUES, STATUSLINE_TIME_FORMATS, STATUSLINE_HOUR_CYCLES, MAX_PERCENT, MAX_STATUSLINE_PALETTE_INDEX, MAX_STATUSLINE_LABEL_COLUMNS, MAX_BAR_CELLS, MAX_ACCOUNT_USER_CHARS, MAX_DISPLAY_TEXT_CHARS, LABEL_RE2, OPTIONAL_LABEL_RE, colourValue, barCharacter, labelText, overrideText, wholePercent, thresholdPercent, SHAPES, StatuslineSchema, ResolvedStatuslineSchema, STATUSLINE_DEFAULTS, STATUSLINE_ENV;
173
+ var STATUSLINE_HEADER_SEGMENTS, STATUSLINE_ROWS, STATUSLINE_SESSION_TIME_PARTS, PROMPT_CACHE_TTL_SECONDS, STATUSLINE_COLOUR_NAMES, DEFAULT_HEADER_SEGMENTS, DEFAULT_ROWS, STATUSLINE_PATH_LEVELS, STATUSLINE_USAGE_VALUES, STATUSLINE_TIME_FORMATS, STATUSLINE_HOUR_CYCLES, MAX_PERCENT, MAX_STATUSLINE_PALETTE_INDEX, MAX_STATUSLINE_LABEL_COLUMNS, MAX_BAR_CELLS, MAX_ACCOUNT_USER_CHARS, MAX_DISPLAY_TEXT_CHARS, LABEL_RE2, OPTIONAL_LABEL_RE, colourValue, barCharacter, labelText, overrideText, wholePercent, thresholdPercent, SHAPES, StatuslineSchema, ResolvedStatuslineSchema, STATUSLINE_DEFAULTS, STATUSLINE_ENV;
174
174
  var init_statusline = __esm({
175
175
  "src/config/statusline.ts"() {
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", "cost", "dailyCost"];
180
- STATUSLINE_ROWS = ["context", "quota", "addedDirs", "gitFiles", "memory", "environment"];
179
+ STATUSLINE_HEADER_SEGMENTS = ["model", "provider", "route", "account", "identity", "headroom", "project", "vcs", "effort", "advisor", "version", "outputStyle", "cost", "dailyCost", "sessionName", "duration", "speed"];
180
+ STATUSLINE_ROWS = ["context", "quota", "addedDirs", "gitFiles", "memory", "environment", "sessionTime", "promptCache", "compactions"];
181
+ STATUSLINE_SESSION_TIME_PARTS = ["started", "lastReply"];
182
+ PROMPT_CACHE_TTL_SECONDS = { fiveMinutes: 300, oneHour: 3600 };
181
183
  STATUSLINE_COLOUR_NAMES = [
182
184
  "default",
183
185
  "dim",
@@ -274,6 +276,12 @@ var init_statusline = __esm({
274
276
  environment: {
275
277
  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
278
  },
279
+ sessionTime: {
280
+ parts: distinctList(z.enum(STATUSLINE_SESSION_TIME_PARTS)).describe("The parts of the sessionTime row to draw, in drawing order: when the session started, and how long ago the last response was written; a part left out is hidden, and an empty list hides the row.")
281
+ },
282
+ promptCache: {
283
+ ttlSeconds: z.number().int().min(1).describe("How long the prompt cache lives, in seconds, when the transcript has not yet shown which tier the session writes (five minutes or one hour); the tier the transcript shows takes over once it does.")
284
+ },
277
285
  colours: {
278
286
  context: colourValue.describe("The colour of the context bar and its figures below the warning threshold."),
279
287
  usage: colourValue.describe("The colour of the quota bars and their figures below the warning threshold."),
@@ -320,6 +328,8 @@ var init_statusline = __esm({
320
328
  clock: z.strictObject(SHAPES.clock).partial().optional(),
321
329
  cost: z.strictObject(SHAPES.cost).partial().optional(),
322
330
  environment: z.strictObject(SHAPES.environment).partial().optional(),
331
+ sessionTime: z.strictObject(SHAPES.sessionTime).partial().optional(),
332
+ promptCache: z.strictObject(SHAPES.promptCache).partial().optional(),
323
333
  colours: z.strictObject(SHAPES.colours).partial().optional(),
324
334
  project: z.strictObject(SHAPES.project).partial().optional(),
325
335
  git: z.strictObject(SHAPES.git).partial().optional(),
@@ -339,6 +349,8 @@ var init_statusline = __esm({
339
349
  clock: z.strictObject(SHAPES.clock),
340
350
  cost: z.strictObject(SHAPES.cost),
341
351
  environment: z.strictObject(SHAPES.environment),
352
+ sessionTime: z.strictObject(SHAPES.sessionTime),
353
+ promptCache: z.strictObject(SHAPES.promptCache),
342
354
  colours: z.strictObject(SHAPES.colours),
343
355
  project: z.strictObject(SHAPES.project),
344
356
  git: z.strictObject(SHAPES.git),
@@ -358,6 +370,8 @@ var init_statusline = __esm({
358
370
  clock: { hourCycle: "auto", seconds: false },
359
371
  cost: { routed: false },
360
372
  environment: { threshold: 0 },
373
+ sessionTime: { parts: [...STATUSLINE_SESSION_TIME_PARTS] },
374
+ promptCache: { ttlSeconds: PROMPT_CACHE_TTL_SECONDS.fiveMinutes },
361
375
  colours: {
362
376
  context: "green",
363
377
  usage: "green",
@@ -4438,7 +4452,7 @@ var init_package = __esm({
4438
4452
  "package.json"() {
4439
4453
  package_default = {
4440
4454
  name: "claude-use",
4441
- version: "11.57.0",
4455
+ version: "11.58.0",
4442
4456
  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.",
4443
4457
  license: "MIT",
4444
4458
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -4542,6 +4556,22 @@ var init_package = __esm({
4542
4556
  }
4543
4557
  });
4544
4558
 
4559
+ // src/blockingSpawn.ts
4560
+ import {
4561
+ execFileSync,
4562
+ spawnSync
4563
+ } from "node:child_process";
4564
+ function spawnSyncBlocking(operation, command, args, options) {
4565
+ refuseToBlockInRole(operation);
4566
+ return spawnSync(command, args, options ?? {});
4567
+ }
4568
+ var init_blockingSpawn = __esm({
4569
+ "src/blockingSpawn.ts"() {
4570
+ "use strict";
4571
+ init_processRole();
4572
+ }
4573
+ });
4574
+
4545
4575
  // src/frontdoor/supervisorProcesses.ts
4546
4576
  function parseFrontDoorSupervisorPids(psOutput) {
4547
4577
  const pids = [];
@@ -5673,7 +5703,7 @@ var init_logStyle = __esm({
5673
5703
  });
5674
5704
 
5675
5705
  // src/realPorts.ts
5676
- import { execFile, spawn as spawn2, spawnSync } from "node:child_process";
5706
+ import { execFile, spawn as spawn2 } from "node:child_process";
5677
5707
  import { createHash as createHash5 } from "node:crypto";
5678
5708
  import fs3 from "node:fs";
5679
5709
  import os3 from "node:os";
@@ -5698,27 +5728,23 @@ function realIsProcessAlive(pid) {
5698
5728
  }
5699
5729
  }
5700
5730
  function realIsProcessZombie(pid) {
5701
- refuseToBlockInRole("a synchronous process-table read");
5702
- const result = spawnSync("ps", ["-o", "stat=", "-p", String(pid)], { encoding: "utf8" });
5731
+ const result = spawnSyncBlocking("a process-table read", "ps", ["-o", "stat=", "-p", String(pid)], { encoding: "utf8" });
5703
5732
  return result.status === 0 && result.stdout.trim().startsWith("Z");
5704
5733
  }
5705
5734
  function realIsProcessRunning(pid) {
5706
5735
  return realIsProcessAlive(pid) && !realIsProcessZombie(pid);
5707
5736
  }
5708
5737
  function realIsFrontDoorSupervisor(pid) {
5709
- refuseToBlockInRole("a synchronous process-table read");
5710
- const result = spawnSync("ps", ["-o", "pid=,command=", "-p", String(pid)], { encoding: "utf8" });
5738
+ const result = spawnSyncBlocking("a process-table read", "ps", ["-o", "pid=,command=", "-p", String(pid)], { encoding: "utf8" });
5711
5739
  return result.status === 0 && parseFrontDoorSupervisorPids(result.stdout).includes(pid);
5712
5740
  }
5713
5741
  function realProcessCommandLine(pid) {
5714
- refuseToBlockInRole("a synchronous process-table read");
5715
- const result = spawnSync("ps", ["-o", "command=", "-p", String(pid)], { encoding: "utf8", timeout: PS_TIMEOUT_MS });
5742
+ const result = spawnSyncBlocking("a process-table read", "ps", ["-o", "command=", "-p", String(pid)], { encoding: "utf8", timeout: PS_TIMEOUT_MS });
5716
5743
  return result.status === 0 ? result.stdout.trim() : void 0;
5717
5744
  }
5718
5745
  function realFrontDoorLiveness(pids) {
5719
- refuseToBlockInRole("a synchronous process-table read");
5720
5746
  return frontDoorLivenessOf(pids, (asked) => {
5721
- const result = spawnSync("ps", ["-o", "pid=,stat=,command=", "-p", asked.map(String).join(",")], { encoding: "utf8", timeout: PS_TIMEOUT_MS });
5747
+ const result = spawnSyncBlocking("a process-table read", "ps", ["-o", "pid=,stat=,command=", "-p", asked.map(String).join(",")], { encoding: "utf8", timeout: PS_TIMEOUT_MS });
5722
5748
  return { status: result.status, stdout: result.stdout, stderr: result.stderr, ...result.error === void 0 ? {} : { error: result.error } };
5723
5749
  });
5724
5750
  }
@@ -5727,7 +5753,7 @@ function expandHome2(filePath) {
5727
5753
  }
5728
5754
  function hasDesktopSession() {
5729
5755
  if (process.platform === "darwin") {
5730
- const result = spawnSync("launchctl", ["managername"], { encoding: "utf8" });
5756
+ const result = spawnSyncBlocking("a desktop-session check", "launchctl", ["managername"], { encoding: "utf8" });
5731
5757
  return result.status === 0 && result.stdout.trim() === MACOS_GUI_SESSION_MANAGER;
5732
5758
  }
5733
5759
  return hasDisplayServer();
@@ -5927,6 +5953,7 @@ var realFsPort, OWNER_ONLY_DIR_MODE, OWNER_ONLY_FILE_MODE, PERMISSION_BITS, real
5927
5953
  var init_realPorts = __esm({
5928
5954
  "src/realPorts.ts"() {
5929
5955
  "use strict";
5956
+ init_blockingSpawn();
5930
5957
  init_processRole();
5931
5958
  init_load();
5932
5959
  init_versionDiscovery();
@@ -6094,7 +6121,7 @@ var init_realPorts = __esm({
6094
6121
  PS_TIMEOUT_MS = 2e3;
6095
6122
  realRunPort = {
6096
6123
  run(command, args) {
6097
- const result = spawnSync(command, [...args], { encoding: "utf8" });
6124
+ const result = spawnSyncBlocking("an external command", command, args, { encoding: "utf8" });
6098
6125
  return { status: result.status, stdout: result.stdout, stderr: result.stderr };
6099
6126
  }
6100
6127
  };
@@ -6117,7 +6144,7 @@ var init_realPorts = __esm({
6117
6144
  },
6118
6145
  runCommand(argv, options) {
6119
6146
  const [command, ...args] = argv;
6120
- const result = spawnSync(command, args, {
6147
+ const result = spawnSyncBlocking("a credential command", command, args, {
6121
6148
  encoding: "utf8",
6122
6149
  timeout: options.timeoutMs,
6123
6150
  stdio: options.interactive ? ["inherit", "pipe", "inherit"] : ["ignore", "pipe", "pipe"]
@@ -6156,7 +6183,7 @@ var init_realPorts = __esm({
6156
6183
  };
6157
6184
  realSpawnPort = {
6158
6185
  spawnSync(command, args, options) {
6159
- const result = spawnSync(command, args, options);
6186
+ const result = spawnSyncBlocking("a spawned program", command, args, options);
6160
6187
  return { status: result.status, signal: result.signal, ...result.error === void 0 ? {} : { error: result.error } };
6161
6188
  }
6162
6189
  };
@@ -8072,7 +8099,6 @@ var init_credentialCache = __esm({
8072
8099
  });
8073
8100
 
8074
8101
  // src/realCredentialCache.ts
8075
- import { spawn as spawn3, spawnSync as spawnSync2 } from "node:child_process";
8076
8102
  import fs6 from "node:fs";
8077
8103
  import path24 from "node:path";
8078
8104
  function cacheFileNameFor(owner) {
@@ -8094,7 +8120,7 @@ function requireKeychain() {
8094
8120
  }
8095
8121
  }
8096
8122
  function security(args, stdin) {
8097
- const result = spawnSync2("security", args, { encoding: "utf8", ...stdin === void 0 ? {} : { input: stdin }, stdio: ["pipe", "pipe", "ignore"] });
8123
+ const result = spawnSyncBlocking("a keychain call", "security", args, { encoding: "utf8", ...stdin === void 0 ? {} : { input: stdin }, stdio: ["pipe", "pipe", "ignore"] });
8098
8124
  return { status: result.status, stdout: result.stdout };
8099
8125
  }
8100
8126
  function createRealCredentialCache(root) {
@@ -8149,6 +8175,7 @@ var KEYCHAIN_CACHE_SERVICE, CACHE_DIR_MODE, CACHE_FILE_MODE;
8149
8175
  var init_realCredentialCache = __esm({
8150
8176
  "src/realCredentialCache.ts"() {
8151
8177
  "use strict";
8178
+ init_blockingSpawn();
8152
8179
  init_credentialCache();
8153
8180
  KEYCHAIN_CACHE_SERVICE = "agent-shim-credential-cache";
8154
8181
  CACHE_DIR_MODE = 448;
@@ -11517,13 +11544,13 @@ function resolveLaunch(params) {
11517
11544
  environment
11518
11545
  };
11519
11546
  }
11520
- function runLaunchPlan(plan, spawn4) {
11547
+ function runLaunchPlan(plan, spawn3) {
11521
11548
  try {
11522
11549
  if (plan.hold() === "cancelled") {
11523
11550
  return LAUNCH_CANCELLED_EXIT;
11524
11551
  }
11525
11552
  plan.markChildStarted();
11526
- const result = spawn4.spawnSync(plan.bin, plan.args, { stdio: "inherit", env: plan.env });
11553
+ const result = spawn3.spawnSync(plan.bin, plan.args, { stdio: "inherit", env: plan.env });
11527
11554
  if (result.error !== void 0) {
11528
11555
  throw result.error;
11529
11556
  }
@@ -11728,17 +11755,24 @@ var init_realFrontDoorPort = __esm({
11728
11755
  }
11729
11756
  });
11730
11757
 
11758
+ // src/replayRun.ts
11759
+ var init_replayRun = __esm({
11760
+ "src/replayRun.ts"() {
11761
+ "use strict";
11762
+ }
11763
+ });
11764
+
11731
11765
  // src/launchWiring.ts
11732
11766
  import os8 from "node:os";
11733
11767
  import path42 from "node:path";
11734
11768
  import { randomUUID as randomUUID5 } from "node:crypto";
11735
- function buildFarmRuntime(paths, cwd) {
11769
+ function buildFarmRuntime(paths, cwd, run = realRunPort) {
11736
11770
  const home = os8.homedir();
11737
11771
  const read = cosmiconfigReader();
11738
11772
  const classification = loadClassification(paths);
11739
11773
  const loaded = loadCascadeInput({ paths, home, cwd, read });
11740
11774
  const selections = readDirectorySelections(loaded);
11741
- const git = resolveGitBranch(realRunPort, cwd);
11775
+ const git = resolveGitBranch(run, cwd);
11742
11776
  const updateMode = resolveUpdateMode(loaded.globalConfig);
11743
11777
  return {
11744
11778
  runtime: {
@@ -11785,7 +11819,7 @@ function realPrepareLaunchParams(paths, options) {
11785
11819
  frontdoor: realFrontDoorPort(paths, options.spawnDaemon),
11786
11820
  credentials: { ...realCredentialPort, cache: realCredentialCacheEnv(paths) },
11787
11821
  hold: realHoldPort,
11788
- hasStoredLogin: (identity) => identitySignIn(realFarmFs, { platform: process.platform, run: realRunPort }, { farmRoot: path42.join(paths.identitiesDir, identity), hasCredentialBlock: false }).state !== "signed-out",
11822
+ hasStoredLogin: (identity) => identitySignIn(realFarmFs, { platform: process.platform, run: options.run ?? realRunPort }, { farmRoot: path42.join(paths.identitiesDir, identity), hasCredentialBlock: false }).state !== "signed-out",
11789
11823
  ...farm.directoryIdentity === void 0 ? {} : { directoryPinnedIdentity: farm.directoryIdentity },
11790
11824
  ...farm.directoryConfigProfile === void 0 ? {} : { directoryRuleConfigProfile: farm.directoryConfigProfile },
11791
11825
  ...farm.globalDefaultConfigProfile === void 0 ? {} : { globalDefaultConfigProfile: farm.globalDefaultConfigProfile },
@@ -11818,7 +11852,7 @@ function prepareClaudeLaunch(options) {
11818
11852
  const spawnDaemon = daemonSpawnerFor(options.agentShim);
11819
11853
  return prepareLaunch(realPrepareLaunchParams(paths, { proc, log, spawnDaemon, farm: buildFarmRuntime(paths, options.cwd) }));
11820
11854
  }
11821
- function resolveClaudeLaunch(options) {
11855
+ function resolveClaudeLaunch(options, run = realRunPort) {
11822
11856
  const paths = options.paths ?? resolveLayoutPaths();
11823
11857
  const refusals = [];
11824
11858
  const warnings = [];
@@ -11842,7 +11876,7 @@ function resolveClaudeLaunch(options) {
11842
11876
  const spawnDaemon = () => {
11843
11877
  throw new Error("resolving a launch starts no daemon");
11844
11878
  };
11845
- return { resolution: resolveLaunch(realPrepareLaunchParams(paths, { proc, log, spawnDaemon, farm: buildFarmRuntime(paths, options.cwd) })), warnings };
11879
+ return { resolution: resolveLaunch(realPrepareLaunchParams(paths, { proc, log, spawnDaemon, run, farm: buildFarmRuntime(paths, options.cwd, run) })), warnings };
11846
11880
  }
11847
11881
  var LaunchRefusedError;
11848
11882
  var init_launchWiring = __esm({
@@ -11858,6 +11892,7 @@ var init_launchWiring = __esm({
11858
11892
  init_launcher();
11859
11893
  init_launchHook();
11860
11894
  init_cascade();
11895
+ init_replayRun();
11861
11896
  init_paths();
11862
11897
  init_signIn();
11863
11898
  init_realPorts();
@@ -17898,9 +17933,9 @@ function createLaunchApiRouter(deps) {
17898
17933
  // A POST because the launch's environment and arguments are a body, but the answer changes nothing.
17899
17934
  spec: (current) => ({ ...current, [READ_ONLY_OPERATION_EXTENSION]: true })
17900
17935
  })
17901
- ).input(LaunchResolveInputSchema).output(LaunchResolveOutputSchema).handler(({ input }) => {
17936
+ ).input(LaunchResolveInputSchema).output(LaunchResolveOutputSchema).handler(async ({ input }) => {
17902
17937
  try {
17903
- const { resolution, warnings } = deps.resolveLaunch({ path: input.path, argv: input.argv ?? [], env: input.env ?? {} });
17938
+ const { resolution, warnings } = await deps.resolveLaunch({ path: input.path, argv: input.argv ?? [], env: input.env ?? {} });
17904
17939
  return { ...resolution, warnings };
17905
17940
  } catch (error) {
17906
17941
  if (error instanceof CliError) {