agent-shim 11.27.0 → 11.28.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.mjs CHANGED
@@ -263,7 +263,11 @@ var init_schema = __esm({
263
263
  headroom: z.boolean().optional(),
264
264
  trackUsage: z.boolean().optional(),
265
265
  /** The exact Claude Code version to run, as it is named in Claude Code's versions directory (`2.1.220`). A pin that is not installed fails the launch; it never falls back to the highest version. */
266
- claudeVersion: z.string().regex(NUMERIC_DOTTED_VERSION_RE, "must be an exact dotted-numeric Claude Code version such as 2.1.220").optional()
266
+ claudeVersion: z.string().regex(NUMERIC_DOTTED_VERSION_RE, "must be an exact dotted-numeric Claude Code version such as 2.1.220").optional(),
267
+ /** How long the launcher waits after its own output before it starts claude, so that output can be read before Claude Code takes over the terminal (`5s`, `500ms`). Applies only when a terminal is watching. */
268
+ delay: z.string().regex(DURATION_RE, "must be a duration such as 5s or 500ms").optional(),
269
+ /** Whether the launcher waits for a key press after its own output before it starts claude. Takes the place of `delay` when both are set. Applies only when a terminal is watching. */
270
+ pause: z.boolean().optional()
267
271
  });
268
272
  CREDENTIAL_TARGETS = ["bearer", "apiKey", "oauthToken"];
269
273
  PROVIDER_CREDENTIAL_TARGETS = ["bearer", "apiKey"];
@@ -1366,6 +1370,12 @@ function flattenLayers(layers, options) {
1366
1370
  if (layer.launch.claudeVersion !== void 0) {
1367
1371
  launch.claudeVersion = layer.launch.claudeVersion;
1368
1372
  }
1373
+ if (layer.launch.delay !== void 0) {
1374
+ launch.delay = layer.launch.delay;
1375
+ }
1376
+ if (layer.launch.pause !== void 0) {
1377
+ launch.pause = layer.launch.pause;
1378
+ }
1369
1379
  }
