claude-use 2.8.0 → 2.9.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.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.cjs +72 -15
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -77,7 +77,7 @@ claude-use profile set <name> --category <cat>=<bool>[,<cat>=<bool>,...]
77
77
  claude-use profile set <name> --entry "<path>"=<bool>[,"<path>"=<bool>,...]
78
78
  claude-use profile set <name> [--skip-permissions] [--remote-control] [--headroom]
79
79
 
80
- claude-use provider add <name> --display-name <name> --base-url <url> --token-env <VAR> [--env KEY=VALUE]
80
+ claude-use provider add <name> --display-name <name> --base-url <url> (--token-env <VAR> | --token-command <argv...>) [--auth-scheme <bearer|apiKey>] [--env KEY=VALUE]
81
81
  claude-use provider list
82
82
  claude-use provider show <name>
83
83
  claude-use provider remove <name>
package/dist/cli.cjs CHANGED
@@ -239649,7 +239649,7 @@ var program = new Command();
239649
239649
  // package.json
239650
239650
  var package_default = {
239651
239651
  name: "claude-use",
239652
- version: "2.8.0",
239652
+ version: "2.9.0",
239653
239653
  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.",
239654
239654
  license: "Apache-2.0",
239655
239655
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -259498,14 +259498,34 @@ var LaunchSchema = external_exports.strictObject({
259498
259498
  provider: external_exports.string().min(1).optional(),
259499
259499
  headroom: external_exports.boolean().optional()
259500
259500
  });
259501
+ var AUTH_SCHEMES = ["bearer", "apiKey"];
259501
259502
  var ProviderSchema = external_exports.strictObject({
259502
259503
  $schema: external_exports.string().optional(),
259503
259504
  displayName: external_exports.string().min(1),
259504
259505
  baseUrl: external_exports.url(),
259505
259506
  tokenEnv: external_exports.string().min(1).optional(),
259507
+ tokenCommand: external_exports.tuple([external_exports.string().min(1)], external_exports.string()).optional(),
259508
+ authScheme: external_exports.enum(AUTH_SCHEMES).optional(),
259506
259509
  env: external_exports.record(external_exports.string().min(1), external_exports.string()).optional()
259507
- }).refine((provider) => provider.tokenEnv !== void 0 || (provider.env?.ANTHROPIC_AUTH_TOKEN ?? "") !== "", {
259508
- message: "a provider needs either tokenEnv (the name of the environment variable holding its token) or a non-empty env.ANTHROPIC_AUTH_TOKEN"
259510
+ }).superRefine((provider, ctx) => {
259511
+ const sources = [
259512
+ provider.tokenEnv !== void 0 ? "tokenEnv" : void 0,
259513
+ provider.tokenCommand !== void 0 ? "tokenCommand" : void 0,
259514
+ (provider.env?.ANTHROPIC_AUTH_TOKEN ?? "") !== "" ? "env.ANTHROPIC_AUTH_TOKEN" : void 0
259515
+ ].filter((source) => source !== void 0);
259516
+ if (sources.length !== 1) {
259517
+ ctx.addIssue({
259518
+ code: "custom",
259519
+ message: sources.length === 0 ? "a provider needs exactly one token source: tokenEnv (the name of the environment variable holding its token), tokenCommand (an argv whose stdout is the token), or a non-empty env.ANTHROPIC_AUTH_TOKEN" : `a provider takes exactly one token source, but this one has ${sources.join(", ")}`
259520
+ });
259521
+ }
259522
+ if (provider.authScheme === "apiKey" && (provider.env?.ANTHROPIC_API_KEY ?? "") !== "") {
259523
+ ctx.addIssue({
259524
+ code: "custom",
259525
+ path: ["env", "ANTHROPIC_API_KEY"],
259526
+ message: 'authScheme "apiKey" exports the token as ANTHROPIC_API_KEY, so env.ANTHROPIC_API_KEY must not be set to a value'
259527
+ });
259528
+ }
259509
259529
  });
259510
259530
  var ConfigProfileSchema = external_exports.strictObject({
259511
259531
  $schema: external_exports.string().optional(),
@@ -266045,6 +266065,13 @@ var READY_FETCH_TIMEOUT_MS = 2e3;
266045
266065
  function headroomPidRunning(pid) {
266046
266066
  return !exitedHeadroom.has(pid) && realIsProcessRunning(pid);
266047
266067
  }
266068
+ function headroomSpawnEnv(parentEnv, allowlist) {
266069
+ return {
266070
+ ...parentEnv,
266071
+ HEADROOM_ALLOWED_BASE_URLS: allowlist.join(","),
266072
+ HEADROOM_HTTP2: parentEnv.HEADROOM_HTTP2 ?? "0"
266073
+ };
266074
+ }
266048
266075
  function realSupervisorPorts(paths) {
266049
266076
  return {
266050
266077
  fs: realFarmFs,
@@ -266067,7 +266094,7 @@ function realSupervisorPorts(paths) {
266067
266094
  const child = (0, import_node_child_process3.spawn)("headroom", ["proxy", "--host", "127.0.0.1", "--port", String(port)], {
266068
266095
  detached: true,
266069
266096
  stdio: ["ignore", logFd, logFd],
266070
- env: { ...process.env, HEADROOM_ALLOWED_BASE_URLS: allowlist.join(",") }
266097
+ env: headroomSpawnEnv(process.env, allowlist)
266071
266098
  });
266072
266099
  if (child.pid === void 0) {
266073
266100
  throw new Error("spawning headroom returned no pid");
@@ -266270,6 +266297,8 @@ function addProvider(paths, name, input2) {
266270
266297
  displayName: input2.displayName,
266271
266298
  baseUrl: input2.baseUrl,
266272
266299
  ...input2.tokenEnv === void 0 ? {} : { tokenEnv: input2.tokenEnv },
266300
+ ...input2.tokenCommand === void 0 ? {} : { tokenCommand: input2.tokenCommand },
266301
+ ...input2.authScheme === void 0 ? {} : { authScheme: input2.authScheme },
266273
266302
  ...input2.env === void 0 || Object.keys(input2.env).length === 0 ? {} : { env: input2.env }
266274
266303
  });
266275
266304
  if (!parsed.success) {
@@ -266285,6 +266314,30 @@ function removeProvider(paths, name) {
266285
266314
  import_node_fs10.default.rmSync(providerJsonPath(paths, name));
266286
266315
  }
266287
266316
  var PROVIDER_MISSING_TOKEN_EXIT = 64;
266317
+ function obtainToken(name, definition, params) {
266318
+ const unusable = (message) => ({ ok: false, status: PROVIDER_MISSING_TOKEN_EXIT, message });
266319
+ if (definition.tokenCommand !== void 0) {
266320
+ const [command, ...args] = definition.tokenCommand;
266321
+ if (params.run === void 0) {
266322
+ return { ok: false, status: 1, message: `claude-use: provider ${name} needs its token command run, but this launcher has no command runner wired` };
266323
+ }
266324
+ const result = params.run.run(command, args);
266325
+ if (result.status !== 0) {
266326
+ const stderr = result.stderr.trim();
266327
+ const outcome = result.status === null ? "could not be run or was killed by a signal" : `exited with status ${String(result.status)}`;
266328
+ return unusable(`claude-use: provider ${name}: token command ${command} ${outcome}${stderr === "" ? "" : `: ${stderr}`}`);
266329
+ }
266330
+ const token2 = result.stdout.trim();
266331
+ return token2 === "" ? unusable(`claude-use: provider ${name}: token command ${command} printed no token`) : { ok: true, token: token2 };
266332
+ }
266333
+ const token = definition.tokenEnv !== void 0 ? params.env[definition.tokenEnv] : definition.env?.ANTHROPIC_AUTH_TOKEN;
266334
+ if (token === void 0 || token === "") {
266335
+ return unusable(
266336
+ definition.tokenEnv !== void 0 ? `claude-use: provider ${name} needs ${definition.tokenEnv} set in your environment` : `claude-use: provider ${name} has no usable credential: its env.ANTHROPIC_AUTH_TOKEN is empty`
266337
+ );
266338
+ }
266339
+ return { ok: true, token };
266340
+ }
266288
266341
  function resolveProvider(params) {
266289
266342
  const cliName = params.cliProvider !== void 0 && params.cliProvider !== "" ? params.cliProvider : void 0;
266290
266343
  let cascadeName;
@@ -266308,14 +266361,11 @@ function resolveProvider(params) {
266308
266361
  message: `claude-use: no provider named "${name}". ` + (known.length > 0 ? `Known providers: ${known.join(", ")}.` : "No providers are defined yet; run `claude-use provider add`.")
266309
266362
  };
266310
266363
  }
266311
- const token = definition.tokenEnv !== void 0 ? params.env[definition.tokenEnv] : definition.env?.ANTHROPIC_AUTH_TOKEN;
266312
- if (token === void 0 || token === "") {
266313
- return {
266314
- ok: false,
266315
- status: PROVIDER_MISSING_TOKEN_EXIT,
266316
- message: definition.tokenEnv !== void 0 ? `claude-use: provider ${name} needs ${definition.tokenEnv} set in your environment` : `claude-use: provider ${name} has no usable credential: its env.ANTHROPIC_AUTH_TOKEN is empty`
266317
- };
266364
+ const credential = obtainToken(name, definition, params);
266365
+ if (!credential.ok) {
266366
+ return credential;
266318
266367
  }
266368
+ const token = credential.token;
266319
266369
  return { ok: true, provider: { name, definition, token } };
266320
266370
  }
266321
266371
  function collectEnvPairs(value, previous = {}) {
@@ -266332,16 +266382,17 @@ function collectEnvPairs(value, previous = {}) {
266332
266382
  }
266333
266383
  function registerProviderCommand(program2, paths) {
266334
266384
  const provider = program2.command("provider").description("Manage API providers the launcher can route a session through.");
266335
- provider.command("add <name>").description("Create a new API provider definition.").requiredOption("--display-name <name>", "Human-readable name, exported to the child as CLAUDE_USE_PROVIDER.").requiredOption("--base-url <url>", "Anthropic-compatible base URL the child's requests are sent to.").option("--token-env <var>", "NAME of the environment variable holding the provider's token (never the token itself). Optional only when --env carries ANTHROPIC_AUTH_TOKEN (a local proxy's fixed dummy token).").option("--env <pair>", "Extra KEY=VALUE environment entry for the child (repeatable).", collectEnvPairs).action((name, options) => {
266385
+ provider.command("add <name>").description("Create a new API provider definition.").requiredOption("--display-name <name>", "Human-readable name, exported to the child as CLAUDE_USE_PROVIDER.").requiredOption("--base-url <url>", "Anthropic-compatible base URL the child's requests are sent to.").option("--token-env <var>", "NAME of the environment variable holding the provider's token (never the token itself). Exactly one of --token-env, --token-command or --env ANTHROPIC_AUTH_TOKEN=<fixed dummy token for a local proxy> is required.").option("--token-command <argv...>", "Command (program and arguments) run at launch whose trimmed stdout is the token, e.g. --token-command op read op://vault/item/field. Give it last on the command line, since it consumes every following word.").addOption(new Option("--auth-scheme <scheme>", "How the token reaches Claude Code: bearer sets ANTHROPIC_AUTH_TOKEN (default), apiKey sets ANTHROPIC_API_KEY.").choices(AUTH_SCHEMES)).option("--env <pair>", "Extra KEY=VALUE environment entry for the child (repeatable).", collectEnvPairs).action((name, options) => {
266336
266386
  addProvider(paths, name, {
266337
266387
  displayName: options.displayName,
266338
266388
  baseUrl: options.baseUrl,
266339
266389
  ...options.tokenEnv === void 0 ? {} : { tokenEnv: options.tokenEnv },
266390
+ ...options.tokenCommand === void 0 ? {} : { tokenCommand: options.tokenCommand },
266391
+ ...options.authScheme === void 0 ? {} : { authScheme: options.authScheme },
266340
266392
  ...options.env === void 0 ? {} : { env: options.env }
266341
266393
  });
266342
- console.log(
266343
- options.tokenEnv === void 0 ? `Created provider "${name}" (${options.baseUrl}, fixed env credential).` : `Created provider "${name}" (${options.baseUrl}, token from ${options.tokenEnv}).`
266344
- );
266394
+ const source = options.tokenEnv !== void 0 ? `token from ${options.tokenEnv}` : options.tokenCommand !== void 0 ? `token from ${options.tokenCommand[0]}` : "fixed env credential";
266395
+ console.log(`Created provider "${name}" (${options.baseUrl}, ${source}).`);
266345
266396
  });
266346
266397
  provider.command("list").description("List every API provider.").action(() => {
266347
266398
  const entries = listProviders(paths);
@@ -266597,6 +266648,10 @@ function buildEnv(params) {
266597
266648
  for (const [key, value] of Object.entries(providerEnv)) {
266598
266649
  env[key] = value;
266599
266650
  }
266651
+ if (params.provider.definition.authScheme === "apiKey") {
266652
+ env.ANTHROPIC_API_KEY = params.provider.token;
266653
+ env.ANTHROPIC_AUTH_TOKEN = "";
266654
+ }
266600
266655
  }
266601
266656
  if (params.headroom !== void 0) {
266602
266657
  env.HEADROOM_PROXY_URL = `http://127.0.0.1:${String(params.headroom.port)}`;
@@ -266725,6 +266780,7 @@ function runLauncher(params) {
266725
266780
  paths,
266726
266781
  port: fs12,
266727
266782
  env,
266783
+ ...params.run === void 0 ? {} : { run: params.run },
266728
266784
  ...parsedArgv.provider === void 0 ? {} : { cliProvider: parsedArgv.provider },
266729
266785
  ...farmContext === void 0 ? {} : { cascade: farmContext.cascade }
266730
266786
  });
@@ -266937,6 +266993,7 @@ async function runClaude(argvOverride) {
266937
266993
  resolveClaudeBinary: realResolveClaudeBinary(resolveOwnInstallDirs(paths, realOwnExecutablePath())),
266938
266994
  farm: farm.runtime,
266939
266995
  headroom: realHeadroomPort(paths),
266996
+ run: realRunPort,
266940
266997
  ...farm.directoryIdentity === void 0 ? {} : { directoryPinnedIdentity: farm.directoryIdentity },
266941
266998
  ...farm.directoryConfigProfile === void 0 ? {} : { directoryRuleConfigProfile: farm.directoryConfigProfile },
266942
266999
  ...farm.globalDefaultConfigProfile === void 0 ? {} : { globalDefaultConfigProfile: farm.globalDefaultConfigProfile }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-use",
3
- "version": "2.8.0",
3
+ "version": "2.9.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": "Apache-2.0",
6
6
  "author": "Joseph Mearman <joseph@mearman.co.uk>",