agent-shim 11.57.1 → 11.59.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
@@ -170,27 +170,41 @@ function distinctList(member) {
170
170
  function isSingleVisibleGrapheme(text) {
171
171
  return graphemesOf(text).length === 1 && (0, import_string_width2.default)(text) === 1 && !/[\p{C}\p{Z}]/u.test(text) && !drawsNothing(text);
172
172
  }
173
+ function unsettable(setting) {
174
+ return setting.unwrap().nullable().optional().describe(`${setting.description ?? ""} ${UNSET_NOTE}`);
175
+ }
173
176
  function isPlainObject(value) {
174
177
  return typeof value === "object" && value !== null && !Array.isArray(value);
175
178
  }
176
179
  function mergeStatuslineSettings(base, over) {
177
- if (!isPlainObject(base) || !isPlainObject(over)) {
180
+ if (!isPlainObject(over)) {
178
181
  return over === void 0 ? base : over;
179
182
  }
180
- const merged = { ...base };
183
+ const merged = isPlainObject(base) ? { ...base } : {};
181
184
  for (const [key, value] of Object.entries(over)) {
182
- merged[key] = key in base ? mergeStatuslineSettings(base[key], value) : value;
185
+ if (value === null) {
186
+ Reflect.deleteProperty(merged, key);
187
+ } else {
188
+ merged[key] = mergeStatuslineSettings(merged[key], value);
189
+ }
183
190
  }
184
191
  return merged;
185
192
  }
193
+ function contextBands({ bands, context }) {
194
+ return { warnAt: context.warnAt ?? bands.warnAt, criticalAt: context.criticalAt ?? bands.criticalAt };
195
+ }
186
196
  function resolveStatusline(settings) {
187
197
  const resolved = ResolvedStatuslineSchema.parse(mergeStatuslineSettings(STATUSLINE_DEFAULTS, settings));
188
198
  if (resolved.bands.warnAt >= resolved.bands.criticalAt) {
189
199
  throw new RangeError(`statusline bands.warnAt (${String(resolved.bands.warnAt)}) must be below bands.criticalAt (${String(resolved.bands.criticalAt)})`);
190
200
  }
201
+ const forContext = contextBands(resolved);
202
+ if (forContext.warnAt >= forContext.criticalAt) {
203
+ throw new RangeError(`statusline context.warnAt (${String(forContext.warnAt)}) must be below context.criticalAt (${String(forContext.criticalAt)}), each following bands while it is unset`);
204
+ }
191
205
  return resolved;
192
206
  }
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;
207
+ 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, STATUSLINE_CONTEXT_VALUES, STATUSLINE_CONTEXT_ESTIMATES, AUTOCOMPACT_RESERVE_FRACTION, AUTOCOMPACT_RESERVE_RAMP_START, AUTOCOMPACT_RESERVE_RAMP_END, labelText, overrideText, wholePercent, thresholdPercent, SHAPES, UNSET_NOTE, StatuslineSchema, ResolvedStatuslineSchema, STATUSLINE_DEFAULTS, STATUSLINE_ENV;
194
208
  var init_statusline = __esm({
195
209
  "src/config/statusline.ts"() {
196
210
  "use strict";
@@ -198,8 +212,10 @@ var init_statusline = __esm({
198
212
  import_zod = require("zod");
199
213
  init_blank();
200
214
  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"];
215
+ STATUSLINE_HEADER_SEGMENTS = ["model", "provider", "route", "account", "identity", "headroom", "project", "vcs", "effort", "advisor", "version", "outputStyle", "cost", "dailyCost", "sessionName", "duration", "speed"];
216
+ STATUSLINE_ROWS = ["context", "quota", "addedDirs", "gitFiles", "memory", "environment", "sessionTime", "promptCache", "compactions", "tokens"];
217
+ STATUSLINE_SESSION_TIME_PARTS = ["started", "lastReply"];
218
+ PROMPT_CACHE_TTL_SECONDS = { fiveMinutes: 300, oneHour: 3600 };
203
219
  STATUSLINE_COLOUR_NAMES = [
204
220
  "default",
205
221
  "dim",
@@ -236,6 +252,11 @@ var init_statusline = __esm({
236
252
  OPTIONAL_LABEL_RE = /^(?:[^\p{C}\p{Z}]+(?: [^\p{C}\p{Z}]+)*)?$/u;
237
253
  colourValue = import_zod.z.union([import_zod.z.enum(STATUSLINE_COLOUR_NAMES), import_zod.z.number().int().min(0).max(MAX_STATUSLINE_PALETTE_INDEX), import_zod.z.string().regex(/^#[0-9a-fA-F]{6}$/, "must be a colour name, a palette index from 0 to 255 or #rrggbb")]);
238
254
  barCharacter = import_zod.z.string().refine(isSingleVisibleGrapheme, "must be a single visible character that takes one terminal column");
255
+ STATUSLINE_CONTEXT_VALUES = ["both", "percent", "tokens", "remaining"];
256
+ STATUSLINE_CONTEXT_ESTIMATES = ["never", "raw", "buffered"];
257
+ AUTOCOMPACT_RESERVE_FRACTION = 0.165;
258
+ AUTOCOMPACT_RESERVE_RAMP_START = 0.05;
259
+ AUTOCOMPACT_RESERVE_RAMP_END = 0.5;
239
260
  labelText = import_zod.z.string().refine((text) => (0, import_string_width2.default)(text) <= MAX_STATUSLINE_LABEL_COLUMNS, `must take no more than ${String(MAX_STATUSLINE_LABEL_COLUMNS)} terminal columns`).refine((text) => !drawsNothing(text), "must show something: a label of only combining marks or blank characters draws nothing").regex(LABEL_RE2, "must be visible text without control characters");
240
261
  overrideText = import_zod.z.string().max(MAX_DISPLAY_TEXT_CHARS).regex(OPTIONAL_LABEL_RE, "must be visible text without control characters");
241
262
  wholePercent = import_zod.z.number().int().min(1).max(MAX_PERCENT);
@@ -263,6 +284,15 @@ var init_statusline = __esm({
263
284
  advisor: {
264
285
  override: overrideText.describe("A name to show for the advisor model in place of the one the session's transcript records; empty shows the transcript's, prettified.")
265
286
  },
287
+ context: {
288
+ bar: import_zod.z.enum(["shown", "hidden"]).describe("Whether the context row draws its bar, or only its figures on one line of text."),
289
+ value: import_zod.z.enum(STATUSLINE_CONTEXT_VALUES).describe("The context figure: both (the tokens held against the window, then the percentage), percent, tokens, or remaining (the percentage of the window left)."),
290
+ warnAt: wholePercent.optional().describe("The whole percentage of the context window at which the context bar turns yellow; while it is unset the context bar follows bands.warnAt."),
291
+ criticalAt: wholePercent.optional().describe("The whole percentage of the context window at which the context bar turns red and, with context.breakdown set to critical, the token breakdown appears; while it is unset the context bar follows bands.criticalAt."),
292
+ autoCompactWindow: import_zod.z.number().int().positive().optional().describe("A window in tokens to measure the context against instead of the model's, matching the figure /context gives once Claude Code compacts before the window is full. While it is set, the row draws nothing until the client reports the tokens held, since without them there is nothing to measure against it; while it is unset the model's own window is used."),
293
+ estimate: import_zod.z.enum(STATUSLINE_CONTEXT_ESTIMATES).describe(`What to draw when the client reports no percentage of the window in use, or reports 0 while tokens are already held (which is how a client says it has not worked it out yet): never (nothing is estimated: a percentage reported, 0 included, is drawn as it is, and none reported draws nothing), raw (the tokens held over the window), or buffered (that, plus the ${String(AUTOCOMPACT_RESERVE_FRACTION * MAX_PERCENT)}% of the window Claude Code reserves for compaction, rising from nothing at ${String(AUTOCOMPACT_RESERVE_RAMP_START * MAX_PERCENT)}% of the window held to the whole reserve at ${String(AUTOCOMPACT_RESERVE_RAMP_END * MAX_PERCENT)}%).`),
294
+ breakdown: import_zod.z.enum(["never", "critical"]).describe("Whether to add the input and cache tokens of the last request to the context row once its use reaches context.criticalAt.")
295
+ },
266
296
  bands: {
267
297
  warnAt: wholePercent.describe("The whole percentage of use at which a bar turns yellow; it must be below criticalAt."),
268
298
  criticalAt: wholePercent.describe("The whole percentage of use at which a bar turns red.")
@@ -296,6 +326,12 @@ var init_statusline = __esm({
296
326
  environment: {
297
327
  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
328
  },
329
+ sessionTime: {
330
+ 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.")
331
+ },
332
+ promptCache: {
333
+ 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.")
334
+ },
299
335
  colours: {
300
336
  context: colourValue.describe("The colour of the context bar and its figures below the warning threshold."),
301
337
  usage: colourValue.describe("The colour of the quota bars and their figures below the warning threshold."),
@@ -328,6 +364,7 @@ var init_statusline = __esm({
328
364
  showConflicts: import_zod.z.boolean().describe("Whether the segment shows !conflict when the working-copy commit has an unresolved conflict.")
329
365
  }
330
366
  };
367
+ UNSET_NOTE = "A layer may write null to return it to unset when a shallower layer sets it.";
331
368
  StatuslineSchema = import_zod.z.strictObject({
332
369
  layout: import_zod.z.strictObject(SHAPES.layout).partial().optional(),
333
370
  model: import_zod.z.strictObject(SHAPES.model).partial().optional(),
@@ -335,6 +372,7 @@ var init_statusline = __esm({
335
372
  account: import_zod.z.strictObject(SHAPES.account).partial().optional(),
336
373
  effort: import_zod.z.strictObject(SHAPES.effort).partial().optional(),
337
374
  advisor: import_zod.z.strictObject(SHAPES.advisor).partial().optional(),
375
+ context: import_zod.z.strictObject({ ...SHAPES.context, warnAt: unsettable(SHAPES.context.warnAt), criticalAt: unsettable(SHAPES.context.criticalAt), autoCompactWindow: unsettable(SHAPES.context.autoCompactWindow) }).partial().optional(),
338
376
  bands: import_zod.z.strictObject(SHAPES.bands).partial().optional(),
339
377
  labels: import_zod.z.strictObject(SHAPES.labels).partial().optional(),
340
378
  bar: import_zod.z.strictObject(SHAPES.bar).partial().optional(),
@@ -342,6 +380,8 @@ var init_statusline = __esm({
342
380
  clock: import_zod.z.strictObject(SHAPES.clock).partial().optional(),
343
381
  cost: import_zod.z.strictObject(SHAPES.cost).partial().optional(),
344
382
  environment: import_zod.z.strictObject(SHAPES.environment).partial().optional(),
383
+ sessionTime: import_zod.z.strictObject(SHAPES.sessionTime).partial().optional(),
384
+ promptCache: import_zod.z.strictObject(SHAPES.promptCache).partial().optional(),
345
385
  colours: import_zod.z.strictObject(SHAPES.colours).partial().optional(),
346
386
  project: import_zod.z.strictObject(SHAPES.project).partial().optional(),
347
387
  git: import_zod.z.strictObject(SHAPES.git).partial().optional(),
@@ -354,6 +394,7 @@ var init_statusline = __esm({
354
394
  account: import_zod.z.strictObject(SHAPES.account),
355
395
  effort: import_zod.z.strictObject(SHAPES.effort),
356
396
  advisor: import_zod.z.strictObject(SHAPES.advisor),
397
+ context: import_zod.z.strictObject(SHAPES.context),
357
398
  bands: import_zod.z.strictObject(SHAPES.bands),
358
399
  labels: import_zod.z.strictObject(SHAPES.labels),
359
400
  bar: import_zod.z.strictObject(SHAPES.bar),
@@ -361,6 +402,8 @@ var init_statusline = __esm({
361
402
  clock: import_zod.z.strictObject(SHAPES.clock),
362
403
  cost: import_zod.z.strictObject(SHAPES.cost),
363
404
  environment: import_zod.z.strictObject(SHAPES.environment),
405
+ sessionTime: import_zod.z.strictObject(SHAPES.sessionTime),
406
+ promptCache: import_zod.z.strictObject(SHAPES.promptCache),
364
407
  colours: import_zod.z.strictObject(SHAPES.colours),
365
408
  project: import_zod.z.strictObject(SHAPES.project),
366
409
  git: import_zod.z.strictObject(SHAPES.git),
@@ -373,6 +416,7 @@ var init_statusline = __esm({
373
416
  account: { parts: ["user", "organisation", "plan"], userLength: 0 },
374
417
  effort: { format: "full" },
375
418
  advisor: { override: "" },
419
+ context: { bar: "shown", value: "both", estimate: "never", breakdown: "never" },
376
420
  bands: { warnAt: 70, criticalAt: 90 },
377
421
  labels: { fiveHour: "5h", sevenDay: "Wk" },
378
422
  bar: { width: 10, filled: "\u2588", empty: "\u2591" },
@@ -380,6 +424,8 @@ var init_statusline = __esm({
380
424
  clock: { hourCycle: "auto", seconds: false },
381
425
  cost: { routed: false },
382
426
  environment: { threshold: 0 },
427
+ sessionTime: { parts: [...STATUSLINE_SESSION_TIME_PARTS] },
428
+ promptCache: { ttlSeconds: PROMPT_CACHE_TTL_SECONDS.fiveMinutes },
383
429
  colours: {
384
430
  context: "green",
385
431
  usage: "green",
@@ -4462,7 +4508,7 @@ var init_package = __esm({
4462
4508
  "package.json"() {
4463
4509
  package_default = {
4464
4510
  name: "agent-shim",
4465
- version: "11.57.1",
4511
+ version: "11.59.0",
4466
4512
  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
4513
  license: "MIT",
4468
4514
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -7655,8 +7701,10 @@ function valueAt(source, path43) {
7655
7701
  }
7656
7702
  return current;
7657
7703
  }
7658
- function keyOf(path43, leaf) {
7659
- const common = { path: path43.join("."), description: leaf.description ?? "", defaultValue: valueAt(STATUSLINE_DEFAULTS, path43) };
7704
+ function keyOf(path43, declared) {
7705
+ const optional = declared instanceof import_zod15.z.ZodOptional;
7706
+ const leaf = optional ? declared.unwrap() : declared;
7707
+ const common = { path: path43.join("."), description: declared.description ?? "", defaultValue: valueAt(STATUSLINE_DEFAULTS, path43), optional };
7660
7708
  if (leaf instanceof import_zod15.z.ZodNumber) {
7661
7709
  return { ...common, kind: "integer", choices: [] };
7662
7710
  }
package/dist/index.mjs CHANGED
@@ -150,34 +150,50 @@ function distinctList(member) {
150
150
  function isSingleVisibleGrapheme(text) {
151
151
  return graphemesOf(text).length === 1 && stringWidth2(text) === 1 && !/[\p{C}\p{Z}]/u.test(text) && !drawsNothing(text);
152
152
  }
153
+ function unsettable(setting) {
154
+ return setting.unwrap().nullable().optional().describe(`${setting.description ?? ""} ${UNSET_NOTE}`);
155
+ }
153
156
  function isPlainObject(value) {
154
157
  return typeof value === "object" && value !== null && !Array.isArray(value);
155
158
  }
156
159
  function mergeStatuslineSettings(base, over) {
157
- if (!isPlainObject(base) || !isPlainObject(over)) {
160
+ if (!isPlainObject(over)) {
158
161
  return over === void 0 ? base : over;
159
162
  }
160
- const merged = { ...base };
163
+ const merged = isPlainObject(base) ? { ...base } : {};
161
164
  for (const [key, value] of Object.entries(over)) {
162
- merged[key] = key in base ? mergeStatuslineSettings(base[key], value) : value;
165
+ if (value === null) {
166
+ Reflect.deleteProperty(merged, key);
167
+ } else {
168
+ merged[key] = mergeStatuslineSettings(merged[key], value);
169
+ }
163
170
  }
164
171
  return merged;
165
172
  }
173
+ function contextBands({ bands, context }) {
174
+ return { warnAt: context.warnAt ?? bands.warnAt, criticalAt: context.criticalAt ?? bands.criticalAt };
175
+ }
166
176
  function resolveStatusline(settings) {
167
177
  const resolved = ResolvedStatuslineSchema.parse(mergeStatuslineSettings(STATUSLINE_DEFAULTS, settings));
168
178
  if (resolved.bands.warnAt >= resolved.bands.criticalAt) {
169
179
  throw new RangeError(`statusline bands.warnAt (${String(resolved.bands.warnAt)}) must be below bands.criticalAt (${String(resolved.bands.criticalAt)})`);
170
180
  }
181
+ const forContext = contextBands(resolved);
182
+ if (forContext.warnAt >= forContext.criticalAt) {
183
+ throw new RangeError(`statusline context.warnAt (${String(forContext.warnAt)}) must be below context.criticalAt (${String(forContext.criticalAt)}), each following bands while it is unset`);
184
+ }
171
185
  return resolved;
172
186
  }
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;
187
+ 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, STATUSLINE_CONTEXT_VALUES, STATUSLINE_CONTEXT_ESTIMATES, AUTOCOMPACT_RESERVE_FRACTION, AUTOCOMPACT_RESERVE_RAMP_START, AUTOCOMPACT_RESERVE_RAMP_END, labelText, overrideText, wholePercent, thresholdPercent, SHAPES, UNSET_NOTE, StatuslineSchema, ResolvedStatuslineSchema, STATUSLINE_DEFAULTS, STATUSLINE_ENV;
174
188
  var init_statusline = __esm({
175
189
  "src/config/statusline.ts"() {
176
190
  "use strict";
177
191
  init_blank();
178
192
  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"];
193
+ STATUSLINE_HEADER_SEGMENTS = ["model", "provider", "route", "account", "identity", "headroom", "project", "vcs", "effort", "advisor", "version", "outputStyle", "cost", "dailyCost", "sessionName", "duration", "speed"];
194
+ STATUSLINE_ROWS = ["context", "quota", "addedDirs", "gitFiles", "memory", "environment", "sessionTime", "promptCache", "compactions", "tokens"];
195
+ STATUSLINE_SESSION_TIME_PARTS = ["started", "lastReply"];
196
+ PROMPT_CACHE_TTL_SECONDS = { fiveMinutes: 300, oneHour: 3600 };
181
197
  STATUSLINE_COLOUR_NAMES = [
182
198
  "default",
183
199
  "dim",
@@ -214,6 +230,11 @@ var init_statusline = __esm({
214
230
  OPTIONAL_LABEL_RE = /^(?:[^\p{C}\p{Z}]+(?: [^\p{C}\p{Z}]+)*)?$/u;
215
231
  colourValue = z.union([z.enum(STATUSLINE_COLOUR_NAMES), z.number().int().min(0).max(MAX_STATUSLINE_PALETTE_INDEX), z.string().regex(/^#[0-9a-fA-F]{6}$/, "must be a colour name, a palette index from 0 to 255 or #rrggbb")]);
216
232
  barCharacter = z.string().refine(isSingleVisibleGrapheme, "must be a single visible character that takes one terminal column");
233
+ STATUSLINE_CONTEXT_VALUES = ["both", "percent", "tokens", "remaining"];
234
+ STATUSLINE_CONTEXT_ESTIMATES = ["never", "raw", "buffered"];
235
+ AUTOCOMPACT_RESERVE_FRACTION = 0.165;
236
+ AUTOCOMPACT_RESERVE_RAMP_START = 0.05;
237
+ AUTOCOMPACT_RESERVE_RAMP_END = 0.5;
217
238
  labelText = z.string().refine((text) => stringWidth2(text) <= MAX_STATUSLINE_LABEL_COLUMNS, `must take no more than ${String(MAX_STATUSLINE_LABEL_COLUMNS)} terminal columns`).refine((text) => !drawsNothing(text), "must show something: a label of only combining marks or blank characters draws nothing").regex(LABEL_RE2, "must be visible text without control characters");
218
239
  overrideText = z.string().max(MAX_DISPLAY_TEXT_CHARS).regex(OPTIONAL_LABEL_RE, "must be visible text without control characters");
219
240
  wholePercent = z.number().int().min(1).max(MAX_PERCENT);
@@ -241,6 +262,15 @@ var init_statusline = __esm({
241
262
  advisor: {
242
263
  override: overrideText.describe("A name to show for the advisor model in place of the one the session's transcript records; empty shows the transcript's, prettified.")
243
264
  },
265
+ context: {
266
+ bar: z.enum(["shown", "hidden"]).describe("Whether the context row draws its bar, or only its figures on one line of text."),
267
+ value: z.enum(STATUSLINE_CONTEXT_VALUES).describe("The context figure: both (the tokens held against the window, then the percentage), percent, tokens, or remaining (the percentage of the window left)."),
268
+ warnAt: wholePercent.optional().describe("The whole percentage of the context window at which the context bar turns yellow; while it is unset the context bar follows bands.warnAt."),
269
+ criticalAt: wholePercent.optional().describe("The whole percentage of the context window at which the context bar turns red and, with context.breakdown set to critical, the token breakdown appears; while it is unset the context bar follows bands.criticalAt."),
270
+ autoCompactWindow: z.number().int().positive().optional().describe("A window in tokens to measure the context against instead of the model's, matching the figure /context gives once Claude Code compacts before the window is full. While it is set, the row draws nothing until the client reports the tokens held, since without them there is nothing to measure against it; while it is unset the model's own window is used."),
271
+ estimate: z.enum(STATUSLINE_CONTEXT_ESTIMATES).describe(`What to draw when the client reports no percentage of the window in use, or reports 0 while tokens are already held (which is how a client says it has not worked it out yet): never (nothing is estimated: a percentage reported, 0 included, is drawn as it is, and none reported draws nothing), raw (the tokens held over the window), or buffered (that, plus the ${String(AUTOCOMPACT_RESERVE_FRACTION * MAX_PERCENT)}% of the window Claude Code reserves for compaction, rising from nothing at ${String(AUTOCOMPACT_RESERVE_RAMP_START * MAX_PERCENT)}% of the window held to the whole reserve at ${String(AUTOCOMPACT_RESERVE_RAMP_END * MAX_PERCENT)}%).`),
272
+ breakdown: z.enum(["never", "critical"]).describe("Whether to add the input and cache tokens of the last request to the context row once its use reaches context.criticalAt.")
273
+ },
244
274
  bands: {
245
275
  warnAt: wholePercent.describe("The whole percentage of use at which a bar turns yellow; it must be below criticalAt."),
246
276
  criticalAt: wholePercent.describe("The whole percentage of use at which a bar turns red.")
@@ -274,6 +304,12 @@ var init_statusline = __esm({
274
304
  environment: {
275
305
  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
306
  },
307
+ sessionTime: {
308
+ 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.")
309
+ },
310
+ promptCache: {
311
+ 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.")
312
+ },
277
313
  colours: {
278
314
  context: colourValue.describe("The colour of the context bar and its figures below the warning threshold."),
279
315
  usage: colourValue.describe("The colour of the quota bars and their figures below the warning threshold."),
@@ -306,6 +342,7 @@ var init_statusline = __esm({
306
342
  showConflicts: z.boolean().describe("Whether the segment shows !conflict when the working-copy commit has an unresolved conflict.")
307
343
  }
308
344
  };
345
+ UNSET_NOTE = "A layer may write null to return it to unset when a shallower layer sets it.";
309
346
  StatuslineSchema = z.strictObject({
310
347
  layout: z.strictObject(SHAPES.layout).partial().optional(),
311
348
  model: z.strictObject(SHAPES.model).partial().optional(),
@@ -313,6 +350,7 @@ var init_statusline = __esm({
313
350
  account: z.strictObject(SHAPES.account).partial().optional(),
314
351
  effort: z.strictObject(SHAPES.effort).partial().optional(),
315
352
  advisor: z.strictObject(SHAPES.advisor).partial().optional(),
353
+ context: z.strictObject({ ...SHAPES.context, warnAt: unsettable(SHAPES.context.warnAt), criticalAt: unsettable(SHAPES.context.criticalAt), autoCompactWindow: unsettable(SHAPES.context.autoCompactWindow) }).partial().optional(),
316
354
  bands: z.strictObject(SHAPES.bands).partial().optional(),
317
355
  labels: z.strictObject(SHAPES.labels).partial().optional(),
318
356
  bar: z.strictObject(SHAPES.bar).partial().optional(),
@@ -320,6 +358,8 @@ var init_statusline = __esm({
320
358
  clock: z.strictObject(SHAPES.clock).partial().optional(),
321
359
  cost: z.strictObject(SHAPES.cost).partial().optional(),
322
360
  environment: z.strictObject(SHAPES.environment).partial().optional(),
361
+ sessionTime: z.strictObject(SHAPES.sessionTime).partial().optional(),
362
+ promptCache: z.strictObject(SHAPES.promptCache).partial().optional(),
323
363
  colours: z.strictObject(SHAPES.colours).partial().optional(),
324
364
  project: z.strictObject(SHAPES.project).partial().optional(),
325
365
  git: z.strictObject(SHAPES.git).partial().optional(),
@@ -332,6 +372,7 @@ var init_statusline = __esm({
332
372
  account: z.strictObject(SHAPES.account),
333
373
  effort: z.strictObject(SHAPES.effort),
334
374
  advisor: z.strictObject(SHAPES.advisor),
375
+ context: z.strictObject(SHAPES.context),
335
376
  bands: z.strictObject(SHAPES.bands),
336
377
  labels: z.strictObject(SHAPES.labels),
337
378
  bar: z.strictObject(SHAPES.bar),
@@ -339,6 +380,8 @@ var init_statusline = __esm({
339
380
  clock: z.strictObject(SHAPES.clock),
340
381
  cost: z.strictObject(SHAPES.cost),
341
382
  environment: z.strictObject(SHAPES.environment),
383
+ sessionTime: z.strictObject(SHAPES.sessionTime),
384
+ promptCache: z.strictObject(SHAPES.promptCache),
342
385
  colours: z.strictObject(SHAPES.colours),
343
386
  project: z.strictObject(SHAPES.project),
344
387
  git: z.strictObject(SHAPES.git),
@@ -351,6 +394,7 @@ var init_statusline = __esm({
351
394
  account: { parts: ["user", "organisation", "plan"], userLength: 0 },
352
395
  effort: { format: "full" },
353
396
  advisor: { override: "" },
397
+ context: { bar: "shown", value: "both", estimate: "never", breakdown: "never" },
354
398
  bands: { warnAt: 70, criticalAt: 90 },
355
399
  labels: { fiveHour: "5h", sevenDay: "Wk" },
356
400
  bar: { width: 10, filled: "\u2588", empty: "\u2591" },
@@ -358,6 +402,8 @@ var init_statusline = __esm({
358
402
  clock: { hourCycle: "auto", seconds: false },
359
403
  cost: { routed: false },
360
404
  environment: { threshold: 0 },
405
+ sessionTime: { parts: [...STATUSLINE_SESSION_TIME_PARTS] },
406
+ promptCache: { ttlSeconds: PROMPT_CACHE_TTL_SECONDS.fiveMinutes },
361
407
  colours: {
362
408
  context: "green",
363
409
  usage: "green",
@@ -4438,7 +4484,7 @@ var init_package = __esm({
4438
4484
  "package.json"() {
4439
4485
  package_default = {
4440
4486
  name: "agent-shim",
4441
- version: "11.57.1",
4487
+ version: "11.59.0",
4442
4488
  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
4489
  license: "MIT",
4444
4490
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -7632,8 +7678,10 @@ function valueAt(source, path43) {
7632
7678
  }
7633
7679
  return current;
7634
7680
  }
7635
- function keyOf(path43, leaf) {
7636
- const common = { path: path43.join("."), description: leaf.description ?? "", defaultValue: valueAt(STATUSLINE_DEFAULTS, path43) };
7681
+ function keyOf(path43, declared) {
7682
+ const optional = declared instanceof z15.ZodOptional;
7683
+ const leaf = optional ? declared.unwrap() : declared;
7684
+ const common = { path: path43.join("."), description: declared.description ?? "", defaultValue: valueAt(STATUSLINE_DEFAULTS, path43), optional };
7637
7685
  if (leaf instanceof z15.ZodNumber) {
7638
7686
  return { ...common, kind: "integer", choices: [] };
7639
7687
  }