claude-use 9.13.0 → 9.15.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
@@ -228,7 +228,15 @@ function isCodexProvider(provider) {
228
228
  function poolMemberIdentity(member) {
229
229
  return typeof member === "string" ? member : member.identity;
230
230
  }
231
- var import_node_path2, import_zod, import_trilean, CATEGORY_NAMES, OVERRIDABLE_CATEGORIES, CategoryMapSchema, DURATION_RE, DurationSchema, WhenConditionObjectSchema, WhenSchema, EntryValueSchema, ENTRY_KEY_RE, EntriesSchema, LaunchSchema, CREDENTIAL_TARGETS, PROVIDER_CREDENTIAL_TARGETS, CREDENTIAL_TARGET_VARS, ArgvSchema, CommandSourceOptions, EnvCredentialSourceSchema, FileCredentialSourceSchema, CommandCredentialSourceSchema, OpCredentialSourceSchema, KeychainCredentialSourceSchema, LiteralCredentialSourceSchema, CredentialSourceSchema, RemoteCredentialSourceSchema, CREDENTIAL_CACHE_STORES, CredentialCacheSchema, CredentialSchema, ProviderCredentialSchema, RESERVED_PROVIDER_ENV_KEYS, ProviderEnvSchema, PROVIDER_KINDS, CODEX_EFFORTS, CODEX_LOGINS, CODEX_DEFAULT_TIER_MODELS, CodexProviderConfigSchema, ProviderRouteSchema, HttpProviderSchema, CodexProviderSchema, ProviderSchema, ConfigProfileSchema, POOL_SELECTOR_PREFIX, POOL_NAME_PATTERN, IDENTITY_NAME_PATTERN, PoolNameSchema, SELECTOR_RE, IdentitySelectorSchema, PoolMemberSchema, POOL_PREFERENCES, PoolPreferenceSchema, PoolSchema, DirectoryRuleSchema, DirectoryRulesSchema, PortableConfigSchema, HEADROOM_MODES, HEADROOM_CCR_MODES, HEADROOM_ROLLOUT_CHANNELS, INTERCEPT_CHANNELS, READ_MATURATION_CHANNELS, HeadroomGlobalConfigObjectSchema, HeadroomGlobalConfigSchema, HEADROOM_DEFAULT_SOURCE, HEADROOM_DEFAULT_IDLE_SHUTDOWN_MINUTES, FrontDoorGlobalConfigSchema, UPDATE_MODES, UpdateGlobalConfigSchema, GlobalConfigSchema, IdentitySchema, CategoryClassificationSchema, CategoryClassificationOverlaySchema, SHIPPED_CATEGORY_DEFAULTS;
231
+ function isTimeZone(name) {
232
+ try {
233
+ new Intl.DateTimeFormat("en", { timeZone: name });
234
+ return true;
235
+ } catch {
236
+ return false;
237
+ }
238
+ }
239
+ var import_node_path2, import_zod, import_trilean, CATEGORY_NAMES, OVERRIDABLE_CATEGORIES, CategoryMapSchema, DURATION_RE, DurationSchema, WhenConditionObjectSchema, WhenSchema, EntryValueSchema, ENTRY_KEY_RE, EntriesSchema, LaunchSchema, CREDENTIAL_TARGETS, PROVIDER_CREDENTIAL_TARGETS, CREDENTIAL_TARGET_VARS, ArgvSchema, CommandSourceOptions, EnvCredentialSourceSchema, FileCredentialSourceSchema, CommandCredentialSourceSchema, OpCredentialSourceSchema, KeychainCredentialSourceSchema, LiteralCredentialSourceSchema, CredentialSourceSchema, RemoteCredentialSourceSchema, CREDENTIAL_CACHE_STORES, CredentialCacheSchema, CredentialSchema, ProviderCredentialSchema, RESERVED_PROVIDER_ENV_KEYS, ProviderEnvSchema, PROVIDER_KINDS, CODEX_EFFORTS, CODEX_LOGINS, CODEX_DEFAULT_TIER_MODELS, CodexProviderConfigSchema, ProviderRouteSchema, HttpProviderSchema, CodexProviderSchema, ProviderSchema, ConfigProfileSchema, POOL_SELECTOR_PREFIX, POOL_NAME_PATTERN, IDENTITY_NAME_PATTERN, PoolNameSchema, SELECTOR_RE, IdentitySelectorSchema, PoolMemberSchema, POOL_PREFERENCES, PoolPreferenceSchema, PoolSchema, WEEKDAYS, AnchorSchema, JOB_WINDOWS, JobTriggerSchema, JobTargetSchema, JobSchema, DirectoryRuleSchema, DirectoryRulesSchema, PortableConfigSchema, HEADROOM_MODES, HEADROOM_CCR_MODES, HEADROOM_ROLLOUT_CHANNELS, INTERCEPT_CHANNELS, READ_MATURATION_CHANNELS, HeadroomGlobalConfigObjectSchema, HeadroomGlobalConfigSchema, HEADROOM_DEFAULT_SOURCE, HEADROOM_DEFAULT_IDLE_SHUTDOWN_MINUTES, FrontDoorGlobalConfigSchema, UPDATE_MODES, UpdateGlobalConfigSchema, GlobalConfigSchema, IdentitySchema, CategoryClassificationSchema, CategoryClassificationOverlaySchema, SHIPPED_CATEGORY_DEFAULTS;
232
240
  var init_schema = __esm({
233
241
  "src/config/schema.ts"() {
234
242
  "use strict";
@@ -399,6 +407,25 @@ var init_schema = __esm({
399
407
  identities: import_zod.z.array(PoolMemberSchema).min(1).refine((members) => new Set(members.map(poolMemberIdentity)).size === members.length, { message: "pool members must be unique" }),
400
408
  preference: PoolPreferenceSchema.optional()
401
409
  });
410
+ WEEKDAYS = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"];
411
+ AnchorSchema = import_zod.z.strictObject({
412
+ days: import_zod.z.array(import_zod.z.enum(WEEKDAYS)).min(1).refine((days) => new Set(days).size === days.length, "an anchor names each weekday at most once"),
413
+ time: import_zod.z.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/, "a 24-hour time such as 06:00"),
414
+ timeZone: import_zod.z.string().refine(isTimeZone, "an IANA time zone such as Europe/London").optional()
415
+ });
416
+ JOB_WINDOWS = ["fiveHour", "sevenDay"];
417
+ JobTriggerSchema = import_zod.z.union([import_zod.z.strictObject({ at: import_zod.z.array(AnchorSchema).min(1) }), import_zod.z.strictObject({ beforeReset: import_zod.z.enum(JOB_WINDOWS), lead: import_zod.z.string().regex(DURATION_RE) })]);
418
+ JobTargetSchema = import_zod.z.union([import_zod.z.strictObject({ identity: IdentitySelectorSchema }), import_zod.z.strictObject({ pool: PoolNameSchema })]);
419
+ JobSchema = import_zod.z.strictObject({
420
+ target: JobTargetSchema,
421
+ trigger: JobTriggerSchema,
422
+ prompt: import_zod.z.string().min(1),
423
+ /** The absolute directory the run works in. */
424
+ cwd: import_zod.z.string().min(1),
425
+ timeout: import_zod.z.string().regex(DURATION_RE),
426
+ model: import_zod.z.string().min(1).optional(),
427
+ allowedTools: import_zod.z.array(import_zod.z.string().min(1)).min(1).optional()
428
+ });
402
429
  DirectoryRuleSchema = ConfigProfileSchema.omit({ description: true }).extend({
403
430
  path: import_zod.z.string().min(1),
404
431
  configProfile: import_zod.z.string().min(1).optional(),
@@ -466,14 +493,17 @@ var init_schema = __esm({
466
493
  headroom: HeadroomGlobalConfigSchema.optional(),
467
494
  frontdoor: FrontDoorGlobalConfigSchema.optional(),
468
495
  update: UpdateGlobalConfigSchema.optional(),
469
- pools: import_zod.z.record(PoolNameSchema, PoolSchema).optional()
496
+ pools: import_zod.z.record(PoolNameSchema, PoolSchema).optional(),
497
+ jobs: import_zod.z.record(PoolNameSchema, JobSchema).optional()
470
498
  });
471
499
  IdentitySchema = import_zod.z.strictObject({
472
500
  $schema: import_zod.z.string().optional(),
473
501
  name: import_zod.z.string().min(1).regex(/^[A-Za-z0-9][A-Za-z0-9._@-]*$/),
474
502
  defaultConfigProfile: import_zod.z.string().min(1).optional(),
475
503
  allowAmbientCredential: import_zod.z.boolean().default(false),
476
- credential: CredentialSchema.optional()
504
+ credential: CredentialSchema.optional(),
505
+ /** When this identity's five-hour window should be open: the front door opens one at each anchor if none is. Absent, nothing is opened on a schedule. */
506
+ anchors: import_zod.z.array(AnchorSchema).min(1).optional()
477
507
  });
478
508
  CategoryClassificationSchema = import_zod.z.strictObject({
479
509
  $schema: import_zod.z.string().optional(),
@@ -2663,7 +2693,7 @@ var init_package = __esm({
2663
2693
  "package.json"() {
2664
2694
  package_default = {
2665
2695
  name: "claude-use",
2666
- version: "9.13.0",
2696
+ version: "9.15.0",
2667
2697
  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.",
2668
2698
  license: "MIT",
2669
2699
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -5307,6 +5337,9 @@ function buildLayoutPaths(root) {
5307
5337
  usageLogDir: import_node_path22.default.join(root, "usage", "log"),
5308
5338
  usageSnapshotsDir: import_node_path22.default.join(root, "usage", "snapshots"),
5309
5339
  usagePicksFile: import_node_path22.default.join(root, "usage", "picks.json"),
5340
+ usageAnchorsFile: import_node_path22.default.join(root, "usage", "anchors.json"),
5341
+ usageJobsFile: import_node_path22.default.join(root, "usage", "jobs.json"),
5342
+ jobLogsDir: import_node_path22.default.join(root, "logs", "jobs"),
5310
5343
  mcpPermissionsFile: import_node_path22.default.join(root, "mcp", "permissions.json")
5311
5344
  };
5312
5345
  }
@@ -7809,6 +7842,57 @@ var init_anthropicUsageRefresh = __esm({
7809
7842
  }
7810
7843
  });
7811
7844
 
7845
+ // src/usage/identityClaude.ts
7846
+ function definedEnvironment(env) {
7847
+ return Object.fromEntries(Object.entries(env).flatMap(([name, value]) => value === void 0 ? [] : [[name, value]]));
7848
+ }
7849
+ function identityLaunchArgv(identity, flags) {
7850
+ return [`@${identity}`, IDENTITY_ONLY_FLAG, ...flags];
7851
+ }
7852
+ async function withIdentityClaude(params, identity, flags, use) {
7853
+ const refusals = [];
7854
+ const plan = prepareLaunch(
7855
+ realPrepareLaunchParams(params.paths, {
7856
+ proc: {
7857
+ env: Object.fromEntries(Object.entries(process.env).filter(([name]) => name !== CONFIG_DIR_VARIABLE)),
7858
+ argv: [...identityLaunchArgv(identity, flags)],
7859
+ exit: (code) => {
7860
+ throw new LaunchRefusedError(refusals.join("\n") || `the launch was refused (exit ${String(code)})`, code);
7861
+ }
7862
+ },
7863
+ log: {
7864
+ info: () => void 0,
7865
+ warn: () => void 0,
7866
+ error: (message) => {
7867
+ refusals.push(message);
7868
+ }
7869
+ },
7870
+ spawnDaemon: params.spawnDaemon,
7871
+ farm: buildFarmRuntime(params.paths, params.cwd)
7872
+ })
7873
+ );
7874
+ const abort = new AbortController();
7875
+ const timer = setTimeout(() => {
7876
+ abort.abort();
7877
+ }, params.timeoutMs);
7878
+ try {
7879
+ return await use({ bin: plan.bin, env: definedEnvironment(plan.env), cwd: params.cwd, abort });
7880
+ } finally {
7881
+ clearTimeout(timer);
7882
+ plan.release();
7883
+ }
7884
+ }
7885
+ var CONFIG_DIR_VARIABLE, IDENTITY_ONLY_FLAG;
7886
+ var init_identityClaude = __esm({
7887
+ "src/usage/identityClaude.ts"() {
7888
+ "use strict";
7889
+ init_launchWiring();
7890
+ init_launcher();
7891
+ CONFIG_DIR_VARIABLE = "CLAUDE_CONFIG_DIR";
7892
+ IDENTITY_ONLY_FLAG = "--no-provider";
7893
+ }
7894
+ });
7895
+
7812
7896
  // src/usage/providerQuota.ts
7813
7897
  var import_zod25, MS_PER_SECOND7, SECONDS_PER_HOUR, HOURS_PER_DAY4, 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;
7814
7898
  var init_providerQuota = __esm({
@@ -7879,9 +7963,6 @@ var realAnthropicUsageProbe_exports = {};
7879
7963
  __export(realAnthropicUsageProbe_exports, {
7880
7964
  createRealAnthropicUsageRefresher: () => createRealAnthropicUsageRefresher
7881
7965
  });
7882
- function definedEnvironment(env) {
7883
- return Object.fromEntries(Object.entries(env).flatMap(([name, value]) => value === void 0 ? [] : [[name, value]]));
7884
- }
7885
7966
  function idlePrompt(signal) {
7886
7967
  return {
7887
7968
  [Symbol.asyncIterator]: () => ({
@@ -7894,58 +7975,28 @@ function idlePrompt(signal) {
7894
7975
  };
7895
7976
  }
7896
7977
  function createRealAnthropicUsageProbe(params) {
7897
- return async (identity) => {
7898
- const refusals = [];
7899
- const plan = prepareLaunch(
7900
- realPrepareLaunchParams(params.paths, {
7901
- proc: {
7902
- env: Object.fromEntries(Object.entries(process.env).filter(([name]) => name !== CONFIG_DIR_VARIABLE)),
7903
- argv: [`@${identity}`, ...PROBE_LAUNCH_FLAGS],
7904
- exit: (code) => {
7905
- throw new LaunchRefusedError(refusals.join("\n") || `the launch was refused (exit ${String(code)})`, code);
7906
- }
7907
- },
7908
- log: {
7909
- info: () => void 0,
7910
- warn: () => void 0,
7911
- error: (message) => {
7912
- refusals.push(message);
7913
- }
7914
- },
7915
- spawnDaemon: params.spawnDaemon,
7916
- farm: buildFarmRuntime(params.paths, params.cwd)
7917
- })
7918
- );
7978
+ return async (identity) => await withIdentityClaude(params, identity, PROBE_LAUNCH_FLAGS, async ({ bin, env, cwd, abort }) => {
7919
7979
  const { query } = await import("@anthropic-ai/claude-agent-sdk");
7920
- const abort = new AbortController();
7921
- const timer = setTimeout(() => {
7922
- abort.abort();
7923
- }, params.timeoutMs);
7924
- try {
7925
- const session = query({
7926
- prompt: idlePrompt(abort.signal),
7927
- options: {
7928
- pathToClaudeCodeExecutable: plan.bin,
7929
- env: definedEnvironment(plan.env),
7930
- cwd: params.cwd,
7931
- abortController: abort,
7932
- settingSources: [],
7933
- mcpServers: {},
7934
- strictMcpConfig: true,
7935
- persistSession: false
7936
- }
7937
- });
7938
- try {
7939
- const report = await session.usage_EXPERIMENTAL_MAY_CHANGE_DO_NOT_RELY_ON_THIS_API_YET({ skipBehaviors: true });
7940
- return unifiedFromReportedLimits(report.rate_limits_available ? report.rate_limits : null);
7941
- } finally {
7942
- session.close();
7980
+ const session = query({
7981
+ prompt: idlePrompt(abort.signal),
7982
+ options: {
7983
+ pathToClaudeCodeExecutable: bin,
7984
+ env,
7985
+ cwd,
7986
+ abortController: abort,
7987
+ settingSources: [],
7988
+ mcpServers: {},
7989
+ strictMcpConfig: true,
7990
+ persistSession: false
7943
7991
  }
7992
+ });
7993
+ try {
7994
+ const report = await session.usage_EXPERIMENTAL_MAY_CHANGE_DO_NOT_RELY_ON_THIS_API_YET({ skipBehaviors: true });
7995
+ return unifiedFromReportedLimits(report.rate_limits_available ? report.rate_limits : null);
7944
7996
  } finally {
7945
- clearTimeout(timer);
7946
- plan.release();
7997
+ session.close();
7947
7998
  }
7948
- };
7999
+ });
7949
8000
  }
7950
8001
  function createRealAnthropicUsageRefresher(params) {
7951
8002
  return createAnthropicUsageRefresher({
@@ -7958,18 +8009,16 @@ function createRealAnthropicUsageRefresher(params) {
7958
8009
  concurrency: (0, import_node_os8.availableParallelism)()
7959
8010
  });
7960
8011
  }
7961
- var import_node_os8, PROBE_LAUNCH_FLAGS, CONFIG_DIR_VARIABLE;
8012
+ var import_node_os8, PROBE_LAUNCH_FLAGS;
7962
8013
  var init_realAnthropicUsageProbe = __esm({
7963
8014
  "src/usage/realAnthropicUsageProbe.ts"() {
7964
8015
  "use strict";
7965
8016
  import_node_os8 = require("node:os");
7966
- init_launchWiring();
7967
- init_launcher();
7968
8017
  init_anthropicUsageRefresh();
8018
+ init_identityClaude();
7969
8019
  init_middleware();
7970
8020
  init_quotaRefresh();
7971
8021
  PROBE_LAUNCH_FLAGS = ["--no-headroom", "--no-remote-control"];
7972
- CONFIG_DIR_VARIABLE = "CLAUDE_CONFIG_DIR";
7973
8022
  }
7974
8023
  });
7975
8024
 
@@ -12789,6 +12838,12 @@ function listIdentities(paths) {
12789
12838
  }
12790
12839
  return result;
12791
12840
  }
12841
+ function setIdentityAnchors(paths, identityName, anchors) {
12842
+ if (!identityExists(paths, identityName)) {
12843
+ throw new IdentityNotFoundError(identityName);
12844
+ }
12845
+ return applyPatch(identityJsonPath(paths, identityName), IdentitySchema, { anchors: anchors === void 0 ? void 0 : [...anchors] });
12846
+ }
12792
12847
  function setDefaultConfigProfile(paths, identityName, profileName) {
12793
12848
  if (!identityExists(paths, identityName)) {
12794
12849
  throw new IdentityNotFoundError(identityName);
@@ -13893,7 +13948,8 @@ var IdentityValueSchema = import_zod22.z.strictObject({
13893
13948
  name: import_zod22.z.string(),
13894
13949
  defaultConfigProfile: import_zod22.z.string().optional(),
13895
13950
  allowAmbientCredential: import_zod22.z.boolean(),
13896
- credential: CredentialSummarySchema2.optional()
13951
+ credential: CredentialSummarySchema2.optional(),
13952
+ anchors: import_zod22.z.array(AnchorSchema).optional()
13897
13953
  });
13898
13954
  var ProfileValueSchema = ConfigProfileSchema.omit({ $schema: true });
13899
13955
  var ProviderValueSchema = import_zod22.z.strictObject({
@@ -13911,7 +13967,9 @@ var ConfigIdentitySetInputSchema = import_zod22.z.strictObject({
13911
13967
  name: import_zod22.z.string().min(1),
13912
13968
  defaultConfigProfile: import_zod22.z.union([import_zod22.z.string().min(1), import_zod22.z.literal(false)]).optional(),
13913
13969
  allowAmbientCredential: import_zod22.z.boolean().optional(),
13914
- credential: import_zod22.z.union([import_zod22.z.literal(false), CredentialWriteSchema(CREDENTIAL_TARGETS)]).optional()
13970
+ credential: import_zod22.z.union([import_zod22.z.literal(false), CredentialWriteSchema(CREDENTIAL_TARGETS)]).optional(),
13971
+ /** `false` removes the anchors; a list replaces them. */
13972
+ anchors: import_zod22.z.union([import_zod22.z.literal(false), import_zod22.z.array(AnchorSchema).min(1)]).optional()
13915
13973
  });
13916
13974
  var ConfigIdentitySetOutputSchema = storedMutationOutput("identity", "updated", IdentityValueSchema);
13917
13975
  var ConfigIdentityRemoveInputSchema = import_zod22.z.strictObject({ name: import_zod22.z.string().min(1), confirm: RemovalConfirmationSchema });
@@ -14032,7 +14090,8 @@ function identityValue(name, paths) {
14032
14090
  name: identity.name,
14033
14091
  ...identity.defaultConfigProfile === void 0 ? {} : { defaultConfigProfile: identity.defaultConfigProfile },
14034
14092
  allowAmbientCredential: identity.allowAmbientCredential,
14035
- ...identity.credential === void 0 ? {} : { credential: summariseCredential(identity.credential) }
14093
+ ...identity.credential === void 0 ? {} : { credential: summariseCredential(identity.credential) },
14094
+ ...identity.anchors === void 0 ? {} : { anchors: identity.anchors }
14036
14095
  };
14037
14096
  }
14038
14097
  function providerValue(name, provider) {
@@ -14063,9 +14122,9 @@ function createConfigApiRouter(deps) {
14063
14122
  return { action: "created", kind: "identity", name: input.name, value: identityValue(input.name, paths) };
14064
14123
  })
14065
14124
  ),
14066
- set: route("/rest/config/identity/set", "Update an identity's default profile, ambient-credential setting or credential").input(ConfigIdentitySetInputSchema).output(ConfigIdentitySetOutputSchema).handler(
14125
+ set: route("/rest/config/identity/set", "Update an identity's default profile, ambient-credential setting, credential or anchors").input(ConfigIdentitySetInputSchema).output(ConfigIdentitySetOutputSchema).handler(
14067
14126
  ({ input }) => guarded(() => {
14068
- requireChange(input.defaultConfigProfile !== void 0 || input.allowAmbientCredential !== void 0 || input.credential !== void 0, "defaultConfigProfile, allowAmbientCredential or credential");
14127
+ requireChange(input.defaultConfigProfile !== void 0 || input.allowAmbientCredential !== void 0 || input.credential !== void 0 || input.anchors !== void 0, "defaultConfigProfile, allowAmbientCredential, credential or anchors");
14069
14128
  if (!identityExists(paths, input.name)) {
14070
14129
  throw new IdentityNotFoundError(input.name);
14071
14130
  }
@@ -14090,6 +14149,9 @@ function createConfigApiRouter(deps) {
14090
14149
  };
14091
14150
  setIdentityCredential(paths, input.name, change);
14092
14151
  }
14152
+ if (input.anchors !== void 0) {
14153
+ setIdentityAnchors(paths, input.name, input.anchors === false ? void 0 : input.anchors);
14154
+ }
14093
14155
  return { action: "updated", kind: "identity", name: input.name, value: identityValue(input.name, paths) };
14094
14156
  })
14095
14157
  ),
package/dist/index.mjs CHANGED
@@ -209,7 +209,15 @@ function isCodexProvider(provider) {
209
209
  function poolMemberIdentity(member) {
210
210
  return typeof member === "string" ? member : member.identity;
211
211
  }
212
- var CATEGORY_NAMES, OVERRIDABLE_CATEGORIES, CategoryMapSchema, DURATION_RE, DurationSchema, WhenConditionObjectSchema, WhenSchema, EntryValueSchema, ENTRY_KEY_RE, EntriesSchema, LaunchSchema, CREDENTIAL_TARGETS, PROVIDER_CREDENTIAL_TARGETS, CREDENTIAL_TARGET_VARS, ArgvSchema, CommandSourceOptions, EnvCredentialSourceSchema, FileCredentialSourceSchema, CommandCredentialSourceSchema, OpCredentialSourceSchema, KeychainCredentialSourceSchema, LiteralCredentialSourceSchema, CredentialSourceSchema, RemoteCredentialSourceSchema, CREDENTIAL_CACHE_STORES, CredentialCacheSchema, CredentialSchema, ProviderCredentialSchema, RESERVED_PROVIDER_ENV_KEYS, ProviderEnvSchema, PROVIDER_KINDS, CODEX_EFFORTS, CODEX_LOGINS, CODEX_DEFAULT_TIER_MODELS, CodexProviderConfigSchema, ProviderRouteSchema, HttpProviderSchema, CodexProviderSchema, ProviderSchema, ConfigProfileSchema, POOL_SELECTOR_PREFIX, POOL_NAME_PATTERN, IDENTITY_NAME_PATTERN, PoolNameSchema, SELECTOR_RE, IdentitySelectorSchema, PoolMemberSchema, POOL_PREFERENCES, PoolPreferenceSchema, PoolSchema, DirectoryRuleSchema, DirectoryRulesSchema, PortableConfigSchema, HEADROOM_MODES, HEADROOM_CCR_MODES, HEADROOM_ROLLOUT_CHANNELS, INTERCEPT_CHANNELS, READ_MATURATION_CHANNELS, HeadroomGlobalConfigObjectSchema, HeadroomGlobalConfigSchema, HEADROOM_DEFAULT_SOURCE, HEADROOM_DEFAULT_IDLE_SHUTDOWN_MINUTES, FrontDoorGlobalConfigSchema, UPDATE_MODES, UpdateGlobalConfigSchema, GlobalConfigSchema, IdentitySchema, CategoryClassificationSchema, CategoryClassificationOverlaySchema, SHIPPED_CATEGORY_DEFAULTS;
212
+ function isTimeZone(name) {
213
+ try {
214
+ new Intl.DateTimeFormat("en", { timeZone: name });
215
+ return true;
216
+ } catch {
217
+ return false;
218
+ }
219
+ }
220
+ var CATEGORY_NAMES, OVERRIDABLE_CATEGORIES, CategoryMapSchema, DURATION_RE, DurationSchema, WhenConditionObjectSchema, WhenSchema, EntryValueSchema, ENTRY_KEY_RE, EntriesSchema, LaunchSchema, CREDENTIAL_TARGETS, PROVIDER_CREDENTIAL_TARGETS, CREDENTIAL_TARGET_VARS, ArgvSchema, CommandSourceOptions, EnvCredentialSourceSchema, FileCredentialSourceSchema, CommandCredentialSourceSchema, OpCredentialSourceSchema, KeychainCredentialSourceSchema, LiteralCredentialSourceSchema, CredentialSourceSchema, RemoteCredentialSourceSchema, CREDENTIAL_CACHE_STORES, CredentialCacheSchema, CredentialSchema, ProviderCredentialSchema, RESERVED_PROVIDER_ENV_KEYS, ProviderEnvSchema, PROVIDER_KINDS, CODEX_EFFORTS, CODEX_LOGINS, CODEX_DEFAULT_TIER_MODELS, CodexProviderConfigSchema, ProviderRouteSchema, HttpProviderSchema, CodexProviderSchema, ProviderSchema, ConfigProfileSchema, POOL_SELECTOR_PREFIX, POOL_NAME_PATTERN, IDENTITY_NAME_PATTERN, PoolNameSchema, SELECTOR_RE, IdentitySelectorSchema, PoolMemberSchema, POOL_PREFERENCES, PoolPreferenceSchema, PoolSchema, WEEKDAYS, AnchorSchema, JOB_WINDOWS, JobTriggerSchema, JobTargetSchema, JobSchema, DirectoryRuleSchema, DirectoryRulesSchema, PortableConfigSchema, HEADROOM_MODES, HEADROOM_CCR_MODES, HEADROOM_ROLLOUT_CHANNELS, INTERCEPT_CHANNELS, READ_MATURATION_CHANNELS, HeadroomGlobalConfigObjectSchema, HeadroomGlobalConfigSchema, HEADROOM_DEFAULT_SOURCE, HEADROOM_DEFAULT_IDLE_SHUTDOWN_MINUTES, FrontDoorGlobalConfigSchema, UPDATE_MODES, UpdateGlobalConfigSchema, GlobalConfigSchema, IdentitySchema, CategoryClassificationSchema, CategoryClassificationOverlaySchema, SHIPPED_CATEGORY_DEFAULTS;
213
221
  var init_schema = __esm({
214
222
  "src/config/schema.ts"() {
215
223
  "use strict";
@@ -377,6 +385,25 @@ var init_schema = __esm({
377
385
  identities: z.array(PoolMemberSchema).min(1).refine((members) => new Set(members.map(poolMemberIdentity)).size === members.length, { message: "pool members must be unique" }),
378
386
  preference: PoolPreferenceSchema.optional()
379
387
  });
388
+ WEEKDAYS = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"];
389
+ AnchorSchema = z.strictObject({
390
+ days: z.array(z.enum(WEEKDAYS)).min(1).refine((days) => new Set(days).size === days.length, "an anchor names each weekday at most once"),
391
+ time: z.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/, "a 24-hour time such as 06:00"),
392
+ timeZone: z.string().refine(isTimeZone, "an IANA time zone such as Europe/London").optional()
393
+ });
394
+ JOB_WINDOWS = ["fiveHour", "sevenDay"];
395
+ JobTriggerSchema = z.union([z.strictObject({ at: z.array(AnchorSchema).min(1) }), z.strictObject({ beforeReset: z.enum(JOB_WINDOWS), lead: z.string().regex(DURATION_RE) })]);
396
+ JobTargetSchema = z.union([z.strictObject({ identity: IdentitySelectorSchema }), z.strictObject({ pool: PoolNameSchema })]);
397
+ JobSchema = z.strictObject({
398
+ target: JobTargetSchema,
399
+ trigger: JobTriggerSchema,
400
+ prompt: z.string().min(1),
401
+ /** The absolute directory the run works in. */
402
+ cwd: z.string().min(1),
403
+ timeout: z.string().regex(DURATION_RE),
404
+ model: z.string().min(1).optional(),
405
+ allowedTools: z.array(z.string().min(1)).min(1).optional()
406
+ });
380
407
  DirectoryRuleSchema = ConfigProfileSchema.omit({ description: true }).extend({
381
408
  path: z.string().min(1),
382
409
  configProfile: z.string().min(1).optional(),
@@ -444,14 +471,17 @@ var init_schema = __esm({
444
471
  headroom: HeadroomGlobalConfigSchema.optional(),
445
472
  frontdoor: FrontDoorGlobalConfigSchema.optional(),
446
473
  update: UpdateGlobalConfigSchema.optional(),
447
- pools: z.record(PoolNameSchema, PoolSchema).optional()
474
+ pools: z.record(PoolNameSchema, PoolSchema).optional(),
475
+ jobs: z.record(PoolNameSchema, JobSchema).optional()
448
476
  });
449
477
  IdentitySchema = z.strictObject({
450
478
  $schema: z.string().optional(),
451
479
  name: z.string().min(1).regex(/^[A-Za-z0-9][A-Za-z0-9._@-]*$/),
452
480
  defaultConfigProfile: z.string().min(1).optional(),
453
481
  allowAmbientCredential: z.boolean().default(false),
454
- credential: CredentialSchema.optional()
482
+ credential: CredentialSchema.optional(),
483
+ /** When this identity's five-hour window should be open: the front door opens one at each anchor if none is. Absent, nothing is opened on a schedule. */
484
+ anchors: z.array(AnchorSchema).min(1).optional()
455
485
  });
456
486
  CategoryClassificationSchema = z.strictObject({
457
487
  $schema: z.string().optional(),
@@ -2639,7 +2669,7 @@ var init_package = __esm({
2639
2669
  "package.json"() {
2640
2670
  package_default = {
2641
2671
  name: "claude-use",
2642
- version: "9.13.0",
2672
+ version: "9.15.0",
2643
2673
  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.",
2644
2674
  license: "MIT",
2645
2675
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -5284,6 +5314,9 @@ function buildLayoutPaths(root) {
5284
5314
  usageLogDir: path22.join(root, "usage", "log"),
5285
5315
  usageSnapshotsDir: path22.join(root, "usage", "snapshots"),
5286
5316
  usagePicksFile: path22.join(root, "usage", "picks.json"),
5317
+ usageAnchorsFile: path22.join(root, "usage", "anchors.json"),
5318
+ usageJobsFile: path22.join(root, "usage", "jobs.json"),
5319
+ jobLogsDir: path22.join(root, "logs", "jobs"),
5287
5320
  mcpPermissionsFile: path22.join(root, "mcp", "permissions.json")
5288
5321
  };
5289
5322
  }
@@ -7781,6 +7814,57 @@ var init_anthropicUsageRefresh = __esm({
7781
7814
  }
7782
7815
  });
7783
7816
 
7817
+ // src/usage/identityClaude.ts
7818
+ function definedEnvironment(env) {
7819
+ return Object.fromEntries(Object.entries(env).flatMap(([name, value]) => value === void 0 ? [] : [[name, value]]));
7820
+ }
7821
+ function identityLaunchArgv(identity, flags) {
7822
+ return [`@${identity}`, IDENTITY_ONLY_FLAG, ...flags];
7823
+ }
7824
+ async function withIdentityClaude(params, identity, flags, use) {
7825
+ const refusals = [];
7826
+ const plan = prepareLaunch(
7827
+ realPrepareLaunchParams(params.paths, {
7828
+ proc: {
7829
+ env: Object.fromEntries(Object.entries(process.env).filter(([name]) => name !== CONFIG_DIR_VARIABLE)),
7830
+ argv: [...identityLaunchArgv(identity, flags)],
7831
+ exit: (code) => {
7832
+ throw new LaunchRefusedError(refusals.join("\n") || `the launch was refused (exit ${String(code)})`, code);
7833
+ }
7834
+ },
7835
+ log: {
7836
+ info: () => void 0,
7837
+ warn: () => void 0,
7838
+ error: (message) => {
7839
+ refusals.push(message);
7840
+ }
7841
+ },
7842
+ spawnDaemon: params.spawnDaemon,
7843
+ farm: buildFarmRuntime(params.paths, params.cwd)
7844
+ })
7845
+ );
7846
+ const abort = new AbortController();
7847
+ const timer = setTimeout(() => {
7848
+ abort.abort();
7849
+ }, params.timeoutMs);
7850
+ try {
7851
+ return await use({ bin: plan.bin, env: definedEnvironment(plan.env), cwd: params.cwd, abort });
7852
+ } finally {
7853
+ clearTimeout(timer);
7854
+ plan.release();
7855
+ }
7856
+ }
7857
+ var CONFIG_DIR_VARIABLE, IDENTITY_ONLY_FLAG;
7858
+ var init_identityClaude = __esm({
7859
+ "src/usage/identityClaude.ts"() {
7860
+ "use strict";
7861
+ init_launchWiring();
7862
+ init_launcher();
7863
+ CONFIG_DIR_VARIABLE = "CLAUDE_CONFIG_DIR";
7864
+ IDENTITY_ONLY_FLAG = "--no-provider";
7865
+ }
7866
+ });
7867
+
7784
7868
  // src/usage/providerQuota.ts
7785
7869
  import { z as z25 } from "zod";
7786
7870
  var MS_PER_SECOND7, SECONDS_PER_HOUR, HOURS_PER_DAY4, 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;
@@ -7852,9 +7936,6 @@ __export(realAnthropicUsageProbe_exports, {
7852
7936
  createRealAnthropicUsageRefresher: () => createRealAnthropicUsageRefresher
7853
7937
  });
7854
7938
  import { availableParallelism } from "node:os";
7855
- function definedEnvironment(env) {
7856
- return Object.fromEntries(Object.entries(env).flatMap(([name, value]) => value === void 0 ? [] : [[name, value]]));
7857
- }
7858
7939
  function idlePrompt(signal) {
7859
7940
  return {
7860
7941
  [Symbol.asyncIterator]: () => ({
@@ -7867,58 +7948,28 @@ function idlePrompt(signal) {
7867
7948
  };
7868
7949
  }
7869
7950
  function createRealAnthropicUsageProbe(params) {
7870
- return async (identity) => {
7871
- const refusals = [];
7872
- const plan = prepareLaunch(
7873
- realPrepareLaunchParams(params.paths, {
7874
- proc: {
7875
- env: Object.fromEntries(Object.entries(process.env).filter(([name]) => name !== CONFIG_DIR_VARIABLE)),
7876
- argv: [`@${identity}`, ...PROBE_LAUNCH_FLAGS],
7877
- exit: (code) => {
7878
- throw new LaunchRefusedError(refusals.join("\n") || `the launch was refused (exit ${String(code)})`, code);
7879
- }
7880
- },
7881
- log: {
7882
- info: () => void 0,
7883
- warn: () => void 0,
7884
- error: (message) => {
7885
- refusals.push(message);
7886
- }
7887
- },
7888
- spawnDaemon: params.spawnDaemon,
7889
- farm: buildFarmRuntime(params.paths, params.cwd)
7890
- })
7891
- );
7951
+ return async (identity) => await withIdentityClaude(params, identity, PROBE_LAUNCH_FLAGS, async ({ bin, env, cwd, abort }) => {
7892
7952
  const { query } = await import("@anthropic-ai/claude-agent-sdk");
7893
- const abort = new AbortController();
7894
- const timer = setTimeout(() => {
7895
- abort.abort();
7896
- }, params.timeoutMs);
7897
- try {
7898
- const session = query({
7899
- prompt: idlePrompt(abort.signal),
7900
- options: {
7901
- pathToClaudeCodeExecutable: plan.bin,
7902
- env: definedEnvironment(plan.env),
7903
- cwd: params.cwd,
7904
- abortController: abort,
7905
- settingSources: [],
7906
- mcpServers: {},
7907
- strictMcpConfig: true,
7908
- persistSession: false
7909
- }
7910
- });
7911
- try {
7912
- const report = await session.usage_EXPERIMENTAL_MAY_CHANGE_DO_NOT_RELY_ON_THIS_API_YET({ skipBehaviors: true });
7913
- return unifiedFromReportedLimits(report.rate_limits_available ? report.rate_limits : null);
7914
- } finally {
7915
- session.close();
7953
+ const session = query({
7954
+ prompt: idlePrompt(abort.signal),
7955
+ options: {
7956
+ pathToClaudeCodeExecutable: bin,
7957
+ env,
7958
+ cwd,
7959
+ abortController: abort,
7960
+ settingSources: [],
7961
+ mcpServers: {},
7962
+ strictMcpConfig: true,
7963
+ persistSession: false
7916
7964
  }
7965
+ });
7966
+ try {
7967
+ const report = await session.usage_EXPERIMENTAL_MAY_CHANGE_DO_NOT_RELY_ON_THIS_API_YET({ skipBehaviors: true });
7968
+ return unifiedFromReportedLimits(report.rate_limits_available ? report.rate_limits : null);
7917
7969
  } finally {
7918
- clearTimeout(timer);
7919
- plan.release();
7970
+ session.close();
7920
7971
  }
7921
- };
7972
+ });
7922
7973
  }
7923
7974
  function createRealAnthropicUsageRefresher(params) {
7924
7975
  return createAnthropicUsageRefresher({
@@ -7931,17 +7982,15 @@ function createRealAnthropicUsageRefresher(params) {
7931
7982
  concurrency: availableParallelism()
7932
7983
  });
7933
7984
  }
7934
- var PROBE_LAUNCH_FLAGS, CONFIG_DIR_VARIABLE;
7985
+ var PROBE_LAUNCH_FLAGS;
7935
7986
  var init_realAnthropicUsageProbe = __esm({
7936
7987
  "src/usage/realAnthropicUsageProbe.ts"() {
7937
7988
  "use strict";
7938
- init_launchWiring();
7939
- init_launcher();
7940
7989
  init_anthropicUsageRefresh();
7990
+ init_identityClaude();
7941
7991
  init_middleware();
7942
7992
  init_quotaRefresh();
7943
7993
  PROBE_LAUNCH_FLAGS = ["--no-headroom", "--no-remote-control"];
7944
- CONFIG_DIR_VARIABLE = "CLAUDE_CONFIG_DIR";
7945
7994
  }
7946
7995
  });
7947
7996
 
@@ -12404,6 +12453,12 @@ function listIdentities(paths) {
12404
12453
  }
12405
12454
  return result;
12406
12455
  }
12456
+ function setIdentityAnchors(paths, identityName, anchors) {
12457
+ if (!identityExists(paths, identityName)) {
12458
+ throw new IdentityNotFoundError(identityName);
12459
+ }
12460
+ return applyPatch(identityJsonPath(paths, identityName), IdentitySchema, { anchors: anchors === void 0 ? void 0 : [...anchors] });
12461
+ }
12407
12462
  function setDefaultConfigProfile(paths, identityName, profileName) {
12408
12463
  if (!identityExists(paths, identityName)) {
12409
12464
  throw new IdentityNotFoundError(identityName);
@@ -13508,7 +13563,8 @@ var IdentityValueSchema = z22.strictObject({
13508
13563
  name: z22.string(),
13509
13564
  defaultConfigProfile: z22.string().optional(),
13510
13565
  allowAmbientCredential: z22.boolean(),
13511
- credential: CredentialSummarySchema2.optional()
13566
+ credential: CredentialSummarySchema2.optional(),
13567
+ anchors: z22.array(AnchorSchema).optional()
13512
13568
  });
13513
13569
  var ProfileValueSchema = ConfigProfileSchema.omit({ $schema: true });
13514
13570
  var ProviderValueSchema = z22.strictObject({
@@ -13526,7 +13582,9 @@ var ConfigIdentitySetInputSchema = z22.strictObject({
13526
13582
  name: z22.string().min(1),
13527
13583
  defaultConfigProfile: z22.union([z22.string().min(1), z22.literal(false)]).optional(),
13528
13584
  allowAmbientCredential: z22.boolean().optional(),
13529
- credential: z22.union([z22.literal(false), CredentialWriteSchema(CREDENTIAL_TARGETS)]).optional()
13585
+ credential: z22.union([z22.literal(false), CredentialWriteSchema(CREDENTIAL_TARGETS)]).optional(),
13586
+ /** `false` removes the anchors; a list replaces them. */
13587
+ anchors: z22.union([z22.literal(false), z22.array(AnchorSchema).min(1)]).optional()
13530
13588
  });
13531
13589
  var ConfigIdentitySetOutputSchema = storedMutationOutput("identity", "updated", IdentityValueSchema);
13532
13590
  var ConfigIdentityRemoveInputSchema = z22.strictObject({ name: z22.string().min(1), confirm: RemovalConfirmationSchema });
@@ -13647,7 +13705,8 @@ function identityValue(name, paths) {
13647
13705
  name: identity.name,
13648
13706
  ...identity.defaultConfigProfile === void 0 ? {} : { defaultConfigProfile: identity.defaultConfigProfile },
13649
13707
  allowAmbientCredential: identity.allowAmbientCredential,
13650
- ...identity.credential === void 0 ? {} : { credential: summariseCredential(identity.credential) }
13708
+ ...identity.credential === void 0 ? {} : { credential: summariseCredential(identity.credential) },
13709
+ ...identity.anchors === void 0 ? {} : { anchors: identity.anchors }
13651
13710
  };
13652
13711
  }
13653
13712
  function providerValue(name, provider) {
@@ -13678,9 +13737,9 @@ function createConfigApiRouter(deps) {
13678
13737
  return { action: "created", kind: "identity", name: input.name, value: identityValue(input.name, paths) };
13679
13738
  })
13680
13739
  ),
13681
- set: route("/rest/config/identity/set", "Update an identity's default profile, ambient-credential setting or credential").input(ConfigIdentitySetInputSchema).output(ConfigIdentitySetOutputSchema).handler(
13740
+ set: route("/rest/config/identity/set", "Update an identity's default profile, ambient-credential setting, credential or anchors").input(ConfigIdentitySetInputSchema).output(ConfigIdentitySetOutputSchema).handler(
13682
13741
  ({ input }) => guarded(() => {
13683
- requireChange(input.defaultConfigProfile !== void 0 || input.allowAmbientCredential !== void 0 || input.credential !== void 0, "defaultConfigProfile, allowAmbientCredential or credential");
13742
+ requireChange(input.defaultConfigProfile !== void 0 || input.allowAmbientCredential !== void 0 || input.credential !== void 0 || input.anchors !== void 0, "defaultConfigProfile, allowAmbientCredential, credential or anchors");
13684
13743
  if (!identityExists(paths, input.name)) {
13685
13744
  throw new IdentityNotFoundError(input.name);
13686
13745
  }
@@ -13705,6 +13764,9 @@ function createConfigApiRouter(deps) {
13705
13764
  };
13706
13765
  setIdentityCredential(paths, input.name, change);
13707
13766
  }
13767
+ if (input.anchors !== void 0) {
13768
+ setIdentityAnchors(paths, input.name, input.anchors === false ? void 0 : input.anchors);
13769
+ }
13708
13770
  return { action: "updated", kind: "identity", name: input.name, value: identityValue(input.name, paths) };
13709
13771
  })
13710
13772
  ),