1370
1380
  if (layer.entries === void 0) {
1371
1381
  continue;
@@ -2940,7 +2950,7 @@ var init_package = __esm({
2940
2950
  "package.json"() {
2941
2951
  package_default = {
2942
2952
  name: "agent-shim",
2943
- version: "11.27.0",
2953
+ version: "11.28.0",
2944
2954
  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.",
2945
2955
  license: "MIT",
2946
2956
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -4383,7 +4393,7 @@ function realResolveClaudeBinary(isOwnBinary) {
4383
4393
  function realInstalledClaudeVersions() {
4384
4394
  return installedVersions(listVersionsDir(defaultVersionsDir()));
4385
4395
  }
4386
- var realFsPort, OWNER_ONLY_DIR_MODE, OWNER_ONLY_FILE_MODE, PERMISSION_BITS, realFarmFs, INT32_BYTE_LENGTH, PS_TIMEOUT_MS, realRunPort, MACOS_GUI_SESSION_MANAGER, realCredentialPort, SOCKET_PERMISSION_BITS, realHeadroomSocketTrust, realSpawnPort, realProcPort, realLogPort, EXECUTE_BITS_MASK, WINDOWS_DEFAULT_PATHEXT;
4396
+ var 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;
4387
4397
  var init_realPorts = __esm({
4388
4398
  "src/realPorts.ts"() {
4389
4399
  "use strict";
@@ -4526,6 +4536,31 @@ var init_realPorts = __esm({
4526
4536
  }
4527
4537
  };
4528
4538
  INT32_BYTE_LENGTH = 4;
4539
+ KEY_POLL_MS = 25;
4540
+ CTRL_C_BYTE = 3;
4541
+ realHoldPort = {
4542
+ attended: () => process.stdin.isTTY && process.stdout.isTTY,
4543
+ sleep: realSleepSync,
4544
+ waitForKey: () => {
4545
+ process.stdin.setRawMode(true);
4546
+ try {
4547
+ const buffer = Buffer.alloc(1);
4548
+ for (; ; ) {
4549
+ try {
4550
+ const read = fs3.readSync(process.stdin.fd, buffer, 0, buffer.length, null);
4551
+ return read > 0 && buffer[0] === CTRL_C_BYTE ? "interrupt" : "key";
4552
+ } catch (error) {
4553
+ if (!(error instanceof Error && "code" in error && error.code === "EAGAIN")) {
4554
+ throw error;
4555
+ }
4556
+ realSleepSync(KEY_POLL_MS);
4557
+ }
4558
+ }
4559
+ } finally {
4560
+ process.stdin.setRawMode(false);
4561
+ }
4562
+ }
4563
+ };
4529
4564
  PS_TIMEOUT_MS = 2e3;
4530
4565
  realRunPort = {
4531
4566
  run(command, args) {
@@ -7364,6 +7399,7 @@ function parseLauncherArgv(argv) {
7364
7399
  let configProfile;
7365
7400
  let provider;
7366
7401
  let claudeVersion;
7402
+ let delay;
7367
7403
  const booleans = {};
7368
7404
  const categoryFlags = [];
7369
7405
  const shareFlags = [];
@@ -7421,6 +7457,9 @@ function parseLauncherArgv(argv) {
7421
7457
  case "--claude-version":
7422
7458
  claudeVersion = value;
7423
7459
  break;
7460
+ case "--delay":
7461
+ delay = value;
7462
+ break;
7424
7463
  case "--category":
7425
7464
  categoryFlags.push(value);
7426
7465
  break;
@@ -7443,6 +7482,7 @@ function parseLauncherArgv(argv) {
7443
7482
  ...configProfile === void 0 ? {} : { configProfile },
7444
7483
  ...provider === void 0 ? {} : { provider },
7445
7484
  ...claudeVersion === void 0 ? {} : { claudeVersion },
7485
+ ...delay === void 0 ? {} : { delay },
7446
7486
  ...native ? { native: true } : {},
7447
7487
  ...booleans,
7448
7488
  categoryFlags,
@@ -7466,13 +7506,14 @@ var init_argv = __esm({
7466
7506
  positional;
7467
7507
  flag;
7468
7508
  };
7469
- VALUED_FLAGS = ["--identity", "--config-profile", "--provider", "--claude-version", "--category", "--share", "--hide"];
7509
+ VALUED_FLAGS = ["--identity", "--config-profile", "--provider", "--claude-version", "--delay", "--category", "--share", "--hide"];
7470
7510
  BOOLEAN_FLAGS = [
7471
7511
  { flag: "--headroom", key: "headroom" },
7472
7512
  { flag: "--track-usage", key: "trackUsage" },
7473
7513
  { flag: "--skip-permissions", key: "skipPermissions" },
7474
7514
  { flag: "--remote-control", key: "remoteControl" },
7475
- { flag: "--wait", key: "wait" }
7515
+ { flag: "--wait", key: "wait" },
7516
+ { flag: "--pause", key: "pause" }
7476
7517
  ];
7477
7518
  LAUNCHER_FLAG_NAMES = [
7478
7519
  ...VALUED_FLAGS,
@@ -7660,9 +7701,23 @@ function resolveLaunchFlags(params) {
7660
7701
  skipPermissions: params.flags?.skipPermissions ?? parseEnvBool("AGENT_SHIM_SKIP_PERMISSIONS", params.env.AGENT_SHIM_SKIP_PERMISSIONS) ?? params.cascade?.skipPermissions ?? false,
7661
7702
  remoteControl: params.flags?.remoteControl ?? parseEnvBool("AGENT_SHIM_REMOTE_CONTROL", params.env.AGENT_SHIM_REMOTE_CONTROL) ?? params.cascade?.remoteControl ?? false,
7662
7703
  headroom: params.flags?.headroom ?? parseEnvBool("AGENT_SHIM_HEADROOM", params.env.AGENT_SHIM_HEADROOM) ?? params.cascade?.headroom ?? false,
7663
- trackUsage: params.flags?.trackUsage ?? parseEnvBool("AGENT_SHIM_TRACK_USAGE", params.env.AGENT_SHIM_TRACK_USAGE) ?? params.cascade?.trackUsage ?? true
7704
+ trackUsage: params.flags?.trackUsage ?? parseEnvBool("AGENT_SHIM_TRACK_USAGE", params.env.AGENT_SHIM_TRACK_USAGE) ?? params.cascade?.trackUsage ?? true,
7705
+ pause: params.flags?.pause ?? parseEnvBool("AGENT_SHIM_PAUSE", params.env.AGENT_SHIM_PAUSE) ?? params.cascade?.pause ?? false,
7706
+ delayMs: resolveDelayMs(params)
7664
7707
  };
7665
7708
  }
7709
+ function resolveDelayMs(params) {
7710
+ const fromEnv = params.env.AGENT_SHIM_DELAY === "" ? void 0 : params.env.AGENT_SHIM_DELAY;
7711
+ const [literal, source] = params.flags?.delay !== void 0 ? [params.flags.delay, "--delay"] : fromEnv !== void 0 ? [fromEnv, "AGENT_SHIM_DELAY"] : [params.cascade?.delay, "launch.delay"];
7712
+ if (literal === void 0) {
7713
+ return 0;
7714
+ }
7715
+ try {
7716
+ return parseDuration(literal);
7717
+ } catch (error) {
7718
+ throw new UsageError(`${source}: ${error instanceof Error ? error.message : String(error)}`);
7719
+ }
7720
+ }
7666
7721
  function buildFlagArgs(flags) {
7667
7722
  const args = [];
7668
7723
  if (flags.skipPermissions) {
@@ -7734,6 +7789,8 @@ var init_flags = __esm({
7734
7789
  "src/launcher/flags.ts"() {
7735
7790
  "use strict";
7736
7791
  init_envBool();
7792
+ init_cliError();
7793
+ init_conditions();
7737
7794
  init_credential();
7738
7795
  init_headers();
7739
7796
  init_capability();
@@ -7953,6 +8010,31 @@ var init_diagnostics = __esm({
7953
8010
  }
7954
8011
  });
7955
8012
 
8013
+ // src/launcher/hold.ts
8014
+ function describeDelay(ms) {
8015
+ return ms % MS_PER_SECOND7 === 0 ? `${String(ms / MS_PER_SECOND7)}s` : `${String(ms)}ms`;
8016
+ }
8017
+ function holdBeforeLaunch(hold, port, log) {
8018
+ if (port === void 0 || !port.attended() || !hold.pause && hold.delayMs <= 0) {
8019
+ return "go";
8020
+ }
8021
+ if (hold.pause) {
8022
+ log.info("agent-shim: paused before launch; press any key to start, or Ctrl-C to cancel");
8023
+ return port.waitForKey() === "interrupt" ? "cancelled" : "go";
8024
+ }
8025
+ log.info(`agent-shim: starting in ${describeDelay(hold.delayMs)}`);
8026
+ port.sleep(hold.delayMs);
8027
+ return "go";
8028
+ }
8029
+ var LAUNCH_CANCELLED_EXIT, MS_PER_SECOND7;
8030
+ var init_hold = __esm({
8031
+ "src/launcher/hold.ts"() {
8032
+ "use strict";
8033
+ LAUNCH_CANCELLED_EXIT = 130;
8034
+ MS_PER_SECOND7 = 1e3;
8035
+ }
8036
+ });
8037
+
7956
8038
  // src/antigravity/cloudUpstream.ts
7957
8039
  var init_cloudUpstream = __esm({
7958
8040
  "src/antigravity/cloudUpstream.ts"() {
@@ -8136,20 +8218,20 @@ function filterCatalogue(models, catalogue) {
8136
8218
  const excluded = catalogue.exclude === void 0 ? void 0 : picomatch4(catalogue.exclude, { dot: true });
8137
8219
  return models.filter((model) => included?.(model.id) !== false && excluded?.(model.id) !== true);
8138
8220
  }
8139
- var DEFAULT_CANDIDATE_URLS, MS_PER_SECOND7, SECONDS_PER_HOUR2, HOURS_PER_DAY5, MS_PER_HOUR5, HOURS_BETWEEN_RETRIES, CATALOGUE_MAX_AGE_MS, CATALOGUE_RETRY_MS, CATALOGUE_REQUEST_SECONDS, CATALOGUE_REQUEST_TIMEOUT_MS, CATALOGUE_REFRESH_TIMEOUT_MS, CatalogueModelSchema, CatalogueCacheSchema;
8221
+ var DEFAULT_CANDIDATE_URLS, MS_PER_SECOND8, SECONDS_PER_HOUR2, HOURS_PER_DAY5, MS_PER_HOUR5, HOURS_BETWEEN_RETRIES, CATALOGUE_MAX_AGE_MS, CATALOGUE_RETRY_MS, CATALOGUE_REQUEST_SECONDS, CATALOGUE_REQUEST_TIMEOUT_MS, CATALOGUE_REFRESH_TIMEOUT_MS, CatalogueModelSchema, CatalogueCacheSchema;
8140
8222
  var init_providerCatalogue = __esm({
8141
8223
  "src/providerCatalogue.ts"() {
8142
8224
  "use strict";
8143
8225
  DEFAULT_CANDIDATE_URLS = 2;
8144
- MS_PER_SECOND7 = 1e3;
8226
+ MS_PER_SECOND8 = 1e3;
8145
8227
  SECONDS_PER_HOUR2 = 3600;
8146
8228
  HOURS_PER_DAY5 = 24;
8147
- MS_PER_HOUR5 = SECONDS_PER_HOUR2 * MS_PER_SECOND7;
8229
+ MS_PER_HOUR5 = SECONDS_PER_HOUR2 * MS_PER_SECOND8;
8148
8230
  HOURS_BETWEEN_RETRIES = 1;
8149
8231
  CATALOGUE_MAX_AGE_MS = HOURS_PER_DAY5 * MS_PER_HOUR5;
8150
8232
  CATALOGUE_RETRY_MS = HOURS_BETWEEN_RETRIES * MS_PER_HOUR5;
8151
8233
  CATALOGUE_REQUEST_SECONDS = 10;
8152
- CATALOGUE_REQUEST_TIMEOUT_MS = CATALOGUE_REQUEST_SECONDS * MS_PER_SECOND7;
8234
+ CATALOGUE_REQUEST_TIMEOUT_MS = CATALOGUE_REQUEST_SECONDS * MS_PER_SECOND8;
8153
8235
  CATALOGUE_REFRESH_TIMEOUT_MS = DEFAULT_CANDIDATE_URLS * CATALOGUE_REQUEST_TIMEOUT_MS;
8154
8236
  CatalogueModelSchema = z30.strictObject({ id: z30.string().min(1), name: z30.string().min(1).optional() });
8155
8237
  CatalogueCacheSchema = z30.strictObject({ fetchedAt: z30.number(), url: z30.string().min(1), models: z30.array(CatalogueModelSchema) });
@@ -8673,7 +8755,9 @@ function decideLaunch(params, readOnly) {
8673
8755
  ...parsedArgv.skipPermissions === void 0 ? {} : { skipPermissions: parsedArgv.skipPermissions },
8674
8756
  ...parsedArgv.remoteControl === void 0 ? {} : { remoteControl: parsedArgv.remoteControl },
8675
8757
  ...parsedArgv.headroom === void 0 ? {} : { headroom: parsedArgv.headroom },
8676
- ...parsedArgv.trackUsage === void 0 ? {} : { trackUsage: parsedArgv.trackUsage }
8758
+ ...parsedArgv.trackUsage === void 0 ? {} : { trackUsage: parsedArgv.trackUsage },
8759
+ ...parsedArgv.pause === void 0 ? {} : { pause: parsedArgv.pause },
8760
+ ...parsedArgv.delay === void 0 ? {} : { delay: parsedArgv.delay }
8677
8761
  }
8678
8762
  });
8679
8763
  const loginlessProvider = requestedFlags.remoteControl && selectedProvider !== void 0 && farmIdentity !== void 0 && params.hasStoredLogin?.(farmIdentity) === false ? { identity: farmIdentity, provider: selectedProvider.name } : void 0;
@@ -8818,7 +8902,8 @@ function prepareLaunch(params) {
8818
8902
  registered();
8819
8903
  }
8820
8904
  };
8821
- return { bin: decided.bin, args: finalArgv, env: finalEnv, sessionId, release, markChildStarted: updateCheck.markChildStarted, decision };
8905
+ const hold = () => holdBeforeLaunch({ delayMs: resolvedFlags.delayMs, pause: resolvedFlags.pause }, params.hold, log);
8906
+ return { bin: decided.bin, args: finalArgv, env: finalEnv, sessionId, release, markChildStarted: updateCheck.markChildStarted, hold, decision };
8822
8907
  }
8823
8908
  function resolveLaunch(params) {
8824
8909
  const decided = decideLaunch(params, true);
@@ -8851,6 +8936,9 @@ function resolveLaunch(params) {
8851
8936
  }
8852
8937
  function runLaunchPlan(plan, spawn3) {
8853
8938
  try {
8939
+ if (plan.hold() === "cancelled") {
8940
+ return LAUNCH_CANCELLED_EXIT;
8941
+ }
8854
8942
  plan.markChildStarted();
8855
8943
  const result = spawn3.spawnSync(plan.bin, plan.args, { stdio: "inherit", env: plan.env });
8856
8944
  if (result.error !== void 0) {
@@ -8878,6 +8966,7 @@ var init_launcher = __esm({
8878
8966
  init_extraFlags();
8879
8967
  init_claudeSession();
8880
8968
  init_diagnostics();
8969
+ init_hold();
8881
8970
  init_modelPicker();
8882
8971
  init_providerCatalogue();
8883
8972
  init_pool();
@@ -9086,6 +9175,7 @@ function realPrepareLaunchParams(paths, options) {
9086
9175
  headroom: realHeadroomPort(paths, { spawnDaemon: options.spawnDaemon, cwd: farm.runtime.cwd }),
9087
9176
  frontdoor: realFrontDoorPort(paths, options.spawnDaemon),
9088
9177
  credentials: { ...realCredentialPort, cache: realCredentialCacheEnv(paths) },
9178
+ hold: realHoldPort,
9089
9179
  hasStoredLogin: (identity) => identitySignIn(realFarmFs, { platform: process.platform, run: realRunPort }, { farmRoot: path42.join(paths.identitiesDir, identity), hasCredentialBlock: false }).state !== "signed-out",
9090
9180
  ...farm.directoryIdentity === void 0 ? {} : { directoryPinnedIdentity: farm.directoryIdentity },
9091
9181
  ...farm.directoryConfigProfile === void 0 ? {} : { directoryRuleConfigProfile: farm.directoryConfigProfile },
@@ -9362,13 +9452,13 @@ var init_identityClaude = __esm({
9362
9452
 
9363
9453
  // src/usage/providerQuota.ts
9364
9454
  import { z as z31 } from "zod";
9365
- var MS_PER_SECOND8, SECONDS_PER_HOUR3, HOURS_PER_DAY6, DAYS_PER_MONTH, ZAI_HOST, ZAI_QUOTA_URL, ZAI_UNIT_HOURS, ZAI_UNIT_MONTHS, ZAI_UNIT_MS, ZaiLimitSchema, ZaiResponseSchema, OPENROUTER_HOST, OPENROUTER_KEY_URL, OPENROUTER_CREDITS_URL, MS_PER_DAY3, OpenRouterKeySchema, OpenRouterCreditsSchema, ANTIGRAVITY_HOST, ANTIGRAVITY_QUOTA_URL, ANTIGRAVITY_USER_URL, FIVE_HOURS2, DAYS_PER_WEEK2, FIVE_HOURS_MS, WEEK_MS, AntigravityBucketSchema, AntigravitySummarySchema, GoogleTokenInfoSchema, AntigravityUserSchema;
9455
+ var MS_PER_SECOND9, SECONDS_PER_HOUR3, HOURS_PER_DAY6, DAYS_PER_MONTH, ZAI_HOST, ZAI_QUOTA_URL, ZAI_UNIT_HOURS, ZAI_UNIT_MONTHS, ZAI_UNIT_MS, ZaiLimitSchema, ZaiResponseSchema, OPENROUTER_HOST, OPENROUTER_KEY_URL, OPENROUTER_CREDITS_URL, MS_PER_DAY3, OpenRouterKeySchema, OpenRouterCreditsSchema, ANTIGRAVITY_HOST, ANTIGRAVITY_QUOTA_URL, ANTIGRAVITY_USER_URL, FIVE_HOURS2, DAYS_PER_WEEK2, FIVE_HOURS_MS, WEEK_MS, AntigravityBucketSchema, AntigravitySummarySchema, GoogleTokenInfoSchema, AntigravityUserSchema;
9366
9456
  var init_providerQuota = __esm({
9367
9457
  "src/usage/providerQuota.ts"() {
9368
9458
  "use strict";
9369
9459
  init_cloudUpstream();
9370
9460
  init_schema2();
9371
- MS_PER_SECOND8 = 1e3;
9461
+ MS_PER_SECOND9 = 1e3;
9372
9462
  SECONDS_PER_HOUR3 = 3600;
9373
9463
  HOURS_PER_DAY6 = 24;
9374
9464
  DAYS_PER_MONTH = 30;
@@ -9377,8 +9467,8 @@ var init_providerQuota = __esm({
9377
9467
  ZAI_UNIT_HOURS = 3;
9378
9468
  ZAI_UNIT_MONTHS = 5;
9379
9469
  ZAI_UNIT_MS = /* @__PURE__ */ new Map([
9380
- [ZAI_UNIT_HOURS, SECONDS_PER_HOUR3 * MS_PER_SECOND8],
9381
- [ZAI_UNIT_MONTHS, DAYS_PER_MONTH * HOURS_PER_DAY6 * SECONDS_PER_HOUR3 * MS_PER_SECOND8]
9470
+ [ZAI_UNIT_HOURS, SECONDS_PER_HOUR3 * MS_PER_SECOND9],
9471
+ [ZAI_UNIT_MONTHS, DAYS_PER_MONTH * HOURS_PER_DAY6 * SECONDS_PER_HOUR3 * MS_PER_SECOND9]
9382
9472
  ]);
9383
9473
  ZaiLimitSchema = z31.object({
9384
9474
  type: z31.string(),
@@ -9398,7 +9488,7 @@ var init_providerQuota = __esm({
9398
9488
  OPENROUTER_HOST = "openrouter.ai";
9399
9489
  OPENROUTER_KEY_URL = `https://${OPENROUTER_HOST}/api/v1/key`;
9400
9490
  OPENROUTER_CREDITS_URL = `https://${OPENROUTER_HOST}/api/v1/credits`;
9401
- MS_PER_DAY3 = HOURS_PER_DAY6 * SECONDS_PER_HOUR3 * MS_PER_SECOND8;
9491
+ MS_PER_DAY3 = HOURS_PER_DAY6 * SECONDS_PER_HOUR3 * MS_PER_SECOND9;
9402
9492
  OpenRouterKeySchema = z31.object({
9403
9493
  data: z31.object({
9404
9494
  limit: z31.number().nonnegative().nullable(),
@@ -9414,8 +9504,8 @@ var init_providerQuota = __esm({
9414
9504
  ANTIGRAVITY_USER_URL = `https://${ANTIGRAVITY_HOST}/v1internal:loadCodeAssist`;
9415
9505
  FIVE_HOURS2 = 5;
9416
9506
  DAYS_PER_WEEK2 = 7;
9417
- FIVE_HOURS_MS = FIVE_HOURS2 * SECONDS_PER_HOUR3 * MS_PER_SECOND8;
9418
- WEEK_MS = DAYS_PER_WEEK2 * HOURS_PER_DAY6 * SECONDS_PER_HOUR3 * MS_PER_SECOND8;
9507
+ FIVE_HOURS_MS = FIVE_HOURS2 * SECONDS_PER_HOUR3 * MS_PER_SECOND9;
9508
+ WEEK_MS = DAYS_PER_WEEK2 * HOURS_PER_DAY6 * SECONDS_PER_HOUR3 * MS_PER_SECOND9;
9419
9509
  AntigravityBucketSchema = z31.object({
9420
9510
  bucketId: z31.string(),
9421
9511
  remainingFraction: z31.number().optional(),
@@ -13334,6 +13424,12 @@ function applyProfileChange(paths, name, change) {
13334
13424
  if (change.launchClaudeVersion !== void 0) {
13335
13425
  launchPatch.claudeVersion = change.launchClaudeVersion === false ? void 0 : change.launchClaudeVersion;
13336
13426
  }
13427
+ if (change.launchDelay !== void 0) {
13428
+ launchPatch.delay = change.launchDelay === false ? void 0 : change.launchDelay;
13429
+ }
13430
+ if (change.launchPause !== void 0) {
13431
+ launchPatch.pause = change.launchPause;
13432
+ }
13337
13433
  if (Object.keys(launchPatch).length > 0) {
13338
13434
  setProfileLaunchFlags(paths, name, launchPatch);
13339
13435
  touched = true;
@@ -15549,7 +15645,9 @@ var ConfigProfileSetInputSchema = z24.strictObject({
15549
15645
  headroom: z24.boolean().optional(),
15550
15646
  trackUsage: z24.boolean().optional(),
15551
15647
  provider: z24.union([z24.string().min(1), z24.literal(false)]).optional(),
15552
- claudeVersion: z24.union([z24.string().min(1), z24.literal(false)]).optional()
15648
+ claudeVersion: z24.union([z24.string().min(1), z24.literal(false)]).optional(),
15649
+ delay: z24.union([z24.string().regex(DURATION_RE), z24.literal(false)]).optional(),
15650
+ pause: z24.boolean().optional()
15553
15651
  }).optional()
15554
15652
  });
15555
15653
  var ConfigProfileSetOutputSchema = storedMutationOutput("profile", "updated", ProfileValueSchema);
@@ -15759,7 +15857,9 @@ function createConfigApiRouter(deps) {
15759
15857
  ...launch?.headroom === void 0 ? {} : { launchHeadroom: launch.headroom },
15760
15858
  ...launch?.trackUsage === void 0 ? {} : { launchTrackUsage: launch.trackUsage },
15761
15859
  ...launch?.provider === void 0 ? {} : { launchProvider: launch.provider },
15762
- ...launch?.claudeVersion === void 0 ? {} : { launchClaudeVersion: launch.claudeVersion }
15860
+ ...launch?.claudeVersion === void 0 ? {} : { launchClaudeVersion: launch.claudeVersion },
15861
+ ...launch?.delay === void 0 ? {} : { launchDelay: launch.delay },
15862
+ ...launch?.pause === void 0 ? {} : { launchPause: launch.pause }
15763
15863
  });
15764
15864
  return { action: "updated", kind: "profile", name: input.name, value: profileValue(input.name, paths) };
15765
15865
  })
@@ -16067,7 +16167,10 @@ var LaunchFlagsSchema = z26.strictObject({
16067
16167
  skipPermissions: z26.boolean(),
16068
16168
  remoteControl: z26.boolean(),
16069
16169
  headroom: z26.boolean(),
16070
- trackUsage: z26.boolean()
16170
+ trackUsage: z26.boolean(),
16171
+ pause: z26.boolean(),
16172
+ /** How long the launch waits after its own output before it starts claude, in milliseconds. */
16173
+ delayMs: z26.number()
16071
16174
  });
16072
16175
  var LaunchResolveOutputSchema = z26.strictObject({
16073
16176
  decision: LaunchDecisionSchema,
@@ -276,6 +276,8 @@ declare const LaunchSchema: z.ZodObject<{
276
276
  headroom: z.ZodOptional<z.ZodBoolean>;
277
277
  trackUsage: z.ZodOptional<z.ZodBoolean>;
278
278
  claudeVersion: z.ZodOptional<z.ZodString>;
279
+ delay: z.ZodOptional<z.ZodString>;
280
+ pause: z.ZodOptional<z.ZodBoolean>;
279
281
  }, z.core.$strict>;
280
282
  type LaunchFlags = z.infer<typeof LaunchSchema>;
281
283
  /**
@@ -857,6 +859,8 @@ declare const ConfigProfileSchema: z.ZodObject<{
857
859
  headroom: z.ZodOptional<z.ZodBoolean>;
858
860
  trackUsage: z.ZodOptional<z.ZodBoolean>;
859
861
  claudeVersion: z.ZodOptional<z.ZodString>;
862
+ delay: z.ZodOptional<z.ZodString>;
863
+ pause: z.ZodOptional<z.ZodBoolean>;
860
864
  }, z.core.$strict>>;
861
865
  }, z.core.$strict>;
862
866
  type ConfigProfile = z.infer<typeof ConfigProfileSchema>;
@@ -1063,6 +1067,8 @@ declare const DirectoryRuleSchema: z.ZodObject<{
1063
1067
  headroom: z.ZodOptional<z.ZodBoolean>;
1064
1068
  trackUsage: z.ZodOptional<z.ZodBoolean>;
1065
1069
  claudeVersion: z.ZodOptional<z.ZodString>;
1070
+ delay: z.ZodOptional<z.ZodString>;
1071
+ pause: z.ZodOptional<z.ZodBoolean>;
1066
1072
  }, z.core.$strict>>;
1067
1073
  path: z.ZodString;
1068
1074
  configProfile: z.ZodOptional<z.ZodString>;
@@ -1242,6 +1248,8 @@ declare const DirectoryRulesSchema: z.ZodObject<{
1242
1248
  headroom: z.ZodOptional<z.ZodBoolean>;
1243
1249
  trackUsage: z.ZodOptional<z.ZodBoolean>;
1244
1250
  claudeVersion: z.ZodOptional<z.ZodString>;
1251
+ delay: z.ZodOptional<z.ZodString>;
1252
+ pause: z.ZodOptional<z.ZodBoolean>;
1245
1253
  }, z.core.$strict>>;
1246
1254
  path: z.ZodString;
1247
1255
  configProfile: z.ZodOptional<z.ZodString>;
@@ -1422,6 +1430,8 @@ declare const PortableConfigSchema: z.ZodObject<{
1422
1430
  headroom: z.ZodOptional<z.ZodBoolean>;
1423
1431
  trackUsage: z.ZodOptional<z.ZodBoolean>;
1424
1432
  claudeVersion: z.ZodOptional<z.ZodString>;
1433
+ delay: z.ZodOptional<z.ZodString>;
1434
+ pause: z.ZodOptional<z.ZodBoolean>;
1425
1435
  }, z.core.$strict>>;
1426
1436
  configProfile: z.ZodOptional<z.ZodString>;
1427
1437
  identity: z.ZodOptional<z.ZodString>;
@@ -1626,6 +1636,8 @@ declare const GlobalConfigSchema: z.ZodObject<{
1626
1636
  headroom: z.ZodOptional<z.ZodBoolean>;
1627
1637
  trackUsage: z.ZodOptional<z.ZodBoolean>;
1628
1638
  claudeVersion: z.ZodOptional<z.ZodString>;
1639
+ delay: z.ZodOptional<z.ZodString>;
1640
+ pause: z.ZodOptional<z.ZodBoolean>;
1629
1641
  }, z.core.$strict>>;
1630
1642
  headroom: z.ZodOptional<z.ZodObject<{
1631
1643
  source: z.ZodOptional<z.ZodString>;
@@ -5963,6 +5975,8 @@ declare function createConfigApiRouter(deps: ConfigApiDeps): {
5963
5975
  headroom: zod.ZodOptional<zod.ZodBoolean>;
5964
5976
  trackUsage: zod.ZodOptional<zod.ZodBoolean>;
5965
5977
  claudeVersion: zod.ZodOptional<zod.ZodString>;
5978
+ delay: zod.ZodOptional<zod.ZodString>;
5979
+ pause: zod.ZodOptional<zod.ZodBoolean>;
5966
5980
  }, zod_v4_core.$strict>>;
5967
5981
  }, zod_v4_core.$strict>;
5968
5982
  }, zod_v4_core.$strict>, MergedErrorMap<$ErrorMap, TErrorMap>>;
@@ -5979,6 +5993,8 @@ declare function createConfigApiRouter(deps: ConfigApiDeps): {
5979
5993
  trackUsage: zod.ZodOptional<zod.ZodBoolean>;
5980
5994
  provider: zod.ZodOptional<zod.ZodUnion<readonly [zod.ZodString, zod.ZodLiteral<false>]>>;
5981
5995
  claudeVersion: zod.ZodOptional<zod.ZodUnion<readonly [zod.ZodString, zod.ZodLiteral<false>]>>;
5996
+ delay: zod.ZodOptional<zod.ZodUnion<readonly [zod.ZodString, zod.ZodLiteral<false>]>>;
5997
+ pause: zod.ZodOptional<zod.ZodBoolean>;
5982
5998
  }, zod_v4_core.$strict>>;
5983
5999
  }, zod_v4_core.$strict>, zod.ZodObject<{
5984
6000
  action: zod.ZodLiteral<"updated">;
@@ -6082,6 +6098,8 @@ declare function createConfigApiRouter(deps: ConfigApiDeps): {
6082
6098
  headroom: zod.ZodOptional<zod.ZodBoolean>;
6083
6099
  trackUsage: zod.ZodOptional<zod.ZodBoolean>;
6084
6100
  claudeVersion: zod.ZodOptional<zod.ZodString>;
6101
+ delay: zod.ZodOptional<zod.ZodString>;
6102
+ pause: zod.ZodOptional<zod.ZodBoolean>;
6085
6103
  }, zod_v4_core.$strict>>;
6086
6104
  }, zod_v4_core.$strict>;
6087
6105
  }, zod_v4_core.$strict>, MergedErrorMap<$ErrorMap, TErrorMap>>;
@@ -6682,6 +6700,8 @@ declare function createConfigApiRouter(deps: ConfigApiDeps): {
6682
6700
  headroom: zod.ZodOptional<zod.ZodBoolean>;
6683
6701
  trackUsage: zod.ZodOptional<zod.ZodBoolean>;
6684
6702
  claudeVersion: zod.ZodOptional<zod.ZodString>;
6703
+ delay: zod.ZodOptional<zod.ZodString>;
6704
+ pause: zod.ZodOptional<zod.ZodBoolean>;
6685
6705
  }, zod_v4_core.$strict>>;
6686
6706
  path: zod.ZodString;
6687
6707
  configProfile: zod.ZodOptional<zod.ZodString>;
@@ -6866,6 +6886,8 @@ declare function createConfigApiRouter(deps: ConfigApiDeps): {
6866
6886
  headroom: zod.ZodOptional<zod.ZodBoolean>;
6867
6887
  trackUsage: zod.ZodOptional<zod.ZodBoolean>;
6868
6888
  claudeVersion: zod.ZodOptional<zod.ZodString>;
6889
+ delay: zod.ZodOptional<zod.ZodString>;
6890
+ pause: zod.ZodOptional<zod.ZodBoolean>;
6869
6891
  }, zod_v4_core.$strict>>;
6870
6892
  path: zod.ZodString;
6871
6893
  configProfile: zod.ZodOptional<zod.ZodString>;
@@ -7195,6 +7217,10 @@ interface ResolvedLaunchFlags {
7195
7217
  readonly headroom: boolean;
7196
7218
  /** Whether the launch routes through the front door so its requests are recorded, even with no provider and no headroom. */
7197
7219
  readonly trackUsage: boolean;
7220
+ /** Whether the launcher waits for a key press after its own output before it starts claude. */
7221
+ readonly pause: boolean;
7222
+ /** How long the launcher waits after its own output before it starts claude, in milliseconds; zero for no wait. */
7223
+ readonly delayMs: number;
7198
7224
  }
7199
7225
 
7200
7226
  /** How a supervised launch names its conversation to claude: `start` begins one under the launch's id, `resume` continues the one with that id, `as-given` leaves the caller's own `--resume <id>` as written. */
@@ -7210,6 +7236,18 @@ interface SupervisedLaunch {
7210
7236
  readonly settings?: string;
7211
7237
  }
7212
7238
 
7239
+ /** The effects a hold needs, so it runs against fakes in tests. */
7240
+ interface HoldPort {
7241
+ /** Whether a person is watching: standard input and standard output are both terminals. A launch nobody watches is never held. */
7242
+ readonly attended: () => boolean;
7243
+ /** Blocks for `ms` milliseconds. */
7244
+ readonly sleep: (ms: number) => void;
7245
+ /** Blocks until one key is pressed, and says whether it was the interrupt key (Ctrl-C), which a terminal in the mode this reads in delivers as a byte and not as a signal. */
7246
+ readonly waitForKey: () => "key" | "interrupt";
7247
+ }
7248
+ /** What a hold decided: carry on with the launch, or the person cancelled it. */
7249
+ type HoldOutcome = "go" | "cancelled";
7250
+
7213
7251
  /**
7214
7252
  * Everything the launch-time update check needs from its host, injected so tests run it against scripted answers and no launch ever reaches GitHub by accident. Deliberately narrower than `UpdatePorts`: the launch path never downloads anything (the detached `agent-shim update` does), so only the release check, the cooldown stamp, the clock, the background spawn and the terminal are wired.
7215
7253
  */
@@ -7294,6 +7332,8 @@ interface PrepareLaunchParams {
7294
7332
  readonly supervised?: SupervisedLaunch;
7295
7333
  /** Wires the launch-time update check behind `update.mode`. Omitted by a caller that cannot resolve releases, re-invoke this binary, or write to the terminal; a mode of `notify` or `auto` with no port wired simply checks nothing. */
7296
7334
  readonly update?: UpdateLaunchPort;
7335
+ /** Waits for the person where the launch's `delay` and `pause` settings ask. Omitted by a caller that has no terminal to wait on, and then the launch is never held. */
7336
+ readonly hold?: HoldPort;
7297
7337
  /** Whether an identity has a stored login Claude Code can use (a Keychain item or a credentials file). Absent when the caller cannot ask, in which case a launch assumes it does. */
7298
7338
  readonly hasStoredLogin?: (identity: string) => boolean;
7299
7339
  }
@@ -7349,6 +7389,8 @@ interface LaunchPlan {
7349
7389
  readonly decision: LaunchDecision;
7350
7390
  /** Marks the moment this plan's child is spawned: the launch-time update check suppresses its notify line from then on, since a line printed after the child took over the terminal would land mid-session. Call it immediately before spawning; it is safe to call more than once. */
7351
7391
  readonly markChildStarted: () => void;
7392
+ /** Holds the launch as its `delay` and `pause` settings say, once the launcher has printed everything it will: call it just before spawning the child. `cancelled` means the person pressed Ctrl-C at the pause, and the child must not start. A launch with no hold port, or nobody watching, goes at once. */
7393
+ readonly hold: () => HoldOutcome;
7352
7394
  }
7353
7395
  /**
7354
7396
  * Prepares one `claude` launch, in order:
@@ -7468,6 +7510,8 @@ declare function createLaunchApiRouter(deps: LaunchApiDeps): {
7468
7510
  remoteControl: zod.ZodBoolean;
7469
7511
  headroom: zod.ZodBoolean;
7470
7512
  trackUsage: zod.ZodBoolean;
7513
+ pause: zod.ZodBoolean;
7514
+ delayMs: zod.ZodNumber;
7471
7515
  }, zod_v4_core.$strict>;
7472
7516
  claudeVersion: zod.ZodOptional<zod.ZodObject<{
7473
7517
  version: zod.ZodString;
@@ -8584,6 +8628,8 @@ declare function createDoorApiRouter(deps: DoorApiDeps): {
8584
8628
  remoteControl: zod.ZodBoolean;
8585
8629
  headroom: zod.ZodBoolean;
8586
8630
  trackUsage: zod.ZodBoolean;
8631
+ pause: zod.ZodBoolean;
8632
+ delayMs: zod.ZodNumber;
8587
8633
  }, zod_v4_core.$strict>;
8588
8634
  claudeVersion: zod.ZodOptional<zod.ZodObject<{
8589
8635
  version: zod.ZodString;
@@ -8951,6 +8997,8 @@ declare function createDoorApiRouter(deps: DoorApiDeps): {
8951
8997
  headroom: zod.ZodOptional<zod.ZodBoolean>;
8952
8998
  trackUsage: zod.ZodOptional<zod.ZodBoolean>;
8953
8999
  claudeVersion: zod.ZodOptional<zod.ZodString>;
9000
+ delay: zod.ZodOptional<zod.ZodString>;
9001
+ pause: zod.ZodOptional<zod.ZodBoolean>;
8954
9002
  }, zod_v4_core.$strict>>;
8955
9003
  }, zod_v4_core.$strict>;
8956
9004
  }, zod_v4_core.$strict>, MergedErrorMap<$ErrorMap, TErrorMap>>;
@@ -8967,6 +9015,8 @@ declare function createDoorApiRouter(deps: DoorApiDeps): {
8967
9015
  trackUsage: zod.ZodOptional<zod.ZodBoolean>;
8968
9016
  provider: zod.ZodOptional<zod.ZodUnion<readonly [zod.ZodString, zod.ZodLiteral<false>]>>;
8969
9017
  claudeVersion: zod.ZodOptional<zod.ZodUnion<readonly [zod.ZodString, zod.ZodLiteral<false>]>>;
9018
+ delay: zod.ZodOptional<zod.ZodUnion<readonly [zod.ZodString, zod.ZodLiteral<false>]>>;
9019
+ pause: zod.ZodOptional<zod.ZodBoolean>;
8970
9020
  }, zod_v4_core.$strict>>;
8971
9021
  }, zod_v4_core.$strict>, zod.ZodObject<{
8972
9022
  action: zod.ZodLiteral<"updated">;
@@ -9070,6 +9120,8 @@ declare function createDoorApiRouter(deps: DoorApiDeps): {
9070
9120
  headroom: zod.ZodOptional<zod.ZodBoolean>;
9071
9121
  trackUsage: zod.ZodOptional<zod.ZodBoolean>;
9072
9122
  claudeVersion: zod.ZodOptional<zod.ZodString>;
9123
+ delay: zod.ZodOptional<zod.ZodString>;
9124
+ pause: zod.ZodOptional<zod.ZodBoolean>;
9073
9125
  }, zod_v4_core.$strict>>;
9074
9126
  }, zod_v4_core.$strict>;
9075
9127
  }, zod_v4_core.$strict>, MergedErrorMap<$ErrorMap, TErrorMap>>;
@@ -9670,6 +9722,8 @@ declare function createDoorApiRouter(deps: DoorApiDeps): {
9670
9722
  headroom: zod.ZodOptional<zod.ZodBoolean>;
9671
9723
  trackUsage: zod.ZodOptional<zod.ZodBoolean>;
9672
9724
  claudeVersion: zod.ZodOptional<zod.ZodString>;
9725
+ delay: zod.ZodOptional<zod.ZodString>;
9726
+ pause: zod.ZodOptional<zod.ZodBoolean>;
9673
9727
  }, zod_v4_core.$strict>>;
9674
9728
  path: zod.ZodString;
9675
9729
  configProfile: zod.ZodOptional<zod.ZodString>;
@@ -9854,6 +9908,8 @@ declare function createDoorApiRouter(deps: DoorApiDeps): {
9854
9908
  headroom: zod.ZodOptional<zod.ZodBoolean>;
9855
9909
  trackUsage: zod.ZodOptional<zod.ZodBoolean>;
9856
9910
  claudeVersion: zod.ZodOptional<zod.ZodString>;
9911
+ delay: zod.ZodOptional<zod.ZodString>;
9912
+ pause: zod.ZodOptional<zod.ZodBoolean>;
9857
9913
  }, zod_v4_core.$strict>>;
9858
9914
  path: zod.ZodString;
9859
9915
  configProfile: zod.ZodOptional<zod.ZodString>;
@@ -11078,6 +11134,8 @@ declare const ConfigProfileAddOutputSchema: z.ZodObject<{
11078
11134
  headroom: z.ZodOptional<z.ZodBoolean>;
11079
11135
  trackUsage: z.ZodOptional<z.ZodBoolean>;
11080
11136
  claudeVersion: z.ZodOptional<z.ZodString>;
11137
+ delay: z.ZodOptional<z.ZodString>;
11138
+ pause: z.ZodOptional<z.ZodBoolean>;
11081
11139
  }, z.core.$strict>>;
11082
11140
  }, z.core.$strict>;
11083
11141
  }, z.core.$strict>;
@@ -11095,6 +11153,8 @@ declare const ConfigProfileSetInputSchema: z.ZodObject<{
11095
11153
  trackUsage: z.ZodOptional<z.ZodBoolean>;
11096
11154
  provider: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<false>]>>;
11097
11155
  claudeVersion: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<false>]>>;
11156
+ delay: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<false>]>>;
11157
+ pause: z.ZodOptional<z.ZodBoolean>;
11098
11158
  }, z.core.$strict>>;
11099
11159
  }, z.core.$strict>;
11100
11160
  declare const ConfigProfileSetOutputSchema: z.ZodObject<{
@@ -11199,6 +11259,8 @@ declare const ConfigProfileSetOutputSchema: z.ZodObject<{
11199
11259
  headroom: z.ZodOptional<z.ZodBoolean>;
11200
11260
  trackUsage: z.ZodOptional<z.ZodBoolean>;
11201
11261
  claudeVersion: z.ZodOptional<z.ZodString>;
11262
+ delay: z.ZodOptional<z.ZodString>;
11263
+ pause: z.ZodOptional<z.ZodBoolean>;
11202
11264
  }, z.core.$strict>>;
11203
11265
  }, z.core.$strict>;
11204
11266
  }, z.core.$strict>;
@@ -11801,6 +11863,8 @@ declare const ConfigRuleAddOutputSchema: z.ZodObject<{
11801
11863
  headroom: z.ZodOptional<z.ZodBoolean>;
11802
11864
  trackUsage: z.ZodOptional<z.ZodBoolean>;
11803
11865
  claudeVersion: z.ZodOptional<z.ZodString>;
11866
+ delay: z.ZodOptional<z.ZodString>;
11867
+ pause: z.ZodOptional<z.ZodBoolean>;
11804
11868
  }, z.core.$strict>>;
11805
11869
  path: z.ZodString;
11806
11870
  configProfile: z.ZodOptional<z.ZodString>;
@@ -11987,6 +12051,8 @@ declare const ConfigRuleSetOutputSchema: z.ZodObject<{
11987
12051
  headroom: z.ZodOptional<z.ZodBoolean>;
11988
12052
  trackUsage: z.ZodOptional<z.ZodBoolean>;
11989
12053
  claudeVersion: z.ZodOptional<z.ZodString>;
12054
+ delay: z.ZodOptional<z.ZodString>;
12055
+ pause: z.ZodOptional<z.ZodBoolean>;
11990
12056
  }, z.core.$strict>>;
11991
12057
  path: z.ZodString;
11992
12058
  configProfile: z.ZodOptional<z.ZodString>;
@@ -12473,6 +12539,8 @@ declare const LaunchResolveOutputSchema: z.ZodObject<{
12473
12539
  remoteControl: z.ZodBoolean;
12474
12540
  headroom: z.ZodBoolean;
12475
12541
  trackUsage: z.ZodBoolean;
12542
+ pause: z.ZodBoolean;
12543
+ delayMs: z.ZodNumber;
12476
12544
  }, z.core.$strict>;
12477
12545
  claudeVersion: z.ZodOptional<z.ZodObject<{
12478
12546
  version: z.ZodString;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-shim",
3
- "version": "11.27.0",
3
+ "version": "11.28.0",
4
4
  "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.",
5
5
  "license": "MIT",
6
6
  "author": "Joseph Mearman <joseph@mearman.co.uk>",