claudish 7.20.0 → 7.21.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.js +415 -176
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -651,7 +651,7 @@ var init_onepassword_config = __esm(() => {
|
|
|
651
651
|
});
|
|
652
652
|
|
|
653
653
|
// src/version.ts
|
|
654
|
-
var VERSION = "7.
|
|
654
|
+
var VERSION = "7.21.0";
|
|
655
655
|
|
|
656
656
|
// src/logger.ts
|
|
657
657
|
var exports_logger = {};
|
|
@@ -3654,7 +3654,10 @@ var require_sdk = __commonJS((exports) => {
|
|
|
3654
3654
|
var exports_onepassword = {};
|
|
3655
3655
|
__export(exports_onepassword, {
|
|
3656
3656
|
withSdkRetry: () => withSdkRetry,
|
|
3657
|
+
wasOpAuthorizationDenied: () => wasOpAuthorizationDenied,
|
|
3657
3658
|
valueTail: () => valueTail,
|
|
3659
|
+
setScreenLockProbe: () => setScreenLockProbe,
|
|
3660
|
+
setLockRetryTiming: () => setLockRetryTiming,
|
|
3658
3661
|
resolveSecretsPartial: () => resolveSecretsPartial,
|
|
3659
3662
|
resolveSecrets: () => resolveSecrets,
|
|
3660
3663
|
resolveSdkAuth: () => resolveSdkAuth,
|
|
@@ -3663,7 +3666,10 @@ __export(exports_onepassword, {
|
|
|
3663
3666
|
resolveGlobImport: () => resolveGlobImport,
|
|
3664
3667
|
resolveDesktopAccount: () => resolveDesktopAccount,
|
|
3665
3668
|
resetSdkClientCache: () => resetSdkClientCache,
|
|
3669
|
+
resetOpFailures: () => resetOpFailures,
|
|
3670
|
+
renderOpFailureNotice: () => renderOpFailureNotice,
|
|
3666
3671
|
recordOpHydratedVars: () => recordOpHydratedVars,
|
|
3672
|
+
recordOpFailure: () => recordOpFailure,
|
|
3667
3673
|
readEnvironment: () => readEnvironment,
|
|
3668
3674
|
parseOpFlag: () => parseOpFlag,
|
|
3669
3675
|
parseGlobImport: () => parseGlobImport,
|
|
@@ -3671,16 +3677,20 @@ __export(exports_onepassword, {
|
|
|
3671
3677
|
listVaults: () => listVaults,
|
|
3672
3678
|
listItems: () => listItems,
|
|
3673
3679
|
isTransientSdkError: () => isTransientSdkError,
|
|
3680
|
+
isScreenLocked: () => isScreenLocked,
|
|
3674
3681
|
isOpReference: () => isOpReference,
|
|
3675
3682
|
isOpHydratedVar: () => isOpHydratedVar,
|
|
3683
|
+
isLockedDenial: () => isLockedDenial,
|
|
3676
3684
|
isGlobImport: () => isGlobImport,
|
|
3677
3685
|
globToRegExp: () => globToRegExp,
|
|
3686
|
+
getOpFailures: () => getOpFailures,
|
|
3678
3687
|
filterGlobFields: () => filterGlobFields,
|
|
3679
3688
|
envNameFromOpRef: () => envNameFromOpRef,
|
|
3680
3689
|
discoverItemFieldsById: () => discoverItemFieldsById,
|
|
3681
3690
|
discoverItemFields: () => discoverItemFields,
|
|
3682
3691
|
detectSdkAuth: () => detectSdkAuth,
|
|
3683
3692
|
defaultSdkClientFactory: () => defaultSdkClientFactory,
|
|
3693
|
+
defaultScreenLockProbe: () => defaultScreenLockProbe,
|
|
3684
3694
|
defaultOpAccountLister: () => defaultOpAccountLister,
|
|
3685
3695
|
collectConfigImports: () => collectConfigImports,
|
|
3686
3696
|
buildAuthError: () => buildAuthError,
|
|
@@ -3700,6 +3710,43 @@ function recordOpHydratedVars(names) {
|
|
|
3700
3710
|
function isOpHydratedVar(name) {
|
|
3701
3711
|
return !!name && opHydratedVars.has(name);
|
|
3702
3712
|
}
|
|
3713
|
+
function recordOpFailure(failure) {
|
|
3714
|
+
const dup = opSourceFailures.some((f) => f.kind === failure.kind && f.source === failure.source && f.message === failure.message);
|
|
3715
|
+
if (!dup)
|
|
3716
|
+
opSourceFailures.push(failure);
|
|
3717
|
+
}
|
|
3718
|
+
function getOpFailures() {
|
|
3719
|
+
return opSourceFailures;
|
|
3720
|
+
}
|
|
3721
|
+
function resetOpFailures() {
|
|
3722
|
+
opSourceFailures.length = 0;
|
|
3723
|
+
}
|
|
3724
|
+
function wasOpAuthorizationDenied() {
|
|
3725
|
+
return opSourceFailures.some((f) => /denied authorization/i.test(f.message));
|
|
3726
|
+
}
|
|
3727
|
+
function renderOpFailureNotice(envVar) {
|
|
3728
|
+
if (opSourceFailures.length === 0)
|
|
3729
|
+
return [];
|
|
3730
|
+
const lines = [`1Password was consulted for ${envVar} this run and failed:`];
|
|
3731
|
+
for (const f of opSourceFailures) {
|
|
3732
|
+
const where = f.source ? `${f.kind} ${f.source}` : f.kind;
|
|
3733
|
+
lines.push(` ${where} \u2014 ${f.message.split(`
|
|
3734
|
+
`)[0]}`);
|
|
3735
|
+
}
|
|
3736
|
+
lines.push("");
|
|
3737
|
+
if (wasOpAuthorizationDenied()) {
|
|
3738
|
+
lines.push(" The 1Password desktop app declined to release secrets. This happens when");
|
|
3739
|
+
lines.push(" the approval prompt was dismissed, or when your Mac is locked and the");
|
|
3740
|
+
lines.push(" prompt cannot be shown at all.");
|
|
3741
|
+
lines.push("");
|
|
3742
|
+
lines.push(" Fix: unlock the Mac, approve the 1Password prompt, and re-run.");
|
|
3743
|
+
lines.push(" Headless (no desktop app): export OP_SERVICE_ACCOUNT_TOKEN='ops_...'");
|
|
3744
|
+
} else {
|
|
3745
|
+
lines.push(" Fix: check the reference resolves \u2014 claudish config \u2192 1Password tab.");
|
|
3746
|
+
lines.push(" Headless (no desktop app): export OP_SERVICE_ACCOUNT_TOKEN='ops_...'");
|
|
3747
|
+
}
|
|
3748
|
+
return lines;
|
|
3749
|
+
}
|
|
3703
3750
|
function buildAuthError(detail) {
|
|
3704
3751
|
return new Error(`${detail}
|
|
3705
3752
|
Set OP_SERVICE_ACCOUNT_TOKEN (service account, headless) or OP_ACCOUNT (your 1Password account URL, e.g. my-team.1password.com) for the desktop app \u2014 or set \`onepasswordAccount\` in ~/.claudish/config.json.`);
|
|
@@ -4035,7 +4082,97 @@ function runSdkExclusive(op, label = "op:sdk-op", meta) {
|
|
|
4035
4082
|
function sdkSleep(ms) {
|
|
4036
4083
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
4037
4084
|
}
|
|
4085
|
+
function setLockRetryTiming(opts) {
|
|
4086
|
+
lockRetrySeconds = opts?.seconds ?? LOCK_RETRY_SECONDS;
|
|
4087
|
+
lockTickMs = opts?.tickMs ?? 1000;
|
|
4088
|
+
}
|
|
4089
|
+
function setScreenLockProbe(probe) {
|
|
4090
|
+
screenLockProbe = probe ?? defaultScreenLockProbe;
|
|
4091
|
+
}
|
|
4092
|
+
function isScreenLocked() {
|
|
4093
|
+
return screenLockProbe();
|
|
4094
|
+
}
|
|
4095
|
+
function isLockedDenial(err, env = process.env) {
|
|
4096
|
+
const msg = (err instanceof Error ? err.message : String(err)).toLowerCase();
|
|
4097
|
+
if (!msg.includes("denied authorization"))
|
|
4098
|
+
return false;
|
|
4099
|
+
if (env.OP_SERVICE_ACCOUNT_TOKEN)
|
|
4100
|
+
return false;
|
|
4101
|
+
return isScreenLocked();
|
|
4102
|
+
}
|
|
4103
|
+
async function countdownForUnlock(round, rounds) {
|
|
4104
|
+
const ttyOut = process.stderr.isTTY === true;
|
|
4105
|
+
const ttyIn = process.stdin.isTTY === true;
|
|
4106
|
+
let cancelled = false;
|
|
4107
|
+
if (round === 1) {
|
|
4108
|
+
process.stderr.write(`
|
|
4109
|
+
${bold("\uD83D\uDD10 1Password needs your OK \u2014 but your Mac is locked, so it can't ask.")}
|
|
4110
|
+
Unlock your Mac and approve the popup. Claudish picks it up from there.
|
|
4111
|
+
|
|
4112
|
+
`);
|
|
4113
|
+
}
|
|
4114
|
+
let restoreInput = () => {};
|
|
4115
|
+
if (ttyIn) {
|
|
4116
|
+
const onKey = (buf) => {
|
|
4117
|
+
const k = buf.toString();
|
|
4118
|
+
if (k === "\x1B" || k === "q" || k === "\x03")
|
|
4119
|
+
cancelled = true;
|
|
4120
|
+
};
|
|
4121
|
+
const wasRaw = process.stdin.isRaw === true;
|
|
4122
|
+
try {
|
|
4123
|
+
process.stdin.setRawMode(true);
|
|
4124
|
+
process.stdin.resume();
|
|
4125
|
+
process.stdin.on("data", onKey);
|
|
4126
|
+
restoreInput = () => {
|
|
4127
|
+
process.stdin.off("data", onKey);
|
|
4128
|
+
process.stdin.setRawMode(wasRaw);
|
|
4129
|
+
process.stdin.pause();
|
|
4130
|
+
};
|
|
4131
|
+
} catch {
|
|
4132
|
+
restoreInput = () => {};
|
|
4133
|
+
}
|
|
4134
|
+
}
|
|
4135
|
+
const stop = ttyIn ? "Esc to stop waiting" : "Ctrl-C to stop waiting";
|
|
4136
|
+
const line = (secs) => dim(` waiting ${secs}s \xB7 try ${round} of ${rounds} \xB7 ${stop}`);
|
|
4137
|
+
if (!ttyOut)
|
|
4138
|
+
process.stderr.write(`${line(lockRetrySeconds)}
|
|
4139
|
+
`);
|
|
4140
|
+
try {
|
|
4141
|
+
for (let remaining = lockRetrySeconds;remaining > 0; remaining--) {
|
|
4142
|
+
if (cancelled)
|
|
4143
|
+
break;
|
|
4144
|
+
if (!isScreenLocked())
|
|
4145
|
+
break;
|
|
4146
|
+
if (ttyOut)
|
|
4147
|
+
process.stderr.write(`\r\x1B[2K${line(remaining)}`);
|
|
4148
|
+
await sdkSleep(lockTickMs);
|
|
4149
|
+
}
|
|
4150
|
+
} finally {
|
|
4151
|
+
restoreInput();
|
|
4152
|
+
if (ttyOut)
|
|
4153
|
+
process.stderr.write("\r\x1B[2K");
|
|
4154
|
+
}
|
|
4155
|
+
if (cancelled) {
|
|
4156
|
+
process.stderr.write(` OK, not waiting. You can unlock and re-run any time.
|
|
4157
|
+
`);
|
|
4158
|
+
return "cancel";
|
|
4159
|
+
}
|
|
4160
|
+
return "retry";
|
|
4161
|
+
}
|
|
4038
4162
|
async function withSdkRetry(op, label = "op:sdk-op") {
|
|
4163
|
+
for (let round = 1;; round++) {
|
|
4164
|
+
try {
|
|
4165
|
+
return await withSdkTransientRetry(op, label);
|
|
4166
|
+
} catch (err) {
|
|
4167
|
+
if (round > LOCK_RETRY_ROUNDS || !isLockedDenial(err))
|
|
4168
|
+
throw err;
|
|
4169
|
+
if (await countdownForUnlock(round, LOCK_RETRY_ROUNDS) === "cancel")
|
|
4170
|
+
throw err;
|
|
4171
|
+
resetSdkClientCache();
|
|
4172
|
+
}
|
|
4173
|
+
}
|
|
4174
|
+
}
|
|
4175
|
+
async function withSdkTransientRetry(op, label) {
|
|
4039
4176
|
const MAX_ATTEMPTS = 3;
|
|
4040
4177
|
let lastErr;
|
|
4041
4178
|
for (let attempt = 1;attempt <= MAX_ATTEMPTS; attempt++) {
|
|
@@ -4211,7 +4348,7 @@ async function readEnvironment(environmentId, opts = {}) {
|
|
|
4211
4348
|
}
|
|
4212
4349
|
return out;
|
|
4213
4350
|
}
|
|
4214
|
-
var OP_REF_RE, opHydratedVars, ENV_VAR_NAME_RE, sdkClientCache, defaultSdkClientFactory = async (auth) => {
|
|
4351
|
+
var OP_REF_RE, opHydratedVars, opSourceFailures, ENV_VAR_NAME_RE, sdkClientCache, defaultSdkClientFactory = async (auth) => {
|
|
4215
4352
|
const key = sdkAuthCacheKey(auth);
|
|
4216
4353
|
const cached = sdkClientCache.get(key);
|
|
4217
4354
|
if (cached)
|
|
@@ -4232,7 +4369,21 @@ var OP_REF_RE, opHydratedVars, ENV_VAR_NAME_RE, sdkClientCache, defaultSdkClient
|
|
|
4232
4369
|
sdkClientCache.set(key, build);
|
|
4233
4370
|
build.catch(() => sdkClientCache.delete(key));
|
|
4234
4371
|
return build;
|
|
4235
|
-
}, sdkQueue,
|
|
4372
|
+
}, sdkQueue, LOCK_RETRY_ROUNDS = 3, LOCK_RETRY_SECONDS = 10, lockRetrySeconds, lockTickMs = 1000, styled = (code, s) => process.stderr.isTTY === true ? `\x1B[${code}m${s}\x1B[0m` : s, bold = (s) => styled("1", s), dim = (s) => styled("2", s), defaultScreenLockProbe = () => {
|
|
4373
|
+
if (process.platform !== "darwin")
|
|
4374
|
+
return false;
|
|
4375
|
+
try {
|
|
4376
|
+
const res = spawnSync("ioreg", ["-n", "Root", "-d1", "-a"], {
|
|
4377
|
+
encoding: "utf-8",
|
|
4378
|
+
timeout: 2000
|
|
4379
|
+
});
|
|
4380
|
+
if (res.status !== 0 || typeof res.stdout !== "string")
|
|
4381
|
+
return false;
|
|
4382
|
+
return /CGSSessionScreenIsLocked<\/key>\s*(?:<true\/>|<integer>1<\/integer>)/.test(res.stdout);
|
|
4383
|
+
} catch {
|
|
4384
|
+
return false;
|
|
4385
|
+
}
|
|
4386
|
+
}, screenLockProbe, defaultOpAccountLister = () => {
|
|
4236
4387
|
try {
|
|
4237
4388
|
const res = spawnSync("op", ["account", "list", "--format=json"], { encoding: "utf-8" });
|
|
4238
4389
|
if (res.error || res.status !== 0)
|
|
@@ -4263,9 +4414,12 @@ var init_onepassword = __esm(() => {
|
|
|
4263
4414
|
init_startup_trace();
|
|
4264
4415
|
OP_REF_RE = /^op:\/\/[^\s]+$/;
|
|
4265
4416
|
opHydratedVars = new Set;
|
|
4417
|
+
opSourceFailures = [];
|
|
4266
4418
|
ENV_VAR_NAME_RE = /^[A-Z_][A-Z0-9_]*$/;
|
|
4267
4419
|
sdkClientCache = new Map;
|
|
4268
4420
|
sdkQueue = Promise.resolve();
|
|
4421
|
+
lockRetrySeconds = LOCK_RETRY_SECONDS;
|
|
4422
|
+
screenLockProbe = defaultScreenLockProbe;
|
|
4269
4423
|
});
|
|
4270
4424
|
|
|
4271
4425
|
// src/auth/credentials/op-source.ts
|
|
@@ -4571,12 +4725,14 @@ async function resolveOpKeyForEnvVarsInner(wanted, opts = {}, span) {
|
|
|
4571
4725
|
} catch (err) {
|
|
4572
4726
|
if (err instanceof OpAuthError && onAuthFailure === "skip") {
|
|
4573
4727
|
console.error(`[claudish] 1Password auth unavailable, skipping op:// keys: ${err.message}`);
|
|
4728
|
+
const { recordOpFailure: recordOpFailure3 } = await Promise.resolve().then(() => (init_onepassword(), exports_onepassword));
|
|
4729
|
+
recordOpFailure3({ kind: "auth", message: err.message });
|
|
4574
4730
|
return {};
|
|
4575
4731
|
}
|
|
4576
4732
|
throw err;
|
|
4577
4733
|
}
|
|
4578
4734
|
}
|
|
4579
|
-
const { collectConfigImports: collectConfigImports2, resolveSecrets: resolveSecrets2, recordOpHydratedVars: recordOpHydratedVars2 } = await Promise.resolve().then(() => (init_onepassword(), exports_onepassword));
|
|
4735
|
+
const { collectConfigImports: collectConfigImports2, resolveSecrets: resolveSecrets2, recordOpHydratedVars: recordOpHydratedVars2, recordOpFailure: recordOpFailure2 } = await Promise.resolve().then(() => (init_onepassword(), exports_onepassword));
|
|
4580
4736
|
const cfg = readConfigRaw();
|
|
4581
4737
|
const out = {};
|
|
4582
4738
|
try {
|
|
@@ -4613,6 +4769,7 @@ async function resolveOpKeyForEnvVarsInner(wanted, opts = {}, span) {
|
|
|
4613
4769
|
} catch (globErr) {
|
|
4614
4770
|
const m = globErr instanceof Error ? globErr.message : String(globErr);
|
|
4615
4771
|
console.error(`[claudish] 1Password import skipped: ${m}`);
|
|
4772
|
+
recordOpFailure2({ kind: "import", source: globPath, message: m });
|
|
4616
4773
|
}
|
|
4617
4774
|
}
|
|
4618
4775
|
if (cfg.customEndpoints && typeof cfg.customEndpoints === "object") {
|
|
@@ -4654,16 +4811,19 @@ async function resolveOpKeyForEnvVarsInner(wanted, opts = {}, span) {
|
|
|
4654
4811
|
} catch (envErr) {
|
|
4655
4812
|
const m = envErr instanceof Error ? envErr.message : String(envErr);
|
|
4656
4813
|
console.error(`[claudish] 1Password environment skipped: ${m}`);
|
|
4814
|
+
recordOpFailure2({ kind: "environment", source: envId, message: m });
|
|
4657
4815
|
}
|
|
4658
4816
|
}
|
|
4659
4817
|
}
|
|
4660
4818
|
} catch (err) {
|
|
4661
4819
|
if (err instanceof OpAuthError && onAuthFailure === "skip") {
|
|
4662
4820
|
console.error(`[claudish] 1Password resolution skipped: ${err.message}`);
|
|
4821
|
+
recordOpFailure2({ kind: "auth", message: err.message });
|
|
4663
4822
|
return out;
|
|
4664
4823
|
}
|
|
4665
4824
|
const message = err instanceof Error ? err.message : String(err);
|
|
4666
4825
|
console.error(`[claudish] 1Password secret resolution failed: ${message}`);
|
|
4826
|
+
recordOpFailure2({ kind: "reference", message });
|
|
4667
4827
|
if (onAuthFailure === "throw")
|
|
4668
4828
|
throw err;
|
|
4669
4829
|
}
|
|
@@ -27650,6 +27810,9 @@ function loadConfig() {
|
|
|
27650
27810
|
if (config2.onepasswordEnvironments !== undefined) {
|
|
27651
27811
|
merged.onepasswordEnvironments = config2.onepasswordEnvironments;
|
|
27652
27812
|
}
|
|
27813
|
+
if (config2.anthropicApiBilling !== undefined) {
|
|
27814
|
+
merged.anthropicApiBilling = config2.anthropicApiBilling;
|
|
27815
|
+
}
|
|
27653
27816
|
if (config2.localProviders !== undefined) {
|
|
27654
27817
|
merged.localProviders = Array.from(new Set(config2.localProviders)).sort();
|
|
27655
27818
|
}
|
|
@@ -31758,6 +31921,14 @@ var init_web_search_detector = __esm(() => {
|
|
|
31758
31921
|
WEB_SEARCH_NAMES = new Set(["web_search", "brave_web_search", "tavily_search"]);
|
|
31759
31922
|
});
|
|
31760
31923
|
|
|
31924
|
+
// src/handlers/shared/stream-parsers/message-start-usage.ts
|
|
31925
|
+
function messageStartUsage(priorInputTokens) {
|
|
31926
|
+
return {
|
|
31927
|
+
input_tokens: priorInputTokens && priorInputTokens > 0 ? priorInputTokens : 100,
|
|
31928
|
+
output_tokens: 1
|
|
31929
|
+
};
|
|
31930
|
+
}
|
|
31931
|
+
|
|
31761
31932
|
// src/handlers/shared/stream-parsers/openai-sse.ts
|
|
31762
31933
|
function validateToolArguments(toolName, argsStr, toolSchemas, textContent) {
|
|
31763
31934
|
const result = validateAndRepairToolCall(toolName, argsStr, toolSchemas, textContent);
|
|
@@ -31787,7 +31958,7 @@ function createStreamingState() {
|
|
|
31787
31958
|
accumulatedText: ""
|
|
31788
31959
|
};
|
|
31789
31960
|
}
|
|
31790
|
-
function createStreamingResponseHandler(c, response, adapter, target, middlewareManager, onTokenUpdate, toolSchemas, toolNameMap) {
|
|
31961
|
+
function createStreamingResponseHandler(c, response, adapter, target, middlewareManager, onTokenUpdate, toolSchemas, toolNameMap, priorInputTokens) {
|
|
31791
31962
|
log(`[Streaming] ===== HANDLER STARTED for ${target} =====`);
|
|
31792
31963
|
let isClosed = false;
|
|
31793
31964
|
let ping = null;
|
|
@@ -31816,7 +31987,7 @@ data: ${JSON.stringify(d)}
|
|
|
31816
31987
|
model: target,
|
|
31817
31988
|
stop_reason: null,
|
|
31818
31989
|
stop_sequence: null,
|
|
31819
|
-
usage:
|
|
31990
|
+
usage: messageStartUsage(priorInputTokens)
|
|
31820
31991
|
}
|
|
31821
31992
|
});
|
|
31822
31993
|
send("ping", { type: "ping" });
|
|
@@ -31929,7 +32100,10 @@ data: ${JSON.stringify(d)}
|
|
|
31929
32100
|
send("message_delta", {
|
|
31930
32101
|
type: "message_delta",
|
|
31931
32102
|
delta: { stop_reason: stopReason, stop_sequence: null },
|
|
31932
|
-
usage: {
|
|
32103
|
+
usage: {
|
|
32104
|
+
...state.usage?.prompt_tokens ? { input_tokens: state.usage.prompt_tokens } : {},
|
|
32105
|
+
output_tokens: state.usage?.completion_tokens || 0
|
|
32106
|
+
}
|
|
31933
32107
|
});
|
|
31934
32108
|
send("message_stop", { type: "message_stop" });
|
|
31935
32109
|
}
|
|
@@ -31940,7 +32114,7 @@ data: ${JSON.stringify(d)}
|
|
|
31940
32114
|
} else {
|
|
31941
32115
|
const estimatedOutputTokens = Math.ceil(state.accumulatedText.length / 4);
|
|
31942
32116
|
log(`[Streaming] No usage data from provider, estimating: ~${estimatedOutputTokens} output tokens`);
|
|
31943
|
-
onTokenUpdate(100, estimatedOutputTokens);
|
|
32117
|
+
onTokenUpdate(priorInputTokens || 100, estimatedOutputTokens);
|
|
31944
32118
|
}
|
|
31945
32119
|
}
|
|
31946
32120
|
if (!isClosed) {
|
|
@@ -37558,7 +37732,7 @@ data: ${JSON.stringify(data)}
|
|
|
37558
37732
|
model: opts.modelName,
|
|
37559
37733
|
stop_reason: null,
|
|
37560
37734
|
stop_sequence: null,
|
|
37561
|
-
usage:
|
|
37735
|
+
usage: messageStartUsage(opts.priorInputTokens)
|
|
37562
37736
|
}
|
|
37563
37737
|
});
|
|
37564
37738
|
send("ping", { type: "ping" });
|
|
@@ -37602,7 +37776,10 @@ data: ${JSON.stringify(data)}
|
|
|
37602
37776
|
send("message_delta", {
|
|
37603
37777
|
type: "message_delta",
|
|
37604
37778
|
delta: { stop_reason: hasToolCalls ? "tool_use" : "end_turn", stop_sequence: null },
|
|
37605
|
-
usage: {
|
|
37779
|
+
usage: {
|
|
37780
|
+
...inputTokens > 0 ? { input_tokens: inputTokens } : {},
|
|
37781
|
+
output_tokens: outputTokens
|
|
37782
|
+
}
|
|
37606
37783
|
});
|
|
37607
37784
|
send("message_stop", { type: "message_stop" });
|
|
37608
37785
|
}
|
|
@@ -37805,7 +37982,7 @@ data: ${JSON.stringify(data)}
|
|
|
37805
37982
|
model: opts.modelName,
|
|
37806
37983
|
stop_reason: null,
|
|
37807
37984
|
stop_sequence: null,
|
|
37808
|
-
usage:
|
|
37985
|
+
usage: messageStartUsage(opts.priorInputTokens)
|
|
37809
37986
|
}
|
|
37810
37987
|
});
|
|
37811
37988
|
send("ping", { type: "ping" });
|
|
@@ -37826,7 +38003,10 @@ data: ${JSON.stringify(data)}
|
|
|
37826
38003
|
send("message_delta", {
|
|
37827
38004
|
type: "message_delta",
|
|
37828
38005
|
delta: { stop_reason: "end_turn", stop_sequence: null },
|
|
37829
|
-
usage: {
|
|
38006
|
+
usage: {
|
|
38007
|
+
...promptTokens > 0 ? { input_tokens: promptTokens } : {},
|
|
38008
|
+
output_tokens: completionTokens
|
|
38009
|
+
}
|
|
37830
38010
|
});
|
|
37831
38011
|
send("message_stop", { type: "message_stop" });
|
|
37832
38012
|
}
|
|
@@ -37978,7 +38158,7 @@ data: ${JSON.stringify(data)}
|
|
|
37978
38158
|
model: opts.modelName,
|
|
37979
38159
|
stop_reason: null,
|
|
37980
38160
|
stop_sequence: null,
|
|
37981
|
-
usage:
|
|
38161
|
+
usage: messageStartUsage(opts.priorInputTokens)
|
|
37982
38162
|
}
|
|
37983
38163
|
});
|
|
37984
38164
|
send("ping", { type: "ping" });
|
|
@@ -38241,6 +38421,13 @@ data: ${JSON.stringify(data)}
|
|
|
38241
38421
|
} catch {}
|
|
38242
38422
|
}
|
|
38243
38423
|
}
|
|
38424
|
+
},
|
|
38425
|
+
cancel() {
|
|
38426
|
+
isClosed = true;
|
|
38427
|
+
if (pingInterval) {
|
|
38428
|
+
clearInterval(pingInterval);
|
|
38429
|
+
pingInterval = null;
|
|
38430
|
+
}
|
|
38244
38431
|
}
|
|
38245
38432
|
});
|
|
38246
38433
|
return new Response(stream, {
|
|
@@ -38268,6 +38455,7 @@ class TokenTracker {
|
|
|
38268
38455
|
sessionTotalCost = 0;
|
|
38269
38456
|
sessionInputTokens = 0;
|
|
38270
38457
|
sessionOutputTokens = 0;
|
|
38458
|
+
lastInputTokens = 0;
|
|
38271
38459
|
modelNameOverride;
|
|
38272
38460
|
quotaRemaining;
|
|
38273
38461
|
constructor(port, config2) {
|
|
@@ -38284,10 +38472,11 @@ class TokenTracker {
|
|
|
38284
38472
|
this.quotaRemaining = fraction;
|
|
38285
38473
|
}
|
|
38286
38474
|
rewrite() {
|
|
38287
|
-
this.writeFile(this.
|
|
38475
|
+
this.writeFile(this.getLastInputTokens(), this.sessionOutputTokens);
|
|
38288
38476
|
}
|
|
38289
38477
|
update(inputTokens, outputTokens) {
|
|
38290
38478
|
this.sessionInputTokens = inputTokens;
|
|
38479
|
+
this.lastInputTokens = inputTokens;
|
|
38291
38480
|
this.sessionOutputTokens += outputTokens;
|
|
38292
38481
|
const pricing = this.getPricing();
|
|
38293
38482
|
const cost = inputTokens / 1e6 * pricing.inputCostPer1M + outputTokens / 1e6 * pricing.outputCostPer1M;
|
|
@@ -38296,6 +38485,7 @@ class TokenTracker {
|
|
|
38296
38485
|
}
|
|
38297
38486
|
accumulateBoth(inputTokens, outputTokens) {
|
|
38298
38487
|
this.sessionInputTokens += inputTokens;
|
|
38488
|
+
this.lastInputTokens = this.sessionInputTokens;
|
|
38299
38489
|
this.sessionOutputTokens += outputTokens;
|
|
38300
38490
|
const pricing = this.getPricing();
|
|
38301
38491
|
const cost = this.sessionInputTokens / 1e6 * pricing.inputCostPer1M + this.sessionOutputTokens / 1e6 * pricing.outputCostPer1M;
|
|
@@ -38304,6 +38494,7 @@ class TokenTracker {
|
|
|
38304
38494
|
}
|
|
38305
38495
|
updateWithDelta(inputTokens, outputTokens) {
|
|
38306
38496
|
let incrementalInputTokens;
|
|
38497
|
+
this.lastInputTokens = inputTokens;
|
|
38307
38498
|
if (inputTokens >= this.sessionInputTokens) {
|
|
38308
38499
|
incrementalInputTokens = inputTokens - this.sessionInputTokens;
|
|
38309
38500
|
this.sessionInputTokens = inputTokens;
|
|
@@ -38319,10 +38510,11 @@ class TokenTracker {
|
|
|
38319
38510
|
const pricing = this.getPricing();
|
|
38320
38511
|
const cost = incrementalInputTokens / 1e6 * pricing.inputCostPer1M + outputTokens / 1e6 * pricing.outputCostPer1M;
|
|
38321
38512
|
this.sessionTotalCost += cost;
|
|
38322
|
-
this.writeFile(
|
|
38513
|
+
this.writeFile(inputTokens, this.sessionOutputTokens, pricing.isEstimate);
|
|
38323
38514
|
}
|
|
38324
38515
|
updateWithActualCost(inputTokens, outputTokens, actualCost) {
|
|
38325
38516
|
this.sessionInputTokens = inputTokens;
|
|
38517
|
+
this.lastInputTokens = inputTokens;
|
|
38326
38518
|
this.sessionOutputTokens += outputTokens;
|
|
38327
38519
|
if (typeof actualCost === "number" && actualCost > 0) {
|
|
38328
38520
|
this.sessionTotalCost += actualCost;
|
|
@@ -38338,6 +38530,7 @@ class TokenTracker {
|
|
|
38338
38530
|
updateLocal(inputTokens, outputTokens) {
|
|
38339
38531
|
if (inputTokens > 0) {
|
|
38340
38532
|
this.sessionInputTokens = inputTokens;
|
|
38533
|
+
this.lastInputTokens = inputTokens;
|
|
38341
38534
|
}
|
|
38342
38535
|
this.sessionOutputTokens += outputTokens;
|
|
38343
38536
|
this.writeFile(this.sessionInputTokens, this.sessionOutputTokens);
|
|
@@ -38351,6 +38544,9 @@ class TokenTracker {
|
|
|
38351
38544
|
getInputTokens() {
|
|
38352
38545
|
return this.sessionInputTokens;
|
|
38353
38546
|
}
|
|
38547
|
+
getLastInputTokens() {
|
|
38548
|
+
return this.lastInputTokens || this.sessionInputTokens;
|
|
38549
|
+
}
|
|
38354
38550
|
getOutputTokens() {
|
|
38355
38551
|
return this.sessionOutputTokens;
|
|
38356
38552
|
}
|
|
@@ -38892,16 +39088,18 @@ class ComposedHandler {
|
|
|
38892
39088
|
}
|
|
38893
39089
|
};
|
|
38894
39090
|
const streamFormat = this.provider.overrideStreamFormat?.() ?? this.explicitAdapter?.getStreamFormat() ?? this.modelAdapter?.getStreamFormat() ?? this.getAdapter().getStreamFormat();
|
|
39091
|
+
const priorInputTokens = this.tokenTracker.getLastInputTokens();
|
|
38895
39092
|
switch (streamFormat) {
|
|
38896
39093
|
case "openai-sse":
|
|
38897
|
-
return createStreamingResponseHandler(c, response, adapter, this.bareModelName, this.middlewareManager, onTokenUpdate, claudeRequest.tools, toolNameMap);
|
|
39094
|
+
return createStreamingResponseHandler(c, response, adapter, this.bareModelName, this.middlewareManager, onTokenUpdate, claudeRequest.tools, toolNameMap, priorInputTokens);
|
|
38898
39095
|
case "openai-responses-sse":
|
|
38899
39096
|
return createResponsesStreamHandler(c, response, {
|
|
38900
39097
|
modelName: this.bareModelName,
|
|
38901
39098
|
onTokenUpdate,
|
|
38902
39099
|
toolNameMap: adapter.getToolNameMap(),
|
|
38903
39100
|
contextWindow: lookupModelForProvider(this.bareModelName, this.provider.name),
|
|
38904
|
-
onApiError
|
|
39101
|
+
onApiError,
|
|
39102
|
+
priorInputTokens
|
|
38905
39103
|
});
|
|
38906
39104
|
case "anthropic-sse":
|
|
38907
39105
|
return createAnthropicPassthroughStream(c, response, {
|
|
@@ -38921,13 +39119,15 @@ class ComposedHandler {
|
|
|
38921
39119
|
middlewareManager: this.middlewareManager,
|
|
38922
39120
|
onTokenUpdate,
|
|
38923
39121
|
onToolCall,
|
|
38924
|
-
unwrapResponse: this.options.unwrapGeminiResponse
|
|
39122
|
+
unwrapResponse: this.options.unwrapGeminiResponse,
|
|
39123
|
+
priorInputTokens
|
|
38925
39124
|
});
|
|
38926
39125
|
}
|
|
38927
39126
|
case "ollama-jsonl":
|
|
38928
39127
|
return createOllamaJsonlStream(c, response, {
|
|
38929
39128
|
modelName: this.bareModelName,
|
|
38930
|
-
onTokenUpdate
|
|
39129
|
+
onTokenUpdate,
|
|
39130
|
+
priorInputTokens
|
|
38931
39131
|
});
|
|
38932
39132
|
default:
|
|
38933
39133
|
throw new Error(`Unknown stream format: ${streamFormat}`);
|
|
@@ -42414,7 +42614,12 @@ function getMissingKeyError(resolution) {
|
|
|
42414
42614
|
const lines = [];
|
|
42415
42615
|
lines.push(`Error: ${resolution.apiKeyDescription} is required for model "${resolution.fullModelId}"`);
|
|
42416
42616
|
lines.push("");
|
|
42417
|
-
|
|
42617
|
+
const opNotice = renderOpFailureNotice(resolution.requiredApiKeyEnvVar);
|
|
42618
|
+
if (opNotice.length > 0) {
|
|
42619
|
+
lines.push(...opNotice);
|
|
42620
|
+
lines.push("");
|
|
42621
|
+
}
|
|
42622
|
+
lines.push(opNotice.length > 0 ? "Or set the key directly:" : "Set it with:");
|
|
42418
42623
|
lines.push(` export ${resolution.requiredApiKeyEnvVar}='your-key-here'`);
|
|
42419
42624
|
if (resolution.apiKeyUrl) {
|
|
42420
42625
|
lines.push("");
|
|
@@ -42493,6 +42698,7 @@ var init_provider_resolver = __esm(() => {
|
|
|
42493
42698
|
init_provider_definitions();
|
|
42494
42699
|
init_provider_registry();
|
|
42495
42700
|
init_remote_provider_registry();
|
|
42701
|
+
init_onepassword();
|
|
42496
42702
|
init_routing_hints();
|
|
42497
42703
|
API_KEY_INFO = new Proxy({}, {
|
|
42498
42704
|
get(_target, prop) {
|
|
@@ -58411,7 +58617,8 @@ var init_config = __esm(() => {
|
|
|
58411
58617
|
OPENAI_BASE_URL: "OPENAI_BASE_URL",
|
|
58412
58618
|
CLAUDISH_SUMMARIZE_TOOLS: "CLAUDISH_SUMMARIZE_TOOLS",
|
|
58413
58619
|
CLAUDISH_DIAG_MODE: "CLAUDISH_DIAG_MODE",
|
|
58414
|
-
CLAUDISH_DEBUG: "CLAUDISH_DEBUG"
|
|
58620
|
+
CLAUDISH_DEBUG: "CLAUDISH_DEBUG",
|
|
58621
|
+
CLAUDISH_ANTHROPIC_API_BILLING: "CLAUDISH_ANTHROPIC_API_BILLING"
|
|
58415
58622
|
};
|
|
58416
58623
|
OPENROUTER_HEADERS = {
|
|
58417
58624
|
"HTTP-Referer": "https://claudish.com",
|
|
@@ -60097,7 +60304,7 @@ function tokBarCells(tokensPerSec, maxTokPerSec, tokWidth) {
|
|
|
60097
60304
|
const raw2 = Math.round(tokWidth * Math.max(0, tokensPerSec) / denom);
|
|
60098
60305
|
return Math.min(tokWidth, Math.max(0, raw2));
|
|
60099
60306
|
}
|
|
60100
|
-
var C,
|
|
60307
|
+
var C, bold2, A, LATENCY_BUCKETS, latencyFg = "#ffffff", LATENCY_FG_ANSI = "\x1B[38;2;255;255;255m", ANSI_RESET = "\x1B[0m", STAGE_BG, STAGE_FG, STAGE_BG_ANSI;
|
|
60101
60308
|
var init_theme2 = __esm(() => {
|
|
60102
60309
|
C = {
|
|
60103
60310
|
bg: "#000000",
|
|
@@ -60128,10 +60335,10 @@ var init_theme2 = __esm(() => {
|
|
|
60128
60335
|
chipKeyBg: "#3a3a3a",
|
|
60129
60336
|
chipLabelBg: "#222222"
|
|
60130
60337
|
};
|
|
60131
|
-
|
|
60338
|
+
bold2 = createTextAttributes({ bold: true });
|
|
60132
60339
|
A = {
|
|
60133
|
-
bold,
|
|
60134
|
-
boldIf: (enabled) => enabled ?
|
|
60340
|
+
bold: bold2,
|
|
60341
|
+
boldIf: (enabled) => enabled ? bold2 : undefined
|
|
60135
60342
|
};
|
|
60136
60343
|
LATENCY_BUCKETS = [
|
|
60137
60344
|
{ maxMs: 500, hex: "#1f8f3b" },
|
|
@@ -62491,6 +62698,8 @@ async function parseArgs(args) {
|
|
|
62491
62698
|
process.exit(1);
|
|
62492
62699
|
}
|
|
62493
62700
|
config3.defaultProvider = dpArg;
|
|
62701
|
+
} else if (arg === "--anthropic-api-billing") {
|
|
62702
|
+
config3.anthropicApiBilling = true;
|
|
62494
62703
|
} else if (arg === "--op-env" || arg.startsWith("--op-env=")) {
|
|
62495
62704
|
const v = arg.startsWith("--op-env=") ? arg.slice("--op-env=".length) : args[++i];
|
|
62496
62705
|
if (!v) {
|
|
@@ -63465,95 +63674,99 @@ async function probeModelRouting(models, jsonOutput, options = { live: true, tim
|
|
|
63465
63674
|
function printHelp() {
|
|
63466
63675
|
const useColor = !!process.stdout.isTTY && !process.env.NO_COLOR;
|
|
63467
63676
|
const c = (code) => (s) => useColor ? `\x1B[${code}m${s}\x1B[0m` : s;
|
|
63468
|
-
const
|
|
63469
|
-
const
|
|
63677
|
+
const bold3 = c("1");
|
|
63678
|
+
const dim2 = c("2");
|
|
63470
63679
|
const cyan = c("36");
|
|
63471
63680
|
const green = c("32");
|
|
63472
63681
|
const yellow = c("33");
|
|
63473
63682
|
const magenta = c("35");
|
|
63474
63683
|
const blue = c("34");
|
|
63475
|
-
const h = (title) =>
|
|
63684
|
+
const h = (title) => bold3(cyan(`\u258C ${title}`));
|
|
63476
63685
|
console.log(`
|
|
63477
|
-
${
|
|
63478
|
-
${
|
|
63686
|
+
${bold3("claudish")} ${dim2("\xB7")} Run Claude Code with any AI model
|
|
63687
|
+
${dim2("OpenRouter \xB7 Gemini \xB7 OpenAI \xB7 xAI \xB7 MiniMax \xB7 Kimi \xB7 GLM \xB7 Z.AI \xB7 Sakana \xB7 Poe \xB7 LiteLLM \xB7 Local")}
|
|
63479
63688
|
|
|
63480
63689
|
${h("USAGE")}
|
|
63481
|
-
${green("claudish")} ${
|
|
63482
|
-
${green("claudish")} ${yellow("[OPTIONS] <claude-args...>")} ${
|
|
63483
|
-
${green("claudish")} ${green("--team")} ${yellow("a,b,c")} ${yellow('"prompt"')} ${
|
|
63484
|
-
${green("claudish")} ${green("--team")} ${yellow("a,b,c")} ${green("-f")} ${yellow("input.md")} ${
|
|
63690
|
+
${green("claudish")} ${dim2("# Interactive mode (default, model selector)")}
|
|
63691
|
+
${green("claudish")} ${yellow("[OPTIONS] <claude-args...>")} ${dim2("# Single-shot mode (requires --model)")}
|
|
63692
|
+
${green("claudish")} ${green("--team")} ${yellow("a,b,c")} ${yellow('"prompt"')} ${dim2("# Run models in parallel (magmux grid)")}
|
|
63693
|
+
${green("claudish")} ${green("--team")} ${yellow("a,b,c")} ${green("-f")} ${yellow("input.md")} ${dim2("# Team mode with file input")}
|
|
63485
63694
|
|
|
63486
63695
|
${h("MODEL ROUTING")}
|
|
63487
|
-
${
|
|
63488
|
-
${magenta("google@gemini-3-pro")} ${
|
|
63489
|
-
${magenta("openrouter@google/gemini-3-pro")} ${
|
|
63490
|
-
${magenta("oai@gpt-5.3")} ${
|
|
63491
|
-
${magenta("ollama@llama3.2:3")} ${
|
|
63492
|
-
${magenta("ollama@llama3.2:0")} ${
|
|
63493
|
-
|
|
63494
|
-
${
|
|
63495
|
-
${magenta("g, gemini")} ${
|
|
63496
|
-
${magenta("oai")} ${
|
|
63497
|
-
${magenta("cx, codex")} ${
|
|
63498
|
-
${magenta("or")} ${
|
|
63499
|
-
${magenta("x-ai, xai, grok")} ${
|
|
63500
|
-
${magenta("mm, mmax")} ${
|
|
63501
|
-
${magenta("mmc")} ${
|
|
63502
|
-
${magenta("kimi, moon")} ${
|
|
63503
|
-
${magenta("kc")} ${
|
|
63504
|
-
${magenta("glm, zhipu")} ${
|
|
63505
|
-
${magenta("gc")} ${
|
|
63506
|
-
${magenta("z-ai, zai")} ${
|
|
63507
|
-
${magenta("oc, llama, lc, meta")} ${
|
|
63508
|
-
${magenta("zen")} ${
|
|
63509
|
-
${magenta("zengo, zgo")} ${
|
|
63510
|
-
${magenta("v, vertex")} ${
|
|
63511
|
-
${magenta("go")} ${
|
|
63512
|
-
${magenta("poe")} ${
|
|
63513
|
-
${magenta("litellm, ll")} ${
|
|
63514
|
-
${magenta("ds")} ${
|
|
63515
|
-
${magenta("sakana, fugu")} ${
|
|
63516
|
-
${magenta("sc")} ${
|
|
63517
|
-
${magenta("ollama")} ${
|
|
63518
|
-
${magenta("lms, lmstudio")} ${
|
|
63519
|
-
${magenta("vllm")} ${
|
|
63520
|
-
${magenta("mlx")} ${
|
|
63521
|
-
|
|
63522
|
-
${
|
|
63523
|
-
${yellow("google/*, gemini-*")} ${
|
|
63524
|
-
${yellow("openai/*, gpt-*, o1-*")} ${
|
|
63525
|
-
${yellow("x-ai/*, grok-*")} ${
|
|
63526
|
-
${yellow("meta-llama/*, llama-*")} ${
|
|
63527
|
-
${yellow("minimax/*, abab-*")} ${
|
|
63528
|
-
${yellow("moonshot/*, kimi-*")} ${
|
|
63529
|
-
${yellow("zhipu/*, glm-*")} ${
|
|
63530
|
-
${yellow("sakana/*, fugu-*")} ${
|
|
63531
|
-
${yellow("poe:*")} ${
|
|
63532
|
-
${yellow("anthropic/*, claude-*")} ${
|
|
63533
|
-
${yellow("(unknown vendor/)")} ${
|
|
63534
|
-
|
|
63535
|
-
${
|
|
63696
|
+
${bold3("New syntax:")} ${yellow("provider@model[:concurrency]")}
|
|
63697
|
+
${magenta("google@gemini-3-pro")} ${dim2("Direct Google API (explicit)")}
|
|
63698
|
+
${magenta("openrouter@google/gemini-3-pro")} ${dim2("OpenRouter (explicit)")}
|
|
63699
|
+
${magenta("oai@gpt-5.3")} ${dim2("Direct OpenAI API (shortcut)")}
|
|
63700
|
+
${magenta("ollama@llama3.2:3")} ${dim2("Local Ollama, 3 concurrent requests")}
|
|
63701
|
+
${magenta("ollama@llama3.2:0")} ${dim2("Local Ollama, no limits")}
|
|
63702
|
+
|
|
63703
|
+
${bold3("Provider shortcuts:")}
|
|
63704
|
+
${magenta("g, gemini")} ${dim2("->")} Google Gemini ${dim2("google@gemini-3-pro")}
|
|
63705
|
+
${magenta("oai")} ${dim2("->")} OpenAI Direct ${dim2("oai@gpt-5.3")}
|
|
63706
|
+
${magenta("cx, codex")} ${dim2("->")} OpenAI Codex ${dim2("cx@gpt-5.3 (Responses API)")}
|
|
63707
|
+
${magenta("or")} ${dim2("->")} OpenRouter ${dim2("or@openai/gpt-5.3")}
|
|
63708
|
+
${magenta("x-ai, xai, grok")} ${dim2("->")} xAI / Grok ${dim2("x-ai@grok-3")}
|
|
63709
|
+
${magenta("mm, mmax")} ${dim2("->")} MiniMax Direct ${dim2("mm@MiniMax-M2.1")}
|
|
63710
|
+
${magenta("mmc")} ${dim2("->")} MiniMax Coding ${dim2("mmc@MiniMax-M2.1")}
|
|
63711
|
+
${magenta("kimi, moon")} ${dim2("->")} Kimi Direct ${dim2("kimi@kimi-k2-thinking-turbo")}
|
|
63712
|
+
${magenta("kc")} ${dim2("->")} Kimi Coding ${dim2("kc@kimi-k2-thinking-turbo")}
|
|
63713
|
+
${magenta("glm, zhipu")} ${dim2("->")} GLM Direct ${dim2("glm@glm-4.7")}
|
|
63714
|
+
${magenta("gc")} ${dim2("->")} GLM Coding ${dim2("gc@glm-4.7")}
|
|
63715
|
+
${magenta("z-ai, zai")} ${dim2("->")} Z.AI Direct ${dim2("z-ai@glm-4.7")}
|
|
63716
|
+
${magenta("oc, llama, lc, meta")} ${dim2("->")} OllamaCloud ${dim2("oc@llama-3.1")}
|
|
63717
|
+
${magenta("zen")} ${dim2("->")} OpenCode Zen ${dim2("zen@grok-code")}
|
|
63718
|
+
${magenta("zengo, zgo")} ${dim2("->")} OpenCode Zen Go ${dim2("zengo@grok-code")}
|
|
63719
|
+
${magenta("v, vertex")} ${dim2("->")} Vertex AI ${dim2("v@gemini-2.5-flash")}
|
|
63720
|
+
${magenta("go")} ${dim2("->")} Gemini Code Assist ${dim2("go@gemini-2.5-flash")}
|
|
63721
|
+
${magenta("poe")} ${dim2("->")} Poe ${dim2("poe@GPT-4o")}
|
|
63722
|
+
${magenta("litellm, ll")} ${dim2("->")} LiteLLM ${dim2("ll@gpt-4o (needs LITELLM_BASE_URL)")}
|
|
63723
|
+
${magenta("ds")} ${dim2("->")} DeepSeek ${dim2("ds@deepseek-chat")}
|
|
63724
|
+
${magenta("sakana, fugu")} ${dim2("->")} Sakana Fugu ${dim2("fugu@fugu-ultra")}
|
|
63725
|
+
${magenta("sc")} ${dim2("->")} Sakana Subscription ${dim2("sc@fugu-ultra")}
|
|
63726
|
+
${magenta("ollama")} ${dim2("->")} Ollama (local) ${dim2("ollama@llama3.2")}
|
|
63727
|
+
${magenta("lms, lmstudio")} ${dim2("->")} LM Studio (local) ${dim2("lms@qwen")}
|
|
63728
|
+
${magenta("vllm")} ${dim2("->")} vLLM (local) ${dim2("vllm@model")}
|
|
63729
|
+
${magenta("mlx")} ${dim2("->")} MLX (local) ${dim2("mlx@model")}
|
|
63730
|
+
|
|
63731
|
+
${bold3("Native auto-detection")} ${dim2("(when no provider specified):")}
|
|
63732
|
+
${yellow("google/*, gemini-*")} ${dim2("->")} Google API
|
|
63733
|
+
${yellow("openai/*, gpt-*, o1-*")} ${dim2("->")} OpenAI API
|
|
63734
|
+
${yellow("x-ai/*, grok-*")} ${dim2("->")} xAI
|
|
63735
|
+
${yellow("meta-llama/*, llama-*")} ${dim2("->")} OllamaCloud
|
|
63736
|
+
${yellow("minimax/*, abab-*")} ${dim2("->")} MiniMax API
|
|
63737
|
+
${yellow("moonshot/*, kimi-*")} ${dim2("->")} Kimi API
|
|
63738
|
+
${yellow("zhipu/*, glm-*")} ${dim2("->")} GLM API
|
|
63739
|
+
${yellow("sakana/*, fugu-*")} ${dim2("->")} Sakana Fugu
|
|
63740
|
+
${yellow("poe:*")} ${dim2("->")} Poe
|
|
63741
|
+
${yellow("anthropic/*, claude-*")} ${dim2("->")} Native Anthropic
|
|
63742
|
+
${yellow("(unknown vendor/)")} ${dim2("->")} Error (use openrouter@vendor/model)
|
|
63743
|
+
|
|
63744
|
+
${dim2("A defaultProvider (config / --default-provider) catches bare names that match no rule.")}
|
|
63536
63745
|
|
|
63537
63746
|
${h("OPTIONS")}
|
|
63538
63747
|
${green("-i, --interactive")} Run in interactive mode (default when no prompt given)
|
|
63539
63748
|
${green("-m, --model")} ${yellow("<model>")} Model to use (required for single-shot mode)
|
|
63540
63749
|
${green("--profile")} ${yellow("<name>")} Use named profile for model mapping (default profile if omitted)
|
|
63541
63750
|
${green("--default-provider")} ${yellow("<name>")} Fallback provider for bare model names (builtin or customEndpoints key)
|
|
63542
|
-
${
|
|
63751
|
+
${dim2("Precedence: this flag > CLAUDISH_DEFAULT_PROVIDER env > config.json")}
|
|
63752
|
+
${green("--anthropic-api-billing")} Use your real ANTHROPIC_API_KEY for native Claude models
|
|
63753
|
+
${dim2("(metered API billing). Default: the key is hidden so Claude Code")}
|
|
63754
|
+
${dim2("uses your claude.ai subscription. Env: CLAUDISH_ANTHROPIC_API_BILLING")}
|
|
63755
|
+
${dim2("Config: anthropicApiBilling: true")}
|
|
63543
63756
|
${green("--config")} ${yellow("<file>")} Use THIS config file for the run, fully replacing the machine
|
|
63544
|
-
${
|
|
63545
|
-
${
|
|
63546
|
-
${
|
|
63757
|
+
${dim2("global (~/.claudish/config.json) AND project (.claudish.json).")}
|
|
63758
|
+
${dim2("A file naming no op:// source never touches 1Password (no prompt).")}
|
|
63759
|
+
${dim2("Env vars still resolve first. Env: CLAUDISH_CONFIG")}
|
|
63547
63760
|
${green("--op")} ${yellow("<op://glob>")} Load API keys from a 1Password item glob (SDK-based, no op CLI)
|
|
63548
63761
|
${green("--op")} ${yellow("<glob>")} ${green("--list")} Preview which fields the glob would import (names only, no values)
|
|
63549
63762
|
${green("--op-env")} ${yellow("<id>")} Load env vars from a 1Password Environment (highest priority)
|
|
63550
63763
|
${green("--port")} ${yellow("<port>")} Proxy server port (default: random)
|
|
63551
63764
|
${green("-d, --debug-claudish")} Enable claudish debug logging to file (logs/claudish_*.log)
|
|
63552
|
-
${
|
|
63765
|
+
${dim2('Always-on: CLAUDISH_DEBUG=1 env var or "debug": true in config.json')}
|
|
63553
63766
|
${green("--no-debug-claudish")} Force debug logging off for this run (when globally enabled)
|
|
63554
63767
|
${green("--log-off")} Disable always-on structural logging (~/.claudish/logs/)
|
|
63555
63768
|
${green("--log-diag")} ${yellow("<mode>")} Diagnostic output: auto (default), logfile, off
|
|
63556
|
-
${
|
|
63769
|
+
${dim2('Also: CLAUDISH_DIAG_MODE env var or "diagMode" in config.json')}
|
|
63557
63770
|
${green("--log-level")} ${yellow("<level>")} Log verbosity: debug (full), info (truncated), minimal (labels)
|
|
63558
63771
|
${green("-q, --quiet")} Suppress [claudish] log messages (default in single-shot mode)
|
|
63559
63772
|
${green("-v, --verbose")} Show [claudish] log messages (default in interactive mode)
|
|
@@ -63577,13 +63790,13 @@ ${h("OPTIONS")}
|
|
|
63577
63790
|
${h("MODEL DISCOVERY")}
|
|
63578
63791
|
${green("--models")} Top 100 ranked (Firebase + local providers)
|
|
63579
63792
|
${green("--models --provider")} ${yellow("<slug>")} Filter the catalog to one provider
|
|
63580
|
-
${
|
|
63793
|
+
${dim2("e.g. --provider opencode-zen, anthropic, openai")}
|
|
63581
63794
|
${green("--providers")} Every provider + active-model count
|
|
63582
63795
|
${green("-s, --models-search")} ${yellow("<query>")} Fuzzy search: id, brand synonyms (chatgpt,
|
|
63583
|
-
${
|
|
63796
|
+
${dim2("claude, grok), gateways (zen, oc, codex), caps")}
|
|
63584
63797
|
${green("--models-top")} Curated recommended models (flagship + fast)
|
|
63585
63798
|
${green("--probe")} ${yellow("<models...>")} Probe each provider in the fallback chain with
|
|
63586
|
-
${
|
|
63799
|
+
${dim2("a real 1-token request (may incur tiny cost)")}
|
|
63587
63800
|
${green("--no-probe")} Skip live requests, show static chain only
|
|
63588
63801
|
${green("--probe-timeout")} ${yellow("<secs>")} Per-link timeout for live probes (default: 40)
|
|
63589
63802
|
${green("--models-refresh")} Force refresh the slim model catalog from Firebase
|
|
@@ -63592,11 +63805,11 @@ ${h("MODEL DISCOVERY")}
|
|
|
63592
63805
|
|
|
63593
63806
|
${h("TEAM MODE")}
|
|
63594
63807
|
${green("--team")} ${yellow("<models>")} Run multiple models in parallel (comma-separated)
|
|
63595
|
-
${
|
|
63808
|
+
${dim2('Example: --team minimax-m2.5,kimi-k2.5 "prompt"')}
|
|
63596
63809
|
${green("--mode")} ${yellow("<mode>")} Team mode: default (grid), interactive, json
|
|
63597
63810
|
${green("-f, --file")} ${yellow("<path>")} Read prompt from file (use with --team or single-shot)
|
|
63598
63811
|
|
|
63599
|
-
${h("MODEL MAPPING")} ${
|
|
63812
|
+
${h("MODEL MAPPING")} ${dim2("(per-role override)")}
|
|
63600
63813
|
${green("--model-opus")} ${yellow("<model>")} Model for Opus role (planning, complex tasks)
|
|
63601
63814
|
${green("--model-sonnet")} ${yellow("<model>")} Model for Sonnet role (default coding)
|
|
63602
63815
|
${green("--model-haiku")} ${yellow("<model>")} Model for Haiku role (fast tasks, background)
|
|
@@ -63604,13 +63817,13 @@ ${h("MODEL MAPPING")} ${dim("(per-role override)")}
|
|
|
63604
63817
|
|
|
63605
63818
|
${h("SUBCOMMANDS")}
|
|
63606
63819
|
${green("claudish config")} Open the interactive config TUI (profiles,
|
|
63607
|
-
${
|
|
63820
|
+
${dim2("providers, routing, 1Password)")}
|
|
63608
63821
|
${green("claudish providers")} ${yellow("[--json]")} Show provider credential status (no key material)
|
|
63609
63822
|
${green("claudish quota")} ${yellow("[provider]")} Show remaining quota/usage (alias: usage)
|
|
63610
63823
|
${green("claudish serve")} ${yellow("--port <n> --models <p>")} Run the Claude Desktop redirect gateway
|
|
63611
63824
|
${green("claudish update")} Check for updates and install the latest version
|
|
63612
63825
|
|
|
63613
|
-
${
|
|
63826
|
+
${bold3("Profiles:")}
|
|
63614
63827
|
${green("claudish init")} ${yellow("[--local|--global]")} Setup wizard - create config + first profile
|
|
63615
63828
|
${green("claudish profile list")} ${yellow("[scope]")} List all profiles (both scopes by default)
|
|
63616
63829
|
${green("claudish profile add")} ${yellow("[scope]")} Add a new profile
|
|
@@ -63618,103 +63831,104 @@ ${h("SUBCOMMANDS")}
|
|
|
63618
63831
|
${green("claudish profile use")} ${yellow("[name] [scope]")} Set default profile
|
|
63619
63832
|
${green("claudish profile show")} ${yellow("[name] [scope]")} Show profile details
|
|
63620
63833
|
${green("claudish profile edit")} ${yellow("[name] [scope]")} Edit a profile
|
|
63621
|
-
${
|
|
63834
|
+
${dim2("scope = --local (.claudish.json) | --global (~/.claudish/config.json) | (prompted)")}
|
|
63622
63835
|
|
|
63623
|
-
${
|
|
63836
|
+
${bold3("Authentication:")}
|
|
63624
63837
|
${green("claudish login")} ${yellow("[provider]")} Login to an OAuth provider (interactive if omitted)
|
|
63625
63838
|
${green("claudish logout")} ${yellow("[provider]")} Clear OAuth credentials
|
|
63626
|
-
${
|
|
63839
|
+
${dim2("Providers: gemini, kimi")}
|
|
63627
63840
|
|
|
63628
|
-
${h("1PASSWORD")} ${
|
|
63629
|
-
${
|
|
63841
|
+
${h("1PASSWORD")} ${dim2("(SDK-based \u2014 no op CLI needed for secrets)")}
|
|
63842
|
+
${dim2("Auth via OP_SERVICE_ACCOUNT_TOKEN, or OP_ACCOUNT / onepasswordAccount config (DesktopAuth).")}
|
|
63630
63843
|
${green("--op")} ${yellow("<glob> --list")} Preview which fields a glob would import (names only)
|
|
63631
63844
|
${green("--op")} ${yellow("<glob>")} ${yellow("[...args]")} Resolve a glob into env vars, then run a session
|
|
63632
|
-
${
|
|
63633
|
-
${
|
|
63845
|
+
${dim2("Inline op import requires a GLOB (self-names via field labels)")}
|
|
63846
|
+
${dim2('Example: claudish --op "op://Jack/Keys/**" --model gpt-4o "task"')}
|
|
63634
63847
|
${green("--op-env")} ${yellow("<id>")} Load a 1Password Environment (highest-priority source)
|
|
63635
|
-
${
|
|
63848
|
+
${dim2("Persistent setup (single refs, sets, environments, account): claudish config -> 1Password tab")}
|
|
63636
63849
|
|
|
63637
63850
|
${h("CLAUDE CODE FLAG PASSTHROUGH")}
|
|
63638
|
-
${
|
|
63639
|
-
${green("claudish")} --model grok ${yellow("--agent test")} ${yellow('"task"')} ${
|
|
63640
|
-
${green("claudish")} --model grok ${yellow("--effort high")} --stdin ${yellow('"task"')} ${
|
|
63641
|
-
${green("claudish")} --model grok ${yellow("--permission-mode plan")} -i ${
|
|
63642
|
-
${
|
|
63851
|
+
${dim2("Any unrecognized flag is forwarded to Claude Code. Claudish flags can appear in any order.")}
|
|
63852
|
+
${green("claudish")} --model grok ${yellow("--agent test")} ${yellow('"task"')} ${dim2("# --agent passes through")}
|
|
63853
|
+
${green("claudish")} --model grok ${yellow("--effort high")} --stdin ${yellow('"task"')} ${dim2("# --effort passes, --stdin stays")}
|
|
63854
|
+
${green("claudish")} --model grok ${yellow("--permission-mode plan")} -i ${dim2("# works in interactive too")}
|
|
63855
|
+
${dim2("Use -- when a Claude Code flag value starts with '-':")}
|
|
63643
63856
|
${green("claudish")} --model grok ${green("--")} ${yellow('--system-prompt "-verbose mode" "task"')}
|
|
63644
63857
|
|
|
63645
63858
|
${h("CUSTOM MODELS & ENDPOINTS")}
|
|
63646
|
-
${
|
|
63859
|
+
${dim2("Claudish accepts ANY valid model ID from the Firebase catalog, even if not in --models:")}
|
|
63647
63860
|
${green("claudish")} --model ${yellow("openrouter@your_provider/custom-model-123")} ${yellow('"task"')}
|
|
63648
|
-
${
|
|
63861
|
+
${dim2("Named custom endpoints live in ~/.claudish/config.json under 'customEndpoints' and route via @:")}
|
|
63649
63862
|
${green("claudish")} --model ${yellow("my-vllm@llama3.1-70b")} ${yellow('"task"')}
|
|
63650
63863
|
|
|
63651
63864
|
${h("MODES")}
|
|
63652
|
-
${green("\u2022")} ${
|
|
63653
|
-
${green("\u2022")} ${
|
|
63865
|
+
${green("\u2022")} ${bold3("Interactive")} ${dim2("(default):")} shows model selector, starts a persistent session
|
|
63866
|
+
${green("\u2022")} ${bold3("Single-shot")} ${dim2("(--model):")} runs one task headless and exits
|
|
63654
63867
|
|
|
63655
63868
|
${h("NOTES")}
|
|
63656
|
-
${yellow("\u2022")} Permission prompts are ${
|
|
63869
|
+
${yellow("\u2022")} Permission prompts are ${bold3("ENABLED")} by default (normal Claude Code behavior)
|
|
63657
63870
|
${yellow("\u2022")} Use ${green("-y")} / ${green("--auto-approve")} to skip permission prompts
|
|
63658
63871
|
${yellow("\u2022")} Model selector appears ONLY in interactive mode when ${green("--model")} not specified
|
|
63659
63872
|
${yellow("\u2022")} ${green("--dangerous")} disables the sandbox \u2014 use with extreme caution
|
|
63660
63873
|
|
|
63661
63874
|
${h("ENVIRONMENT VARIABLES")}
|
|
63662
|
-
${
|
|
63875
|
+
${dim2("Claudish auto-loads a .env file from the current directory.")}
|
|
63663
63876
|
|
|
63664
|
-
${
|
|
63877
|
+
${bold3("Claude Code installation:")}
|
|
63665
63878
|
${blue("CLAUDE_PATH")} Custom path to Claude Code binary
|
|
63666
|
-
${
|
|
63879
|
+
${dim2("Search: CLAUDE_PATH -> ~/.claude/local/claude -> PATH")}
|
|
63667
63880
|
|
|
63668
|
-
${
|
|
63881
|
+
${bold3("API keys")} ${dim2("(at least one required for cloud models):")}
|
|
63669
63882
|
${blue("OPENROUTER_API_KEY")} OpenRouter (default backend)
|
|
63670
|
-
${blue("GEMINI_API_KEY")} Google Gemini ${
|
|
63671
|
-
${blue("OPENAI_API_KEY")} OpenAI ${
|
|
63672
|
-
${blue("OPENAI_CODEX_API_KEY")} OpenAI Codex / Responses API ${
|
|
63673
|
-
${blue("XAI_API_KEY")} xAI / Grok ${
|
|
63674
|
-
${blue("MINIMAX_API_KEY")} MiniMax ${
|
|
63675
|
-
${blue("MINIMAX_CODING_API_KEY")} MiniMax Coding Plan ${
|
|
63676
|
-
${blue("MOONSHOT_API_KEY")} Kimi / Moonshot ${
|
|
63677
|
-
${blue("KIMI_CODING_API_KEY")} Kimi Coding Plan ${
|
|
63678
|
-
${blue("ZHIPU_API_KEY")} GLM / Zhipu ${
|
|
63679
|
-
${blue("GLM_CODING_API_KEY")} GLM Coding Plan ${
|
|
63680
|
-
${blue("ZAI_API_KEY")} Z.AI ${
|
|
63681
|
-
${blue("DEEPSEEK_API_KEY")} DeepSeek ${
|
|
63682
|
-
${blue("SAKANA_API_KEY")} Sakana Fugu ${
|
|
63683
|
-
${blue("SAKANA_SUBSCRIPTION_API_KEY")} Sakana Fugu Subscription ${
|
|
63684
|
-
${blue("OLLAMA_API_KEY")} OllamaCloud ${
|
|
63685
|
-
${blue("OPENCODE_API_KEY")} OpenCode Zen ${
|
|
63686
|
-
${blue("POE_API_KEY")} Poe ${
|
|
63687
|
-
${blue("LITELLM_API_KEY")} LiteLLM ${
|
|
63688
|
-
${blue("VERTEX_API_KEY")} Vertex AI Express ${
|
|
63689
|
-
${blue("VERTEX_PROJECT")} Vertex AI project ID ${
|
|
63690
|
-
${blue("VERTEX_LOCATION")} Vertex AI region ${
|
|
63883
|
+
${blue("GEMINI_API_KEY")} Google Gemini ${dim2("(g@, gemini@; alias GOOGLE_API_KEY)")}
|
|
63884
|
+
${blue("OPENAI_API_KEY")} OpenAI ${dim2("(oai@)")}
|
|
63885
|
+
${blue("OPENAI_CODEX_API_KEY")} OpenAI Codex / Responses API ${dim2("(cx@, codex@)")}
|
|
63886
|
+
${blue("XAI_API_KEY")} xAI / Grok ${dim2("(x-ai@, grok@)")}
|
|
63887
|
+
${blue("MINIMAX_API_KEY")} MiniMax ${dim2("(mm@, mmax@)")}
|
|
63888
|
+
${blue("MINIMAX_CODING_API_KEY")} MiniMax Coding Plan ${dim2("(mmc@)")}
|
|
63889
|
+
${blue("MOONSHOT_API_KEY")} Kimi / Moonshot ${dim2("(kimi@, moon@; alias KIMI_API_KEY)")}
|
|
63890
|
+
${blue("KIMI_CODING_API_KEY")} Kimi Coding Plan ${dim2("(kc@)")}
|
|
63891
|
+
${blue("ZHIPU_API_KEY")} GLM / Zhipu ${dim2("(glm@, zhipu@; alias GLM_API_KEY)")}
|
|
63892
|
+
${blue("GLM_CODING_API_KEY")} GLM Coding Plan ${dim2("(gc@; alias ZAI_CODING_API_KEY)")}
|
|
63893
|
+
${blue("ZAI_API_KEY")} Z.AI ${dim2("(z-ai@, zai@)")}
|
|
63894
|
+
${blue("DEEPSEEK_API_KEY")} DeepSeek ${dim2("(ds@)")}
|
|
63895
|
+
${blue("SAKANA_API_KEY")} Sakana Fugu ${dim2("(sakana@, fugu@)")}
|
|
63896
|
+
${blue("SAKANA_SUBSCRIPTION_API_KEY")} Sakana Fugu Subscription ${dim2("(sc@; separate subscription key)")}
|
|
63897
|
+
${blue("OLLAMA_API_KEY")} OllamaCloud ${dim2("(oc@, llama@)")}
|
|
63898
|
+
${blue("OPENCODE_API_KEY")} OpenCode Zen ${dim2("(zen@; optional - free models work without it)")}
|
|
63899
|
+
${blue("POE_API_KEY")} Poe ${dim2("(poe@)")}
|
|
63900
|
+
${blue("LITELLM_API_KEY")} LiteLLM ${dim2("(litellm@, ll@; needs LITELLM_BASE_URL)")}
|
|
63901
|
+
${blue("VERTEX_API_KEY")} Vertex AI Express ${dim2("(v@)")}
|
|
63902
|
+
${blue("VERTEX_PROJECT")} Vertex AI project ID ${dim2("(OAuth mode, v@)")}
|
|
63903
|
+
${blue("VERTEX_LOCATION")} Vertex AI region ${dim2("(default: us-central1)")}
|
|
63691
63904
|
${blue("ANTHROPIC_API_KEY")} Placeholder (prevents Claude Code dialog)
|
|
63692
63905
|
${blue("ANTHROPIC_AUTH_TOKEN")} Placeholder (prevents Claude Code login screen)
|
|
63693
63906
|
|
|
63694
|
-
${
|
|
63907
|
+
${bold3("Custom / base-URL overrides:")}
|
|
63695
63908
|
${blue("GEMINI_BASE_URL")} Custom Gemini endpoint
|
|
63696
63909
|
${blue("OPENAI_BASE_URL")} Custom OpenAI / Azure endpoint
|
|
63697
63910
|
${blue("MINIMAX_BASE_URL")} Custom MiniMax endpoint
|
|
63698
|
-
${blue("MOONSHOT_BASE_URL")} Custom Kimi / Moonshot endpoint ${
|
|
63699
|
-
${blue("ZHIPU_BASE_URL")} Custom GLM / Zhipu endpoint ${
|
|
63700
|
-
${blue("SAKANA_BASE_URL")} Custom Sakana endpoint ${
|
|
63701
|
-
${blue("LITELLM_BASE_URL")} LiteLLM gateway base URL ${
|
|
63702
|
-
${blue("OLLAMACLOUD_BASE_URL")} OllamaCloud ${
|
|
63703
|
-
${blue("OPENCODE_BASE_URL")} OpenCode Zen ${
|
|
63704
|
-
|
|
63705
|
-
${
|
|
63706
|
-
${blue("OLLAMA_BASE_URL")} Ollama server ${
|
|
63707
|
-
${blue("LMSTUDIO_BASE_URL")} LM Studio server ${
|
|
63708
|
-
${blue("VLLM_BASE_URL")} vLLM server ${
|
|
63709
|
-
${blue("MLX_BASE_URL")} MLX server ${
|
|
63710
|
-
|
|
63711
|
-
${
|
|
63712
|
-
${blue("CLAUDISH_MODEL")} Default model ${
|
|
63713
|
-
${blue("CLAUDISH_DEFAULT_PROVIDER")} Fallback provider for bare names ${
|
|
63911
|
+
${blue("MOONSHOT_BASE_URL")} Custom Kimi / Moonshot endpoint ${dim2("(alias KIMI_BASE_URL)")}
|
|
63912
|
+
${blue("ZHIPU_BASE_URL")} Custom GLM / Zhipu endpoint ${dim2("(alias GLM_BASE_URL)")}
|
|
63913
|
+
${blue("SAKANA_BASE_URL")} Custom Sakana endpoint ${dim2("(default: https://api.sakana.ai)")}
|
|
63914
|
+
${blue("LITELLM_BASE_URL")} LiteLLM gateway base URL ${dim2("(required for ll@)")}
|
|
63915
|
+
${blue("OLLAMACLOUD_BASE_URL")} OllamaCloud ${dim2("(default: https://ollama.com)")}
|
|
63916
|
+
${blue("OPENCODE_BASE_URL")} OpenCode Zen ${dim2("(default: https://opencode.ai/zen)")}
|
|
63917
|
+
|
|
63918
|
+
${bold3("Local providers:")}
|
|
63919
|
+
${blue("OLLAMA_BASE_URL")} Ollama server ${dim2("(default: http://localhost:11434; alias OLLAMA_HOST)")}
|
|
63920
|
+
${blue("LMSTUDIO_BASE_URL")} LM Studio server ${dim2("(default: http://localhost:1234)")}
|
|
63921
|
+
${blue("VLLM_BASE_URL")} vLLM server ${dim2("(default: http://localhost:8000)")}
|
|
63922
|
+
${blue("MLX_BASE_URL")} MLX server ${dim2("(default: http://127.0.0.1:8080)")}
|
|
63923
|
+
|
|
63924
|
+
${bold3("Claudish settings:")}
|
|
63925
|
+
${blue("CLAUDISH_MODEL")} Default model ${dim2("(default: openai/gpt-5.3)")}
|
|
63926
|
+
${blue("CLAUDISH_DEFAULT_PROVIDER")} Fallback provider for bare names ${dim2("(see --default-provider)")}
|
|
63714
63927
|
${blue("CLAUDISH_PORT")} Default proxy port
|
|
63715
63928
|
${blue("CLAUDISH_CONTEXT_WINDOW")} Override context window size
|
|
63716
63929
|
${blue("CLAUDISH_DIAG_MODE")} Diagnostic output: auto / logfile / off
|
|
63717
|
-
${blue("CLAUDISH_DEBUG")} Always enable debug logging: 1 / true ${
|
|
63930
|
+
${blue("CLAUDISH_DEBUG")} Always enable debug logging: 1 / true ${dim2("(same as -d)")}
|
|
63931
|
+
${blue("CLAUDISH_ANTHROPIC_API_BILLING")} Bill native Claude to your API key ${dim2("(see --anthropic-api-billing)")}
|
|
63718
63932
|
${blue("CLAUDISH_MCP_TOOLS")} MCP tool gating: all / low-level / agentic / channel
|
|
63719
63933
|
${blue("CLAUDISH_MODEL_OPUS")} Override model for Opus role
|
|
63720
63934
|
${blue("CLAUDISH_MODEL_SONNET")} Override model for Sonnet role
|
|
@@ -63722,41 +63936,41 @@ ${h("ENVIRONMENT VARIABLES")}
|
|
|
63722
63936
|
${blue("CLAUDISH_MODEL_SUBAGENT")} Override model for sub-agents
|
|
63723
63937
|
${blue("NO_COLOR")} Set to disable colored output
|
|
63724
63938
|
|
|
63725
|
-
${
|
|
63939
|
+
${bold3("1Password auth:")}
|
|
63726
63940
|
${blue("OP_SERVICE_ACCOUNT_TOKEN")} Service-account token (preferred for headless)
|
|
63727
|
-
${blue("OP_ACCOUNT")} Account URL for DesktopAuth ${
|
|
63941
|
+
${blue("OP_ACCOUNT")} Account URL for DesktopAuth ${dim2("(e.g. my-team.1password.com)")}
|
|
63728
63942
|
|
|
63729
63943
|
${h("EXAMPLES")}
|
|
63730
|
-
${
|
|
63944
|
+
${dim2("# Interactive (default) - model selector")}
|
|
63731
63945
|
${green("claudish")}
|
|
63732
|
-
${green("claudish")} --free ${
|
|
63946
|
+
${green("claudish")} --free ${dim2("# only FREE models")}
|
|
63733
63947
|
|
|
63734
|
-
${
|
|
63948
|
+
${dim2("# Explicit provider routing")}
|
|
63735
63949
|
${green("claudish")} --model ${magenta("google@gemini-3-pro")} ${yellow('"implement auth"')}
|
|
63736
63950
|
${green("claudish")} --model ${magenta("oai@gpt-5.3")} ${yellow('"add tests for login"')}
|
|
63737
63951
|
${green("claudish")} --model ${magenta("openrouter@deepseek/deepseek-r1")} ${yellow('"unknown vendor"')}
|
|
63738
63952
|
|
|
63739
|
-
${
|
|
63953
|
+
${dim2("# Native auto-detection (provider inferred from model name)")}
|
|
63740
63954
|
${green("claudish")} --model ${yellow("gpt-4o")} ${yellow('"routes to OpenAI"')}
|
|
63741
63955
|
${green("claudish")} --model ${yellow("gemini-2.5-pro")} ${yellow('"routes to Google"')}
|
|
63742
63956
|
|
|
63743
|
-
${
|
|
63957
|
+
${dim2("# Per-role model mapping")}
|
|
63744
63958
|
${green("claudish")} --model-opus ${magenta("oai@gpt-5.3")} --model-sonnet ${magenta("google@gemini-3-pro")}
|
|
63745
63959
|
|
|
63746
|
-
${
|
|
63747
|
-
${
|
|
63960
|
+
${dim2("# stdin for large prompts (diffs, code review)")}
|
|
63961
|
+
${dim2("git diff |")} ${green("claudish")} --stdin --model ${magenta("oai@gpt-5.3")} ${yellow('"Review these changes"')}
|
|
63748
63962
|
|
|
63749
|
-
${
|
|
63963
|
+
${dim2("# Local models with concurrency control")}
|
|
63750
63964
|
${green("claudish")} --model ${magenta("ollama@llama3.2:3")} ${yellow('"3 concurrent requests"')}
|
|
63751
63965
|
${green("claudish")} --model ${magenta("lms@qwen2.5-coder")} ${yellow('"LM Studio shortcut"')}
|
|
63752
63966
|
${green("claudish")} --model ${yellow('"http://localhost:8000/mistral"')} ${yellow('"any OpenAI-compatible URL"')}
|
|
63753
63967
|
|
|
63754
|
-
${
|
|
63968
|
+
${dim2("# Autonomous (no prompts, no sandbox) \u2014 use with caution")}
|
|
63755
63969
|
${green("claudish")} -y --dangerous ${yellow('"refactor entire codebase"')}
|
|
63756
63970
|
|
|
63757
63971
|
${h("MORE INFO")}
|
|
63758
|
-
${
|
|
63759
|
-
${
|
|
63972
|
+
${dim2("GitHub:")} ${blue("https://github.com/MadAppGang/claude-code")}
|
|
63973
|
+
${dim2("OpenRouter:")} ${blue("https://openrouter.ai")}
|
|
63760
63974
|
`);
|
|
63761
63975
|
}
|
|
63762
63976
|
function printAIAgentGuide() {
|
|
@@ -71284,7 +71498,8 @@ __export(exports_claude_runner, {
|
|
|
71284
71498
|
isProxyAuthMode: () => isProxyAuthMode,
|
|
71285
71499
|
computeMainThreadContextWindow: () => computeMainThreadContextWindow,
|
|
71286
71500
|
checkClaudeInstalled: () => checkClaudeInstalled,
|
|
71287
|
-
buildClaudishSettingsOverlay: () => buildClaudishSettingsOverlay
|
|
71501
|
+
buildClaudishSettingsOverlay: () => buildClaudishSettingsOverlay,
|
|
71502
|
+
MIN_AUTO_COMPACT_WINDOW: () => MIN_AUTO_COMPACT_WINDOW
|
|
71288
71503
|
});
|
|
71289
71504
|
import { spawn as spawn4 } from "child_process";
|
|
71290
71505
|
import {
|
|
@@ -71315,6 +71530,18 @@ function hasNativeAnthropicMapping(config3) {
|
|
|
71315
71530
|
];
|
|
71316
71531
|
return models.some((m) => m && parseModelSpec(m).provider === "native-anthropic");
|
|
71317
71532
|
}
|
|
71533
|
+
function wantsAnthropicApiBilling(config3) {
|
|
71534
|
+
if (config3.anthropicApiBilling)
|
|
71535
|
+
return true;
|
|
71536
|
+
const raw2 = process.env[ENV.CLAUDISH_ANTHROPIC_API_BILLING];
|
|
71537
|
+
if (raw2 !== undefined && raw2 !== "" && raw2 !== "0" && raw2.toLowerCase() !== "false")
|
|
71538
|
+
return true;
|
|
71539
|
+
try {
|
|
71540
|
+
return loadConfig().anthropicApiBilling === true;
|
|
71541
|
+
} catch {
|
|
71542
|
+
return false;
|
|
71543
|
+
}
|
|
71544
|
+
}
|
|
71318
71545
|
function isProxyAuthMode(config3) {
|
|
71319
71546
|
return !config3.monitor && !hasNativeAnthropicMapping(config3);
|
|
71320
71547
|
}
|
|
@@ -71578,6 +71805,7 @@ async function runClaudeWithProxy(config3, proxyUrl, onCleanup) {
|
|
|
71578
71805
|
[ENV.CLAUDISH_ACTIVE_MODEL_NAME]: modelDisplayName,
|
|
71579
71806
|
CLAUDISH_IS_LOCAL: isLocalModel2 ? "true" : "false"
|
|
71580
71807
|
};
|
|
71808
|
+
let hidAnthropicApiKey = false;
|
|
71581
71809
|
delete env.CLAUDECODE;
|
|
71582
71810
|
if (config3.monitor) {
|
|
71583
71811
|
delete env.ANTHROPIC_API_KEY;
|
|
@@ -71591,16 +71819,23 @@ async function runClaudeWithProxy(config3, proxyUrl, onCleanup) {
|
|
|
71591
71819
|
env[ENV.ANTHROPIC_MODEL] = modelId;
|
|
71592
71820
|
env[ENV.ANTHROPIC_SMALL_FAST_MODEL] = modelId;
|
|
71593
71821
|
}
|
|
71594
|
-
if (hasNativeAnthropicMapping(config3)) {
|
|
71595
|
-
|
|
71596
|
-
|
|
71822
|
+
if (hasNativeAnthropicMapping(config3)) {
|
|
71823
|
+
if (process.env.ANTHROPIC_API_KEY && !wantsAnthropicApiBilling(config3)) {
|
|
71824
|
+
delete env.ANTHROPIC_API_KEY;
|
|
71825
|
+
hidAnthropicApiKey = true;
|
|
71826
|
+
}
|
|
71827
|
+
} else {
|
|
71828
|
+
env.ANTHROPIC_API_KEY = "sk-ant-api03-placeholder-not-used-proxy-handles-auth-with-openrouter-key-xxxxxxxxxxxxxxxxxxxxx";
|
|
71829
|
+
env.ANTHROPIC_AUTH_TOKEN = "placeholder-token-not-used-proxy-handles-auth";
|
|
71597
71830
|
if (!process.env[ENV.CLAUDE_CODE_AUTO_COMPACT_WINDOW]) {
|
|
71598
71831
|
const autoCompactWindow = await computeMainThreadContextWindow(config3);
|
|
71599
|
-
if (autoCompactWindow
|
|
71832
|
+
if (autoCompactWindow >= MIN_AUTO_COMPACT_WINDOW) {
|
|
71600
71833
|
env[ENV.CLAUDE_CODE_AUTO_COMPACT_WINDOW] = String(autoCompactWindow);
|
|
71601
71834
|
if (!config3.quiet) {
|
|
71602
71835
|
console.error(`[claudish] Auto-compact window: ${autoCompactWindow.toLocaleString()} tokens ` + "(Claude Code compacts before the backend's real limit)");
|
|
71603
71836
|
}
|
|
71837
|
+
} else if (autoCompactWindow > 0 && !config3.quiet) {
|
|
71838
|
+
console.error(`[claudish] Model's real context window (${autoCompactWindow.toLocaleString()}) is below ` + `Claude Code's ${MIN_AUTO_COMPACT_WINDOW.toLocaleString()}-token auto-compact floor \u2014 ` + "leaving CLAUDE_CODE_AUTO_COMPACT_WINDOW unset so native auto-compaction stays on.");
|
|
71604
71839
|
}
|
|
71605
71840
|
}
|
|
71606
71841
|
}
|
|
@@ -71616,6 +71851,9 @@ async function runClaudeWithProxy(config3, proxyUrl, onCleanup) {
|
|
|
71616
71851
|
};
|
|
71617
71852
|
if (!config3.monitor && hasNativeAnthropicMapping(config3)) {
|
|
71618
71853
|
log2("[claudish] Native Claude model detected \u2014 using Claude Code subscription credentials");
|
|
71854
|
+
if (hidAnthropicApiKey) {
|
|
71855
|
+
log2("[claudish] ANTHROPIC_API_KEY found but hidden so it can't override that subscription \xB7 " + "use --anthropic-api-billing (or anthropicApiBilling: true) to bill the API instead");
|
|
71856
|
+
}
|
|
71619
71857
|
}
|
|
71620
71858
|
if (config3.interactive) {
|
|
71621
71859
|
log2(`
|
|
@@ -71782,11 +72020,12 @@ async function checkClaudeInstalled() {
|
|
|
71782
72020
|
const binary = await findClaudeBinary();
|
|
71783
72021
|
return binary !== null;
|
|
71784
72022
|
}
|
|
71785
|
-
var restoreTerminal = null;
|
|
72023
|
+
var restoreTerminal = null, MIN_AUTO_COMPACT_WINDOW = 200000;
|
|
71786
72024
|
var init_claude_runner = __esm(() => {
|
|
71787
72025
|
init_model_catalog();
|
|
71788
72026
|
init_config();
|
|
71789
72027
|
init_logger();
|
|
72028
|
+
init_profile_config();
|
|
71790
72029
|
init_model_discovery();
|
|
71791
72030
|
init_model_parser();
|
|
71792
72031
|
init_routing_rules();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claudish",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.21.0",
|
|
4
4
|
"description": "Run Claude Code with any model - OpenRouter, Ollama, LM Studio & local models",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -60,10 +60,10 @@
|
|
|
60
60
|
"ai"
|
|
61
61
|
],
|
|
62
62
|
"optionalDependencies": {
|
|
63
|
-
"@claudish/magmux-darwin-arm64": "7.
|
|
64
|
-
"@claudish/magmux-darwin-x64": "7.
|
|
65
|
-
"@claudish/magmux-linux-arm64": "7.
|
|
66
|
-
"@claudish/magmux-linux-x64": "7.
|
|
63
|
+
"@claudish/magmux-darwin-arm64": "7.21.0",
|
|
64
|
+
"@claudish/magmux-darwin-x64": "7.21.0",
|
|
65
|
+
"@claudish/magmux-linux-arm64": "7.21.0",
|
|
66
|
+
"@claudish/magmux-linux-x64": "7.21.0"
|
|
67
67
|
},
|
|
68
68
|
"author": "Jack Rudenko <i@madappgang.com>",
|
|
69
69
|
"license": "MIT",
|