claude-use 2.5.3 → 2.6.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/cli.cjs +62 -17
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -221824,7 +221824,7 @@ var program = new Command();
|
|
|
221824
221824
|
// package.json
|
|
221825
221825
|
var package_default = {
|
|
221826
221826
|
name: "claude-use",
|
|
221827
|
-
version: "2.
|
|
221827
|
+
version: "2.6.0",
|
|
221828
221828
|
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.",
|
|
221829
221829
|
license: "Apache-2.0",
|
|
221830
221830
|
author: "Joseph Mearman <joseph@mearman.co.uk>",
|
|
@@ -241675,8 +241675,10 @@ var ProviderSchema = external_exports.strictObject({
|
|
|
241675
241675
|
$schema: external_exports.string().optional(),
|
|
241676
241676
|
displayName: external_exports.string().min(1),
|
|
241677
241677
|
baseUrl: external_exports.url(),
|
|
241678
|
-
tokenEnv: external_exports.string().min(1),
|
|
241678
|
+
tokenEnv: external_exports.string().min(1).optional(),
|
|
241679
241679
|
env: external_exports.record(external_exports.string().min(1), external_exports.string()).optional()
|
|
241680
|
+
}).refine((provider) => provider.tokenEnv !== void 0 || (provider.env?.ANTHROPIC_AUTH_TOKEN ?? "") !== "", {
|
|
241681
|
+
message: "a provider needs either tokenEnv (the name of the environment variable holding its token) or a non-empty env.ANTHROPIC_AUTH_TOKEN"
|
|
241680
241682
|
});
|
|
241681
241683
|
var ConfigProfileSchema = external_exports.strictObject({
|
|
241682
241684
|
$schema: external_exports.string().optional(),
|
|
@@ -243749,6 +243751,7 @@ function resolveLayoutPaths() {
|
|
|
243749
243751
|
var import_node_child_process2 = require("node:child_process");
|
|
243750
243752
|
var import_node_crypto4 = require("node:crypto");
|
|
243751
243753
|
var import_node_fs3 = __toESM(require("node:fs"), 1);
|
|
243754
|
+
var import_node_net = __toESM(require("node:net"), 1);
|
|
243752
243755
|
var import_node_path13 = __toESM(require("node:path"), 1);
|
|
243753
243756
|
var import_node_sea = require("node:sea");
|
|
243754
243757
|
|
|
@@ -243829,6 +243832,10 @@ var HeadroomStateSchema = external_exports.strictObject({
|
|
|
243829
243832
|
headroomPid: external_exports.number().int().positive().optional(),
|
|
243830
243833
|
/** The loopback port the proxy listens on. Absent until the proxy has passed its readiness check, so "port is set" is itself the ready signal a launcher polls for. */
|
|
243831
243834
|
port: external_exports.number().int().positive().optional(),
|
|
243835
|
+
/**
|
|
243836
|
+
* The sticky port preference: the address the daemon last served on, kept across crashes, restarts, and idle shutdowns so the next start reuses it. Distinct from `port` on purpose: `port` is the ready signal (absent whenever nothing is serving), while `lastPort` survives every shutdown, because every live session's environment was frozen at launch pointing at this address and a restart that moves strands them.
|
|
243837
|
+
*/
|
|
243838
|
+
lastPort: external_exports.number().int().positive().optional(),
|
|
243832
243839
|
/** The `headroom --version` output of the running install. */
|
|
243833
243840
|
version: external_exports.string().optional(),
|
|
243834
243841
|
/** Hash of the allowlist the running proxy was started with, so a provider-file change is detected as drift. */
|
|
@@ -244153,6 +244160,21 @@ function spawnHeadroomSupervisor(paths) {
|
|
|
244153
244160
|
import_node_fs3.default.closeSync(logFd);
|
|
244154
244161
|
}
|
|
244155
244162
|
}
|
|
244163
|
+
async function realIsPortFree(port) {
|
|
244164
|
+
return await new Promise((resolve) => {
|
|
244165
|
+
const server2 = import_node_net.default.createServer();
|
|
244166
|
+
server2.unref();
|
|
244167
|
+
server2.once("error", () => {
|
|
244168
|
+
resolve(false);
|
|
244169
|
+
});
|
|
244170
|
+
server2.once("close", () => {
|
|
244171
|
+
resolve(true);
|
|
244172
|
+
});
|
|
244173
|
+
server2.listen(port, "127.0.0.1", () => {
|
|
244174
|
+
server2.close();
|
|
244175
|
+
});
|
|
244176
|
+
});
|
|
244177
|
+
}
|
|
244156
244178
|
function realHeadroomPort(paths) {
|
|
244157
244179
|
return {
|
|
244158
244180
|
ensure: () => {
|
|
@@ -247421,7 +247443,7 @@ function registerDoctorCommand(program2, paths) {
|
|
|
247421
247443
|
|
|
247422
247444
|
// src/headroom/commands.ts
|
|
247423
247445
|
var import_node_fs9 = __toESM(require("node:fs"), 1);
|
|
247424
|
-
var
|
|
247446
|
+
var import_node_net2 = __toESM(require("node:net"), 1);
|
|
247425
247447
|
var import_node_child_process3 = require("node:child_process");
|
|
247426
247448
|
|
|
247427
247449
|
// src/headroom/supervisor.ts
|
|
@@ -247523,14 +247545,18 @@ function compareVersions2(a2, b) {
|
|
|
247523
247545
|
var HEADROOM_SUPERVISOR_STILL_RUNNING = -1;
|
|
247524
247546
|
async function runSupervisor(config2, ports, options = {}) {
|
|
247525
247547
|
const { fs: fs11, paths } = ports;
|
|
247548
|
+
const previousState = readHeadroomState(fs11, paths.headroomStateFile);
|
|
247549
|
+
let installedSource = previousState?.installedSource;
|
|
247550
|
+
let lastPort = previousState?.lastPort;
|
|
247526
247551
|
const fail = (message) => {
|
|
247527
|
-
writeHeadroomState(fs11, paths.headroomStateFile, {
|
|
247552
|
+
writeHeadroomState(fs11, paths.headroomStateFile, {
|
|
247553
|
+
lastError: message,
|
|
247554
|
+
...lastPort === void 0 ? {} : { lastPort }
|
|
247555
|
+
});
|
|
247528
247556
|
fs11.removeRecursive(paths.headroomLockFile);
|
|
247529
247557
|
ports.log(`claude-use headroom supervisor: ${message}`);
|
|
247530
247558
|
return 1;
|
|
247531
247559
|
};
|
|
247532
|
-
const previousState = readHeadroomState(fs11, paths.headroomStateFile);
|
|
247533
|
-
let installedSource = previousState?.installedSource;
|
|
247534
247560
|
const ensureInstalled = () => {
|
|
247535
247561
|
const version3 = ports.headroomVersion();
|
|
247536
247562
|
const versionOk = version3 !== void 0 && versionSatisfies(version3, config2.source);
|
|
@@ -247550,7 +247576,7 @@ async function runSupervisor(config2, ports, options = {}) {
|
|
|
247550
247576
|
return fail(`could not install headroom from ${config2.source}: install failed (is uv installed and on PATH?)`);
|
|
247551
247577
|
}
|
|
247552
247578
|
const version2 = ports.headroomVersion() ?? "unknown";
|
|
247553
|
-
writeHeadroomState(fs11, paths.headroomStateFile, { supervisorPid: ports.ownPid, version: version2, installedSource });
|
|
247579
|
+
writeHeadroomState(fs11, paths.headroomStateFile, { supervisorPid: ports.ownPid, version: version2, installedSource, ...lastPort === void 0 ? {} : { lastPort } });
|
|
247554
247580
|
ports.log(`claude-use headroom supervisor ${String(ports.ownPid)}: managing headroom on allowlist [${allowlistOf(ports).join(", ")}]`);
|
|
247555
247581
|
const orphanPid = previousState?.headroomPid;
|
|
247556
247582
|
if (orphanPid !== void 0 && ports.isRunning(orphanPid)) {
|
|
@@ -247576,7 +247602,12 @@ async function runSupervisor(config2, ports, options = {}) {
|
|
|
247576
247602
|
ports.log(`claude-use headroom supervisor: headroom pid ${String(headroomPid)} died`);
|
|
247577
247603
|
headroomPid = void 0;
|
|
247578
247604
|
runningHash = void 0;
|
|
247579
|
-
writeHeadroomState(fs11, paths.headroomStateFile, {
|
|
247605
|
+
writeHeadroomState(fs11, paths.headroomStateFile, {
|
|
247606
|
+
supervisorPid: ports.ownPid,
|
|
247607
|
+
version: version2,
|
|
247608
|
+
installedSource,
|
|
247609
|
+
...lastPort === void 0 ? {} : { lastPort }
|
|
247610
|
+
});
|
|
247580
247611
|
}
|
|
247581
247612
|
if (consecutiveFailures >= HEADROOM_START_RETRY_BUDGET) {
|
|
247582
247613
|
return fail(`headroom failed to become ready ${String(consecutiveFailures)} times in a row; giving up`);
|
|
@@ -247584,17 +247615,25 @@ async function runSupervisor(config2, ports, options = {}) {
|
|
|
247584
247615
|
if (installedSource !== config2.source && !ensureInstalled()) {
|
|
247585
247616
|
return fail(`could not install headroom from ${config2.source}: install failed (is uv installed and on PATH?)`);
|
|
247586
247617
|
}
|
|
247587
|
-
const
|
|
247618
|
+
const previousSticky = lastPort;
|
|
247619
|
+
const port = lastPort !== void 0 && await ports.isPortFree(lastPort) ? lastPort : await ports.freePort();
|
|
247588
247620
|
const pid = ports.spawnHeadroom(port, allowlist);
|
|
247589
247621
|
const ready = await waitUntilReady(ports, port);
|
|
247590
247622
|
if (ready) {
|
|
247591
247623
|
consecutiveFailures = 0;
|
|
247592
247624
|
headroomPid = pid;
|
|
247593
247625
|
runningHash = allowlistHash;
|
|
247626
|
+
lastPort = port;
|
|
247627
|
+
if (previousSticky !== void 0 && port !== previousSticky) {
|
|
247628
|
+
ports.log(
|
|
247629
|
+
`claude-use headroom supervisor: sticky port ${String(previousSticky)} was occupied; moving to ${String(port)} (sessions launched against the old port are stale until they relaunch)`
|
|
247630
|
+
);
|
|
247631
|
+
}
|
|
247594
247632
|
writeHeadroomState(fs11, paths.headroomStateFile, {
|
|
247595
247633
|
supervisorPid: ports.ownPid,
|
|
247596
247634
|
headroomPid: pid,
|
|
247597
247635
|
port,
|
|
247636
|
+
lastPort: port,
|
|
247598
247637
|
version: version2,
|
|
247599
247638
|
allowlistHash,
|
|
247600
247639
|
installedSource: config2.source
|
|
@@ -247630,7 +247669,10 @@ async function runSupervisor(config2, ports, options = {}) {
|
|
|
247630
247669
|
`claude-use headroom supervisor: no sessions for ${String(config2.idleShutdownMinutes)} minute(s); stopping headroom and exiting`
|
|
247631
247670
|
);
|
|
247632
247671
|
ports.stopProcess(headroomPid);
|
|
247633
|
-
writeHeadroomState(fs11, paths.headroomStateFile, {
|
|
247672
|
+
writeHeadroomState(fs11, paths.headroomStateFile, {
|
|
247673
|
+
version: version2,
|
|
247674
|
+
...lastPort === void 0 ? {} : { lastPort }
|
|
247675
|
+
});
|
|
247634
247676
|
return 0;
|
|
247635
247677
|
}
|
|
247636
247678
|
} else {
|
|
@@ -247706,7 +247748,7 @@ function formatHeadroomStatus(status) {
|
|
|
247706
247748
|
}
|
|
247707
247749
|
async function realFreePort() {
|
|
247708
247750
|
return await new Promise((resolve, reject) => {
|
|
247709
|
-
const server2 =
|
|
247751
|
+
const server2 = import_node_net2.default.createServer();
|
|
247710
247752
|
server2.unref();
|
|
247711
247753
|
server2.on("error", reject);
|
|
247712
247754
|
server2.listen(0, "127.0.0.1", () => {
|
|
@@ -247742,6 +247784,7 @@ function realSupervisorPorts(paths) {
|
|
|
247742
247784
|
},
|
|
247743
247785
|
isRunning: headroomPidRunning,
|
|
247744
247786
|
freePort: realFreePort,
|
|
247787
|
+
isPortFree: realIsPortFree,
|
|
247745
247788
|
spawnHeadroom: (port, allowlist) => {
|
|
247746
247789
|
import_node_fs9.default.mkdirSync(paths.logsDir, { recursive: true });
|
|
247747
247790
|
const logFd = import_node_fs9.default.openSync(paths.headroomLogPath, "a");
|
|
@@ -247937,7 +247980,7 @@ function addProvider(paths, name, input2) {
|
|
|
247937
247980
|
const parsed = ProviderSchema.safeParse({
|
|
247938
247981
|
displayName: input2.displayName,
|
|
247939
247982
|
baseUrl: input2.baseUrl,
|
|
247940
|
-
tokenEnv: input2.tokenEnv,
|
|
247983
|
+
...input2.tokenEnv === void 0 ? {} : { tokenEnv: input2.tokenEnv },
|
|
247941
247984
|
...input2.env === void 0 || Object.keys(input2.env).length === 0 ? {} : { env: input2.env }
|
|
247942
247985
|
});
|
|
247943
247986
|
if (!parsed.success) {
|
|
@@ -247976,12 +248019,12 @@ function resolveProvider(params) {
|
|
|
247976
248019
|
message: `claude-use: no provider named "${name}". ` + (known.length > 0 ? `Known providers: ${known.join(", ")}.` : "No providers are defined yet; run `claude-use provider add`.")
|
|
247977
248020
|
};
|
|
247978
248021
|
}
|
|
247979
|
-
const token = params.env[definition.tokenEnv];
|
|
248022
|
+
const token = definition.tokenEnv !== void 0 ? params.env[definition.tokenEnv] : definition.env?.ANTHROPIC_AUTH_TOKEN;
|
|
247980
248023
|
if (token === void 0 || token === "") {
|
|
247981
248024
|
return {
|
|
247982
248025
|
ok: false,
|
|
247983
248026
|
status: PROVIDER_MISSING_TOKEN_EXIT,
|
|
247984
|
-
message: `claude-use: provider ${name} needs ${definition.tokenEnv} set in your environment`
|
|
248027
|
+
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`
|
|
247985
248028
|
};
|
|
247986
248029
|
}
|
|
247987
248030
|
return { ok: true, provider: { name, definition, token } };
|
|
@@ -248000,14 +248043,16 @@ function collectEnvPairs(value, previous = {}) {
|
|
|
248000
248043
|
}
|
|
248001
248044
|
function registerProviderCommand(program2, paths) {
|
|
248002
248045
|
const provider = program2.command("provider").description("Manage API providers the launcher can route a session through.");
|
|
248003
|
-
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.").
|
|
248046
|
+
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) => {
|
|
248004
248047
|
addProvider(paths, name, {
|
|
248005
248048
|
displayName: options.displayName,
|
|
248006
248049
|
baseUrl: options.baseUrl,
|
|
248007
|
-
tokenEnv: options.tokenEnv,
|
|
248050
|
+
...options.tokenEnv === void 0 ? {} : { tokenEnv: options.tokenEnv },
|
|
248008
248051
|
...options.env === void 0 ? {} : { env: options.env }
|
|
248009
248052
|
});
|
|
248010
|
-
console.log(
|
|
248053
|
+
console.log(
|
|
248054
|
+
options.tokenEnv === void 0 ? `Created provider "${name}" (${options.baseUrl}, fixed env credential).` : `Created provider "${name}" (${options.baseUrl}, token from ${options.tokenEnv}).`
|
|
248055
|
+
);
|
|
248011
248056
|
});
|
|
248012
248057
|
provider.command("list").description("List every API provider.").action(() => {
|
|
248013
248058
|
const entries = listProviders(paths);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-use",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.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>",
|