claudish 7.28.0 → 7.29.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 +990 -488
- 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.29.0";
|
|
655
655
|
|
|
656
656
|
// src/logger.ts
|
|
657
657
|
var exports_logger = {};
|
|
@@ -37099,13 +37099,15 @@ var init_config = __esm(() => {
|
|
|
37099
37099
|
SeveritySchema = exports_external.enum(["off", "warn", "fix"]);
|
|
37100
37100
|
BehaviorConfigSchema = exports_external.object({
|
|
37101
37101
|
preset: exports_external.string().optional(),
|
|
37102
|
+
telemetry: exports_external.object({ enabled: exports_external.boolean().optional() }).optional(),
|
|
37102
37103
|
rules: exports_external.record(exports_external.string(), SeveritySchema).optional(),
|
|
37103
37104
|
hooks: exports_external.array(exports_external.string()).optional(),
|
|
37104
37105
|
observer: exports_external.object({
|
|
37105
37106
|
enabled: exports_external.boolean().optional(),
|
|
37106
|
-
mode: exports_external.enum(["off", "suggest"
|
|
37107
|
+
mode: exports_external.enum(["off", "suggest"]).optional(),
|
|
37107
37108
|
model: exports_external.string().optional(),
|
|
37108
|
-
timeoutMs: exports_external.number().int().positive().optional()
|
|
37109
|
+
timeoutMs: exports_external.number().int().positive().optional(),
|
|
37110
|
+
watchTools: exports_external.array(exports_external.string()).optional()
|
|
37109
37111
|
}).optional()
|
|
37110
37112
|
});
|
|
37111
37113
|
});
|
|
@@ -37172,17 +37174,274 @@ var init_harness = __esm(() => {
|
|
|
37172
37174
|
PLAN_MODE_HINT = /plan file|create your plan at|Plan mode is active|Plan mode still active/i;
|
|
37173
37175
|
});
|
|
37174
37176
|
|
|
37177
|
+
// src/behavior/journal.ts
|
|
37178
|
+
import { appendFile as appendFile2, mkdir, stat } from "fs/promises";
|
|
37179
|
+
import { homedir as homedir17 } from "os";
|
|
37180
|
+
import { dirname as dirname6, join as join17 } from "path";
|
|
37181
|
+
function classifyPath(observed, expected) {
|
|
37182
|
+
if (!observed)
|
|
37183
|
+
return "not_applicable";
|
|
37184
|
+
if (!expected)
|
|
37185
|
+
return "no_expectation";
|
|
37186
|
+
if (observed === expected)
|
|
37187
|
+
return "as_expected";
|
|
37188
|
+
const dirOf = (p) => p.slice(0, Math.max(0, p.lastIndexOf("/")));
|
|
37189
|
+
return dirOf(observed) === dirOf(expected) ? "same_dir_wrong_name" : "outside_expected_dir";
|
|
37190
|
+
}
|
|
37191
|
+
function journalPath() {
|
|
37192
|
+
return join17(homedir17(), ".claudish", "behavior-journal.jsonl");
|
|
37193
|
+
}
|
|
37194
|
+
async function recordDecision(entry, path = journalPath()) {
|
|
37195
|
+
try {
|
|
37196
|
+
const size = await stat(path).then((s) => s.size, () => 0);
|
|
37197
|
+
if (size > MAX_JOURNAL_BYTES) {
|
|
37198
|
+
if (!capWarned) {
|
|
37199
|
+
capWarned = true;
|
|
37200
|
+
log(`[behavior:journal] ${path} exceeded ${Math.round(MAX_JOURNAL_BYTES / 1e6)}MB \u2014 ` + "no longer recording. Archive or delete it to resume.");
|
|
37201
|
+
}
|
|
37202
|
+
return;
|
|
37203
|
+
}
|
|
37204
|
+
if (size === 0)
|
|
37205
|
+
await mkdir(dirname6(path), { recursive: true }).catch(() => {});
|
|
37206
|
+
await appendFile2(path, `${JSON.stringify(entry)}
|
|
37207
|
+
`);
|
|
37208
|
+
} catch (err) {
|
|
37209
|
+
log(`[behavior:journal] could not record: ${err}`);
|
|
37210
|
+
}
|
|
37211
|
+
}
|
|
37212
|
+
var MAX_JOURNAL_BYTES, capWarned = false;
|
|
37213
|
+
var init_journal = __esm(() => {
|
|
37214
|
+
init_logger();
|
|
37215
|
+
MAX_JOURNAL_BYTES = 32 * 1024 * 1024;
|
|
37216
|
+
});
|
|
37217
|
+
|
|
37218
|
+
// src/behavior/observer/digest.ts
|
|
37219
|
+
var exports_digest = {};
|
|
37220
|
+
__export(exports_digest, {
|
|
37221
|
+
buildDigest: () => buildDigest
|
|
37222
|
+
});
|
|
37223
|
+
function buildDigest(params) {
|
|
37224
|
+
const digest = {
|
|
37225
|
+
model: params.model,
|
|
37226
|
+
toolNames: params.toolNames.slice(0, MAX_TOOL_NAMES),
|
|
37227
|
+
harness: params.harness,
|
|
37228
|
+
ruleVocabulary: params.ruleVocabulary
|
|
37229
|
+
};
|
|
37230
|
+
if (params.call) {
|
|
37231
|
+
const paths = [];
|
|
37232
|
+
for (const [key, value] of Object.entries(params.call.args)) {
|
|
37233
|
+
if (PATH_KEYS.has(key) && typeof value === "string")
|
|
37234
|
+
paths.push(value);
|
|
37235
|
+
}
|
|
37236
|
+
digest.proposedCall = {
|
|
37237
|
+
name: params.call.name,
|
|
37238
|
+
argKeys: Object.keys(params.call.args),
|
|
37239
|
+
paths: paths.length > 0 ? paths : undefined
|
|
37240
|
+
};
|
|
37241
|
+
}
|
|
37242
|
+
return digest;
|
|
37243
|
+
}
|
|
37244
|
+
var MAX_TOOL_NAMES = 40, PATH_KEYS;
|
|
37245
|
+
var init_digest = __esm(() => {
|
|
37246
|
+
PATH_KEYS = new Set(["file_path", "path", "notebook_path", "filePath"]);
|
|
37247
|
+
});
|
|
37248
|
+
|
|
37249
|
+
// src/providers/ollama-discovery.ts
|
|
37250
|
+
function ollamaBaseUrl() {
|
|
37251
|
+
return process.env.OLLAMA_HOST || process.env.OLLAMA_BASE_URL || "http://localhost:11434";
|
|
37252
|
+
}
|
|
37253
|
+
async function fetchOllamaModels(options = {}) {
|
|
37254
|
+
const { enrichCapabilities = true } = options;
|
|
37255
|
+
const host = ollamaBaseUrl();
|
|
37256
|
+
try {
|
|
37257
|
+
const response = await fetch(`${host}/api/tags`, {
|
|
37258
|
+
signal: AbortSignal.timeout(3000)
|
|
37259
|
+
});
|
|
37260
|
+
if (!response.ok)
|
|
37261
|
+
return [];
|
|
37262
|
+
const data = await response.json();
|
|
37263
|
+
const models = data.models || [];
|
|
37264
|
+
const enriched = await Promise.all(models.map(async (m) => {
|
|
37265
|
+
let capabilities = [];
|
|
37266
|
+
if (enrichCapabilities) {
|
|
37267
|
+
try {
|
|
37268
|
+
const showResponse = await fetch(`${host}/api/show`, {
|
|
37269
|
+
method: "POST",
|
|
37270
|
+
headers: { "Content-Type": "application/json" },
|
|
37271
|
+
body: JSON.stringify({ name: m.name }),
|
|
37272
|
+
signal: AbortSignal.timeout(2000)
|
|
37273
|
+
});
|
|
37274
|
+
if (showResponse.ok) {
|
|
37275
|
+
const showData = await showResponse.json();
|
|
37276
|
+
capabilities = showData.capabilities || [];
|
|
37277
|
+
}
|
|
37278
|
+
} catch {}
|
|
37279
|
+
}
|
|
37280
|
+
const nameLower = String(m.name).toLowerCase();
|
|
37281
|
+
const supportsTools = capabilities.includes("tools");
|
|
37282
|
+
const isEmbeddingModel = capabilities.includes("embedding") || nameLower.includes("embed");
|
|
37283
|
+
const sizeInfo = m.details?.parameter_size || "unknown size";
|
|
37284
|
+
const toolsIndicator = supportsTools ? "\u2713 tools" : "\u2717 no tools";
|
|
37285
|
+
return {
|
|
37286
|
+
id: `ollama/${m.name}`,
|
|
37287
|
+
name: m.name,
|
|
37288
|
+
description: `Local Ollama model (${sizeInfo}, ${toolsIndicator})`,
|
|
37289
|
+
provider: "ollama",
|
|
37290
|
+
pricing: { prompt: "0", completion: "0" },
|
|
37291
|
+
isLocal: true,
|
|
37292
|
+
supportsTools,
|
|
37293
|
+
isEmbeddingModel,
|
|
37294
|
+
capabilities,
|
|
37295
|
+
details: m.details,
|
|
37296
|
+
size: m.size
|
|
37297
|
+
};
|
|
37298
|
+
}));
|
|
37299
|
+
return enriched.filter((m) => !m.isEmbeddingModel);
|
|
37300
|
+
} catch {
|
|
37301
|
+
return [];
|
|
37302
|
+
}
|
|
37303
|
+
}
|
|
37304
|
+
|
|
37305
|
+
// src/behavior/observer/client.ts
|
|
37306
|
+
var exports_client = {};
|
|
37307
|
+
__export(exports_client, {
|
|
37308
|
+
resetObserverModelCache: () => resetObserverModelCache,
|
|
37309
|
+
observe: () => observe
|
|
37310
|
+
});
|
|
37311
|
+
function isGenuinelyLocal(model) {
|
|
37312
|
+
if (/[-:]cloud$/i.test(model.name))
|
|
37313
|
+
return false;
|
|
37314
|
+
return (model.size ?? 0) >= MIN_LOCAL_MODEL_BYTES;
|
|
37315
|
+
}
|
|
37316
|
+
async function resolveObserverModel(config2) {
|
|
37317
|
+
if (config2.observer?.model)
|
|
37318
|
+
return config2.observer.model;
|
|
37319
|
+
if (cachedModel !== undefined)
|
|
37320
|
+
return cachedModel;
|
|
37321
|
+
try {
|
|
37322
|
+
const models = await fetchOllamaModels({ enrichCapabilities: false });
|
|
37323
|
+
const usable = models.filter((m) => !m.isEmbeddingModel && isGenuinelyLocal(m));
|
|
37324
|
+
if (usable.length === 0) {
|
|
37325
|
+
log("[behavior:observer] No local Ollama models found \u2014 observer disabled for this run");
|
|
37326
|
+
cachedModel = null;
|
|
37327
|
+
return null;
|
|
37328
|
+
}
|
|
37329
|
+
usable.sort((a, b) => (a.size ?? Number.MAX_SAFE_INTEGER) - (b.size ?? Number.MAX_SAFE_INTEGER));
|
|
37330
|
+
cachedModel = usable[0].name;
|
|
37331
|
+
log(`[behavior:observer] Using discovered local model: ${cachedModel}`);
|
|
37332
|
+
return cachedModel;
|
|
37333
|
+
} catch (err) {
|
|
37334
|
+
log(`[behavior:observer] Model discovery failed, observer disabled: ${err}`);
|
|
37335
|
+
cachedModel = null;
|
|
37336
|
+
return null;
|
|
37337
|
+
}
|
|
37338
|
+
}
|
|
37339
|
+
function resetObserverModelCache() {
|
|
37340
|
+
cachedModel = undefined;
|
|
37341
|
+
}
|
|
37342
|
+
async function observe(digest, config2) {
|
|
37343
|
+
const mode = config2.observer?.mode ?? "suggest";
|
|
37344
|
+
if (config2.observer?.enabled !== true || mode === "off")
|
|
37345
|
+
return null;
|
|
37346
|
+
const model = await resolveObserverModel(config2);
|
|
37347
|
+
if (!model)
|
|
37348
|
+
return null;
|
|
37349
|
+
const timeoutMs = config2.observer?.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
|
|
37350
|
+
try {
|
|
37351
|
+
const response = await fetch(`${ollamaBaseUrl()}/api/chat`, {
|
|
37352
|
+
method: "POST",
|
|
37353
|
+
headers: { "Content-Type": "application/json" },
|
|
37354
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
37355
|
+
body: JSON.stringify({
|
|
37356
|
+
model,
|
|
37357
|
+
stream: false,
|
|
37358
|
+
format: "json",
|
|
37359
|
+
options: { temperature: 0 },
|
|
37360
|
+
messages: [
|
|
37361
|
+
{ role: "system", content: SYSTEM_PROMPT },
|
|
37362
|
+
{ role: "user", content: JSON.stringify(digest) }
|
|
37363
|
+
]
|
|
37364
|
+
})
|
|
37365
|
+
});
|
|
37366
|
+
if (!response.ok) {
|
|
37367
|
+
log(`[behavior:observer] HTTP ${response.status} \u2014 skipping`);
|
|
37368
|
+
return null;
|
|
37369
|
+
}
|
|
37370
|
+
const body = await response.json();
|
|
37371
|
+
const content = body?.message?.content;
|
|
37372
|
+
if (typeof content !== "string")
|
|
37373
|
+
return null;
|
|
37374
|
+
const parsed = JSON.parse(content);
|
|
37375
|
+
const ruleId = typeof parsed?.ruleId === "string" ? parsed.ruleId : null;
|
|
37376
|
+
if (ruleId && !digest.ruleVocabulary.includes(ruleId)) {
|
|
37377
|
+
log(`[behavior:observer] Discarding unknown ruleId "${ruleId}"`);
|
|
37378
|
+
return null;
|
|
37379
|
+
}
|
|
37380
|
+
return {
|
|
37381
|
+
ruleId,
|
|
37382
|
+
confidence: typeof parsed?.confidence === "number" ? parsed.confidence : 0,
|
|
37383
|
+
note: typeof parsed?.note === "string" ? parsed.note : undefined
|
|
37384
|
+
};
|
|
37385
|
+
} catch (err) {
|
|
37386
|
+
log(`[behavior:observer] Skipped: ${err instanceof Error ? err.message : err}`);
|
|
37387
|
+
return null;
|
|
37388
|
+
}
|
|
37389
|
+
}
|
|
37390
|
+
var DEFAULT_TIMEOUT_MS2 = 1500, SYSTEM_PROMPT = `You audit an AI coding agent for violations of Claude Code's conventions.
|
|
37391
|
+
You receive a JSON digest: the tools available, detected harness state, and the tool call the agent proposes.
|
|
37392
|
+
Decide whether the proposed call violates one of the rules listed in ruleVocabulary.
|
|
37393
|
+
|
|
37394
|
+
Reply with ONLY a JSON object, no prose:
|
|
37395
|
+
{"ruleId": "<id from ruleVocabulary, or null>", "confidence": <0-1>, "note": "<short reason>"}
|
|
37396
|
+
|
|
37397
|
+
Return ruleId null unless you are confident. A false positive is worse than a miss.`, MIN_LOCAL_MODEL_BYTES, cachedModel;
|
|
37398
|
+
var init_client = __esm(() => {
|
|
37399
|
+
init_logger();
|
|
37400
|
+
MIN_LOCAL_MODEL_BYTES = 50 * 1024 * 1024;
|
|
37401
|
+
});
|
|
37402
|
+
|
|
37403
|
+
// src/behavior/observer/live-log.ts
|
|
37404
|
+
var exports_live_log = {};
|
|
37405
|
+
__export(exports_live_log, {
|
|
37406
|
+
recordLiveDivergence: () => recordLiveDivergence
|
|
37407
|
+
});
|
|
37408
|
+
import { appendFile as appendFile3 } from "fs/promises";
|
|
37409
|
+
import { homedir as homedir18 } from "os";
|
|
37410
|
+
import { join as join18 } from "path";
|
|
37411
|
+
function defaultPath() {
|
|
37412
|
+
return join18(homedir18(), ".claudish", "behavior-divergences.jsonl");
|
|
37413
|
+
}
|
|
37414
|
+
async function recordLiveDivergence(entry, path = defaultPath()) {
|
|
37415
|
+
try {
|
|
37416
|
+
await appendFile3(path, `${JSON.stringify(entry)}
|
|
37417
|
+
`);
|
|
37418
|
+
} catch (err) {
|
|
37419
|
+
log(`[behavior:observer] could not append divergence: ${err}`);
|
|
37420
|
+
}
|
|
37421
|
+
}
|
|
37422
|
+
var init_live_log = __esm(() => {
|
|
37423
|
+
init_logger();
|
|
37424
|
+
});
|
|
37425
|
+
|
|
37175
37426
|
// src/behavior/engine.ts
|
|
37176
37427
|
class BehaviorSession {
|
|
37177
37428
|
active;
|
|
37178
37429
|
modelId;
|
|
37179
37430
|
providerName;
|
|
37431
|
+
config;
|
|
37180
37432
|
facts = { planModeActive: false };
|
|
37181
37433
|
bufferedTools = new Set;
|
|
37182
|
-
constructor(active, modelId, providerName) {
|
|
37434
|
+
constructor(active, modelId, providerName, config2 = {}) {
|
|
37183
37435
|
this.active = active;
|
|
37184
37436
|
this.modelId = modelId;
|
|
37185
37437
|
this.providerName = providerName;
|
|
37438
|
+
this.config = config2;
|
|
37439
|
+
}
|
|
37440
|
+
get observerOn() {
|
|
37441
|
+
return this.config.observer?.enabled === true && (this.config.observer.mode ?? "suggest") !== "off";
|
|
37442
|
+
}
|
|
37443
|
+
observerWatchList() {
|
|
37444
|
+
return this.config.observer?.watchTools ?? ["Write", "Edit", "NotebookEdit", "ExitPlanMode"];
|
|
37186
37445
|
}
|
|
37187
37446
|
armBuffering() {
|
|
37188
37447
|
const armed = new Set;
|
|
@@ -37194,6 +37453,10 @@ class BehaviorSession {
|
|
|
37194
37453
|
for (const t of rule.interceptsTools ?? [])
|
|
37195
37454
|
armed.add(t);
|
|
37196
37455
|
}
|
|
37456
|
+
if (this.observerOn) {
|
|
37457
|
+
for (const t of this.observerWatchList())
|
|
37458
|
+
armed.add(t);
|
|
37459
|
+
}
|
|
37197
37460
|
this.bufferedTools = armed;
|
|
37198
37461
|
}
|
|
37199
37462
|
get harness() {
|
|
@@ -37275,13 +37538,80 @@ class BehaviorSession {
|
|
|
37275
37538
|
log(`[behavior] ${rule.id} (warn-only, not applied): ${action.reason}`);
|
|
37276
37539
|
continue;
|
|
37277
37540
|
}
|
|
37541
|
+
this.journal("tool_call", "repaired", {
|
|
37542
|
+
ruleId: rule.id,
|
|
37543
|
+
toolName,
|
|
37544
|
+
argKeys: Object.keys(args),
|
|
37545
|
+
observedPath: typeof args.file_path === "string" ? args.file_path : undefined,
|
|
37546
|
+
expectedPath: this.facts.planFilePath,
|
|
37547
|
+
note: action.reason
|
|
37548
|
+
});
|
|
37278
37549
|
args = action.args;
|
|
37279
37550
|
changed = true;
|
|
37280
37551
|
log(`[behavior] ${rule.id} repaired ${toolName}: ${action.reason}`);
|
|
37281
37552
|
}
|
|
37282
37553
|
}
|
|
37554
|
+
if (!changed) {
|
|
37555
|
+
this.journal("tool_call", "ignored", {
|
|
37556
|
+
toolName,
|
|
37557
|
+
argKeys: Object.keys(args),
|
|
37558
|
+
observedPath: typeof args.file_path === "string" ? args.file_path : undefined,
|
|
37559
|
+
expectedPath: this.facts.planFilePath
|
|
37560
|
+
});
|
|
37561
|
+
}
|
|
37562
|
+
if (this.observerOn && !changed) {
|
|
37563
|
+
this.consultObserver(toolName, args);
|
|
37564
|
+
}
|
|
37283
37565
|
return changed ? JSON.stringify(args) : null;
|
|
37284
37566
|
}
|
|
37567
|
+
journal(surface, decision, detail) {
|
|
37568
|
+
recordDecision({
|
|
37569
|
+
ts: new Date().toISOString(),
|
|
37570
|
+
model: this.modelId,
|
|
37571
|
+
provider: this.providerName,
|
|
37572
|
+
surface,
|
|
37573
|
+
decision,
|
|
37574
|
+
ruleId: detail.ruleId,
|
|
37575
|
+
toolName: detail.toolName,
|
|
37576
|
+
argKeys: detail.argKeys,
|
|
37577
|
+
pathRelation: classifyPath(detail.observedPath, detail.expectedPath),
|
|
37578
|
+
local: {
|
|
37579
|
+
observedPath: detail.observedPath,
|
|
37580
|
+
expectedPath: detail.expectedPath,
|
|
37581
|
+
note: detail.note
|
|
37582
|
+
}
|
|
37583
|
+
});
|
|
37584
|
+
}
|
|
37585
|
+
async consultObserver(toolName, args) {
|
|
37586
|
+
try {
|
|
37587
|
+
const { buildDigest: buildDigest2 } = await Promise.resolve().then(() => (init_digest(), exports_digest));
|
|
37588
|
+
const { observe: observe2 } = await Promise.resolve().then(() => (init_client(), exports_client));
|
|
37589
|
+
const { recordLiveDivergence: recordLiveDivergence2 } = await Promise.resolve().then(() => (init_live_log(), exports_live_log));
|
|
37590
|
+
const digest = buildDigest2({
|
|
37591
|
+
model: this.modelId,
|
|
37592
|
+
toolNames: [...this.bufferedTools],
|
|
37593
|
+
harness: this.facts,
|
|
37594
|
+
ruleVocabulary: this.active.map((a) => a.rule.id),
|
|
37595
|
+
call: { name: toolName, args }
|
|
37596
|
+
});
|
|
37597
|
+
const verdict = await observe2(digest, this.config);
|
|
37598
|
+
if (!verdict?.ruleId)
|
|
37599
|
+
return;
|
|
37600
|
+
log(`[behavior:observer] flagged ${toolName} as ${verdict.ruleId} (confidence ${verdict.confidence})${verdict.note ? `: ${verdict.note}` : ""}`);
|
|
37601
|
+
await recordLiveDivergence2({
|
|
37602
|
+
source: "observer",
|
|
37603
|
+
ts: new Date().toISOString(),
|
|
37604
|
+
model: this.modelId,
|
|
37605
|
+
toolName,
|
|
37606
|
+
ruleId: verdict.ruleId,
|
|
37607
|
+
confidence: verdict.confidence,
|
|
37608
|
+
note: verdict.note,
|
|
37609
|
+
paths: digest.proposedCall?.paths
|
|
37610
|
+
});
|
|
37611
|
+
} catch (err) {
|
|
37612
|
+
log(`[behavior:observer] consult failed: ${err}`);
|
|
37613
|
+
}
|
|
37614
|
+
}
|
|
37285
37615
|
applyAction(ruleId, severity, action, ctx) {
|
|
37286
37616
|
if (action.type === "warn") {
|
|
37287
37617
|
log(`[behavior] ${ruleId} (warn): ${action.message}`);
|
|
@@ -37359,13 +37689,14 @@ class BehaviorEngine {
|
|
|
37359
37689
|
if (active.length > 0) {
|
|
37360
37690
|
log(`[behavior] ${active.length} rule(s) active for ${params.modelId}: ` + active.map((a) => `${a.rule.id}=${a.severity}`).join(", "));
|
|
37361
37691
|
}
|
|
37362
|
-
return new BehaviorSession(active, params.modelId, params.providerName);
|
|
37692
|
+
return new BehaviorSession(active, params.modelId, params.providerName, this.config);
|
|
37363
37693
|
}
|
|
37364
37694
|
}
|
|
37365
37695
|
var init_engine = __esm(() => {
|
|
37366
37696
|
init_logger();
|
|
37367
37697
|
init_config();
|
|
37368
37698
|
init_harness();
|
|
37699
|
+
init_journal();
|
|
37369
37700
|
});
|
|
37370
37701
|
|
|
37371
37702
|
// src/behavior/rules/plan-mode.ts
|
|
@@ -37497,75 +37828,118 @@ var init_hooks = __esm(() => {
|
|
|
37497
37828
|
init_logger();
|
|
37498
37829
|
});
|
|
37499
37830
|
|
|
37500
|
-
// src/behavior/observer/
|
|
37501
|
-
|
|
37502
|
-
|
|
37503
|
-
|
|
37504
|
-
|
|
37505
|
-
|
|
37506
|
-
|
|
37507
|
-
function ollamaBaseUrl() {
|
|
37508
|
-
return process.env.OLLAMA_HOST || process.env.OLLAMA_BASE_URL || "http://localhost:11434";
|
|
37831
|
+
// src/behavior/observer/corpus.ts
|
|
37832
|
+
import { appendFileSync as appendFileSync3, readFileSync as readFileSync12, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
|
|
37833
|
+
import { homedir as homedir19 } from "os";
|
|
37834
|
+
import { join as join19 } from "path";
|
|
37835
|
+
function directoryOf2(filePath) {
|
|
37836
|
+
const slash = filePath.lastIndexOf("/");
|
|
37837
|
+
return slash > 0 ? filePath.slice(0, slash) : undefined;
|
|
37509
37838
|
}
|
|
37510
|
-
|
|
37511
|
-
const
|
|
37512
|
-
|
|
37839
|
+
function writeTargetsOf(row) {
|
|
37840
|
+
const content = row?.message?.content;
|
|
37841
|
+
if (!Array.isArray(content))
|
|
37842
|
+
return [];
|
|
37843
|
+
const paths = [];
|
|
37844
|
+
for (const block of content) {
|
|
37845
|
+
if (block?.type !== "tool_use" || !WRITE_TOOLS2.has(block.name))
|
|
37846
|
+
continue;
|
|
37847
|
+
const p = block.input?.file_path;
|
|
37848
|
+
if (typeof p === "string")
|
|
37849
|
+
paths.push(p);
|
|
37850
|
+
}
|
|
37851
|
+
return paths;
|
|
37852
|
+
}
|
|
37853
|
+
function replayTranscript(file2) {
|
|
37854
|
+
let text;
|
|
37513
37855
|
try {
|
|
37514
|
-
|
|
37515
|
-
signal: AbortSignal.timeout(3000)
|
|
37516
|
-
});
|
|
37517
|
-
if (!response.ok)
|
|
37518
|
-
return [];
|
|
37519
|
-
const data = await response.json();
|
|
37520
|
-
const models = data.models || [];
|
|
37521
|
-
const enriched = await Promise.all(models.map(async (m) => {
|
|
37522
|
-
let capabilities = [];
|
|
37523
|
-
if (enrichCapabilities) {
|
|
37524
|
-
try {
|
|
37525
|
-
const showResponse = await fetch(`${host}/api/show`, {
|
|
37526
|
-
method: "POST",
|
|
37527
|
-
headers: { "Content-Type": "application/json" },
|
|
37528
|
-
body: JSON.stringify({ name: m.name }),
|
|
37529
|
-
signal: AbortSignal.timeout(2000)
|
|
37530
|
-
});
|
|
37531
|
-
if (showResponse.ok) {
|
|
37532
|
-
const showData = await showResponse.json();
|
|
37533
|
-
capabilities = showData.capabilities || [];
|
|
37534
|
-
}
|
|
37535
|
-
} catch {}
|
|
37536
|
-
}
|
|
37537
|
-
const nameLower = String(m.name).toLowerCase();
|
|
37538
|
-
const supportsTools = capabilities.includes("tools");
|
|
37539
|
-
const isEmbeddingModel = capabilities.includes("embedding") || nameLower.includes("embed");
|
|
37540
|
-
const sizeInfo = m.details?.parameter_size || "unknown size";
|
|
37541
|
-
const toolsIndicator = supportsTools ? "\u2713 tools" : "\u2717 no tools";
|
|
37542
|
-
return {
|
|
37543
|
-
id: `ollama/${m.name}`,
|
|
37544
|
-
name: m.name,
|
|
37545
|
-
description: `Local Ollama model (${sizeInfo}, ${toolsIndicator})`,
|
|
37546
|
-
provider: "ollama",
|
|
37547
|
-
pricing: { prompt: "0", completion: "0" },
|
|
37548
|
-
isLocal: true,
|
|
37549
|
-
supportsTools,
|
|
37550
|
-
isEmbeddingModel,
|
|
37551
|
-
capabilities,
|
|
37552
|
-
details: m.details,
|
|
37553
|
-
size: m.size
|
|
37554
|
-
};
|
|
37555
|
-
}));
|
|
37556
|
-
return enriched.filter((m) => !m.isEmbeddingModel);
|
|
37856
|
+
text = readFileSync12(file2, "utf8");
|
|
37557
37857
|
} catch {
|
|
37558
37858
|
return [];
|
|
37559
37859
|
}
|
|
37860
|
+
if (!text.includes("ExitPlanMode"))
|
|
37861
|
+
return [];
|
|
37862
|
+
const out = [];
|
|
37863
|
+
const planWrites = [];
|
|
37864
|
+
let lastModel;
|
|
37865
|
+
for (const line of text.split(`
|
|
37866
|
+
`)) {
|
|
37867
|
+
if (!line)
|
|
37868
|
+
continue;
|
|
37869
|
+
let row;
|
|
37870
|
+
try {
|
|
37871
|
+
row = JSON.parse(line);
|
|
37872
|
+
} catch {
|
|
37873
|
+
continue;
|
|
37874
|
+
}
|
|
37875
|
+
if (row?.message?.role === "assistant" && typeof row?.message?.model === "string") {
|
|
37876
|
+
lastModel = row.message.model;
|
|
37877
|
+
}
|
|
37878
|
+
planWrites.push(...writeTargetsOf(row));
|
|
37879
|
+
const record4 = divergenceOf(row, file2, planWrites, lastModel);
|
|
37880
|
+
if (record4)
|
|
37881
|
+
out.push(record4);
|
|
37882
|
+
}
|
|
37883
|
+
return out;
|
|
37560
37884
|
}
|
|
37561
|
-
|
|
37562
|
-
|
|
37563
|
-
|
|
37564
|
-
|
|
37565
|
-
|
|
37566
|
-
|
|
37567
|
-
|
|
37568
|
-
|
|
37885
|
+
function divergenceOf(row, file2, planWrites, lastModel) {
|
|
37886
|
+
const result = row?.toolUseResult;
|
|
37887
|
+
if (!result || typeof result !== "object")
|
|
37888
|
+
return null;
|
|
37889
|
+
if (!("plan" in result) || typeof result.filePath !== "string")
|
|
37890
|
+
return null;
|
|
37891
|
+
const assignedPath = result.filePath;
|
|
37892
|
+
const planDir = directoryOf2(assignedPath);
|
|
37893
|
+
const observedPaths = planDir ? [...new Set(planWrites.filter((p) => directoryOf2(p) === planDir && p !== assignedPath))] : [];
|
|
37894
|
+
return {
|
|
37895
|
+
transcript: file2,
|
|
37896
|
+
timestamp: row?.timestamp,
|
|
37897
|
+
model: row?.message?.model ?? lastModel,
|
|
37898
|
+
ruleId: RULE_ID,
|
|
37899
|
+
assignedPath,
|
|
37900
|
+
observedPaths,
|
|
37901
|
+
outcome: result.plan === null ? "degraded" : "ok"
|
|
37902
|
+
};
|
|
37903
|
+
}
|
|
37904
|
+
function listTranscripts(root) {
|
|
37905
|
+
const files = [];
|
|
37906
|
+
let projects;
|
|
37907
|
+
try {
|
|
37908
|
+
projects = readdirSync2(root);
|
|
37909
|
+
} catch {
|
|
37910
|
+
return files;
|
|
37911
|
+
}
|
|
37912
|
+
for (const project of projects) {
|
|
37913
|
+
const dir = join19(root, project);
|
|
37914
|
+
try {
|
|
37915
|
+
if (!statSync2(dir).isDirectory())
|
|
37916
|
+
continue;
|
|
37917
|
+
for (const f of readdirSync2(dir)) {
|
|
37918
|
+
if (f.endsWith(".jsonl"))
|
|
37919
|
+
files.push(join19(dir, f));
|
|
37920
|
+
}
|
|
37921
|
+
} catch {}
|
|
37922
|
+
}
|
|
37923
|
+
return files;
|
|
37924
|
+
}
|
|
37925
|
+
function buildCorpus(options = {}) {
|
|
37926
|
+
const root = options.projectsRoot ?? join19(homedir19(), ".claude", "projects");
|
|
37927
|
+
const files = listTranscripts(root);
|
|
37928
|
+
const records = [];
|
|
37929
|
+
for (const f of files)
|
|
37930
|
+
records.push(...replayTranscript(f));
|
|
37931
|
+
if (options.write && records.length > 0) {
|
|
37932
|
+
const outputPath = options.outputPath ?? join19(homedir19(), ".claudish", "behavior-divergences.jsonl");
|
|
37933
|
+
try {
|
|
37934
|
+
appendFileSync3(outputPath, `${records.map((r) => JSON.stringify(r)).join(`
|
|
37935
|
+
`)}
|
|
37936
|
+
`);
|
|
37937
|
+
return { scanned: files.length, records, outputPath };
|
|
37938
|
+
} catch {}
|
|
37939
|
+
}
|
|
37940
|
+
return { scanned: files.length, records };
|
|
37941
|
+
}
|
|
37942
|
+
var RULE_ID = "plan-mode/plan-file-path", WRITE_TOOLS2;
|
|
37569
37943
|
var init_corpus = __esm(() => {
|
|
37570
37944
|
WRITE_TOOLS2 = new Set(["Write", "Edit", "NotebookEdit"]);
|
|
37571
37945
|
});
|
|
@@ -37979,7 +38353,7 @@ var init_openai = __esm(() => {
|
|
|
37979
38353
|
});
|
|
37980
38354
|
|
|
37981
38355
|
// src/providers/catalog-query.ts
|
|
37982
|
-
import { statSync as
|
|
38356
|
+
import { statSync as statSync3 } from "fs";
|
|
37983
38357
|
function project(entry) {
|
|
37984
38358
|
return {
|
|
37985
38359
|
modelId: entry.modelId,
|
|
@@ -37992,7 +38366,7 @@ function project(entry) {
|
|
|
37992
38366
|
function getCachedEntries() {
|
|
37993
38367
|
let mtimeMs;
|
|
37994
38368
|
try {
|
|
37995
|
-
mtimeMs =
|
|
38369
|
+
mtimeMs = statSync3(ALL_MODELS_CACHE_PATH).mtimeMs;
|
|
37996
38370
|
} catch {
|
|
37997
38371
|
return null;
|
|
37998
38372
|
}
|
|
@@ -38168,13 +38542,13 @@ var init_vision_proxy = __esm(() => {
|
|
|
38168
38542
|
import {
|
|
38169
38543
|
existsSync as existsSync14,
|
|
38170
38544
|
mkdirSync as mkdirSync9,
|
|
38171
|
-
readFileSync as
|
|
38545
|
+
readFileSync as readFileSync13,
|
|
38172
38546
|
renameSync,
|
|
38173
38547
|
unlinkSync as unlinkSync5,
|
|
38174
38548
|
writeFileSync as writeFileSync9
|
|
38175
38549
|
} from "fs";
|
|
38176
|
-
import { homedir as
|
|
38177
|
-
import { join as
|
|
38550
|
+
import { homedir as homedir20 } from "os";
|
|
38551
|
+
import { join as join20 } from "path";
|
|
38178
38552
|
function ensureDir() {
|
|
38179
38553
|
if (!existsSync14(CLAUDISH_DIR)) {
|
|
38180
38554
|
mkdirSync9(CLAUDISH_DIR, { recursive: true });
|
|
@@ -38184,7 +38558,7 @@ function readFromDisk() {
|
|
|
38184
38558
|
try {
|
|
38185
38559
|
if (!existsSync14(BUFFER_FILE))
|
|
38186
38560
|
return [];
|
|
38187
|
-
const raw2 =
|
|
38561
|
+
const raw2 = readFileSync13(BUFFER_FILE, "utf-8");
|
|
38188
38562
|
const parsed = JSON.parse(raw2);
|
|
38189
38563
|
if (!Array.isArray(parsed.events))
|
|
38190
38564
|
return [];
|
|
@@ -38209,7 +38583,7 @@ function writeToDisk(events) {
|
|
|
38209
38583
|
ensureDir();
|
|
38210
38584
|
const trimmed = enforceSizeCap([...events]);
|
|
38211
38585
|
const payload = { version: 1, events: trimmed };
|
|
38212
|
-
const tmpFile =
|
|
38586
|
+
const tmpFile = join20(CLAUDISH_DIR, `stats-buffer.tmp.${process.pid}.json`);
|
|
38213
38587
|
writeFileSync9(tmpFile, JSON.stringify(payload, null, 2), "utf-8");
|
|
38214
38588
|
renameSync(tmpFile, BUFFER_FILE);
|
|
38215
38589
|
memoryCache = trimmed;
|
|
@@ -38282,8 +38656,8 @@ function syncFlushOnExit() {
|
|
|
38282
38656
|
var BUFFER_MAX_BYTES, CLAUDISH_DIR, BUFFER_FILE, memoryCache = null, eventsSinceLastFlush = 0, flushScheduled = false;
|
|
38283
38657
|
var init_stats_buffer = __esm(() => {
|
|
38284
38658
|
BUFFER_MAX_BYTES = 64 * 1024;
|
|
38285
|
-
CLAUDISH_DIR =
|
|
38286
|
-
BUFFER_FILE =
|
|
38659
|
+
CLAUDISH_DIR = join20(homedir20(), ".claudish");
|
|
38660
|
+
BUFFER_FILE = join20(CLAUDISH_DIR, "stats-buffer.json");
|
|
38287
38661
|
process.on("exit", syncFlushOnExit);
|
|
38288
38662
|
process.on("SIGTERM", () => {
|
|
38289
38663
|
try {
|
|
@@ -40564,8 +40938,8 @@ var init_openai_responses_sse = __esm(() => {
|
|
|
40564
40938
|
|
|
40565
40939
|
// src/handlers/shared/token-tracker.ts
|
|
40566
40940
|
import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "fs";
|
|
40567
|
-
import { homedir as
|
|
40568
|
-
import { dirname as
|
|
40941
|
+
import { homedir as homedir21 } from "os";
|
|
40942
|
+
import { dirname as dirname7, join as join21 } from "path";
|
|
40569
40943
|
|
|
40570
40944
|
class TokenTracker {
|
|
40571
40945
|
port;
|
|
@@ -40709,8 +41083,8 @@ class TokenTracker {
|
|
|
40709
41083
|
data.quota_remaining = this.quotaRemaining;
|
|
40710
41084
|
}
|
|
40711
41085
|
const override = process.env.CLAUDISH_TOKEN_FILE;
|
|
40712
|
-
const outPath = override ||
|
|
40713
|
-
mkdirSync10(
|
|
41086
|
+
const outPath = override || join21(homedir21(), ".claudish", `tokens-${this.port}.json`);
|
|
41087
|
+
mkdirSync10(dirname7(outPath), { recursive: true });
|
|
40714
41088
|
writeFileSync10(outPath, JSON.stringify(data), "utf-8");
|
|
40715
41089
|
} catch (e) {
|
|
40716
41090
|
log(`[TokenTracker] Error writing token file: ${e}`);
|
|
@@ -41556,7 +41930,7 @@ var init_fallback_handler = __esm(() => {
|
|
|
41556
41930
|
});
|
|
41557
41931
|
|
|
41558
41932
|
// src/handlers/native-handler-advisor.ts
|
|
41559
|
-
import { appendFileSync as
|
|
41933
|
+
import { appendFileSync as appendFileSync4 } from "fs";
|
|
41560
41934
|
function loadAdvisorSwapConfig(cliModels, cliCollector) {
|
|
41561
41935
|
return {
|
|
41562
41936
|
enabled: process.env.CLAUDISH_SWAP_ADVISOR === "1" || (cliModels?.length ?? 0) > 0,
|
|
@@ -41611,7 +41985,7 @@ function logAdvisorEvent(cfg, event) {
|
|
|
41611
41985
|
const line = `${JSON.stringify({ ts: new Date().toISOString(), ...event })}
|
|
41612
41986
|
`;
|
|
41613
41987
|
try {
|
|
41614
|
-
|
|
41988
|
+
appendFileSync4(cfg.logPath, line);
|
|
41615
41989
|
} catch {}
|
|
41616
41990
|
}
|
|
41617
41991
|
function recordAdvisorEventsFromChunk(cfg, chunkText) {
|
|
@@ -43214,11 +43588,11 @@ var init_ollama_api_format = __esm(() => {
|
|
|
43214
43588
|
});
|
|
43215
43589
|
|
|
43216
43590
|
// src/providers/api-key-provenance.ts
|
|
43217
|
-
import { existsSync as existsSync15, readFileSync as
|
|
43218
|
-
import { homedir as
|
|
43219
|
-
import { join as
|
|
43591
|
+
import { existsSync as existsSync15, readFileSync as readFileSync14 } from "fs";
|
|
43592
|
+
import { homedir as homedir22 } from "os";
|
|
43593
|
+
import { join as join22, resolve as resolve2 } from "path";
|
|
43220
43594
|
function activeConfigPath() {
|
|
43221
|
-
return activeGlobalConfigFile(
|
|
43595
|
+
return activeGlobalConfigFile(join22(homedir22(), ".claudish", "config.json"));
|
|
43222
43596
|
}
|
|
43223
43597
|
function configLayerLabel() {
|
|
43224
43598
|
return getConfigFileOverride() ? activeConfigPath() : "~/.claudish/config.json";
|
|
@@ -43297,7 +43671,7 @@ function readDotenvKey(envVars) {
|
|
|
43297
43671
|
const dotenvPath = resolve2(".env");
|
|
43298
43672
|
if (!existsSync15(dotenvPath))
|
|
43299
43673
|
return null;
|
|
43300
|
-
const parsed = import_dotenv.parse(
|
|
43674
|
+
const parsed = import_dotenv.parse(readFileSync14(dotenvPath, "utf-8"));
|
|
43301
43675
|
for (const v of envVars) {
|
|
43302
43676
|
if (parsed[v])
|
|
43303
43677
|
return parsed[v];
|
|
@@ -43312,7 +43686,7 @@ function readConfigKey(envVar) {
|
|
|
43312
43686
|
const configPath = activeConfigPath();
|
|
43313
43687
|
if (!existsSync15(configPath))
|
|
43314
43688
|
return null;
|
|
43315
|
-
const cfg = JSON.parse(
|
|
43689
|
+
const cfg = JSON.parse(readFileSync14(configPath, "utf-8"));
|
|
43316
43690
|
return cfg.apiKeys?.[envVar] || null;
|
|
43317
43691
|
} catch {
|
|
43318
43692
|
return null;
|
|
@@ -44870,9 +45244,9 @@ var init_poe = __esm(() => {
|
|
|
44870
45244
|
});
|
|
44871
45245
|
|
|
44872
45246
|
// src/services/pricing-cache.ts
|
|
44873
|
-
import { existsSync as existsSync16, readFileSync as
|
|
44874
|
-
import { homedir as
|
|
44875
|
-
import { join as
|
|
45247
|
+
import { existsSync as existsSync16, readFileSync as readFileSync15, statSync as statSync4 } from "fs";
|
|
45248
|
+
import { homedir as homedir23 } from "os";
|
|
45249
|
+
import { join as join23 } from "path";
|
|
44876
45250
|
function prefixMatch(modelName) {
|
|
44877
45251
|
for (const [key, pricing] of pricingMap) {
|
|
44878
45252
|
if (modelName.startsWith(key))
|
|
@@ -44912,10 +45286,10 @@ function loadDiskCache() {
|
|
|
44912
45286
|
try {
|
|
44913
45287
|
if (!existsSync16(CACHE_FILE))
|
|
44914
45288
|
return false;
|
|
44915
|
-
const
|
|
44916
|
-
const age = Date.now() -
|
|
45289
|
+
const stat2 = statSync4(CACHE_FILE);
|
|
45290
|
+
const age = Date.now() - stat2.mtimeMs;
|
|
44917
45291
|
const isFresh = age < CACHE_TTL_MS2;
|
|
44918
|
-
const raw2 =
|
|
45292
|
+
const raw2 = readFileSync15(CACHE_FILE, "utf-8");
|
|
44919
45293
|
const data = JSON.parse(raw2);
|
|
44920
45294
|
for (const [key, pricing] of Object.entries(data)) {
|
|
44921
45295
|
pricingMap.set(key, pricing);
|
|
@@ -44931,8 +45305,8 @@ var init_pricing_cache = __esm(() => {
|
|
|
44931
45305
|
init_logger();
|
|
44932
45306
|
init_catalog_query();
|
|
44933
45307
|
pricingMap = new Map;
|
|
44934
|
-
CACHE_DIR =
|
|
44935
|
-
CACHE_FILE =
|
|
45308
|
+
CACHE_DIR = join23(homedir23(), ".claudish");
|
|
45309
|
+
CACHE_FILE = join23(CACHE_DIR, "pricing-cache.json");
|
|
44936
45310
|
CACHE_TTL_MS2 = 24 * 60 * 60 * 1000;
|
|
44937
45311
|
});
|
|
44938
45312
|
|
|
@@ -45389,20 +45763,20 @@ var init_proxy_server = __esm(() => {
|
|
|
45389
45763
|
});
|
|
45390
45764
|
|
|
45391
45765
|
// src/team-stats.ts
|
|
45392
|
-
import { existsSync as existsSync17, readFileSync as
|
|
45393
|
-
import { join as
|
|
45766
|
+
import { existsSync as existsSync17, readFileSync as readFileSync16, writeFileSync as writeFileSync11 } from "fs";
|
|
45767
|
+
import { join as join24 } from "path";
|
|
45394
45768
|
function statsDir(sessionPath) {
|
|
45395
|
-
return
|
|
45769
|
+
return join24(sessionPath, "stats");
|
|
45396
45770
|
}
|
|
45397
45771
|
function tokenFileFor(sessionPath, anonId) {
|
|
45398
|
-
return
|
|
45772
|
+
return join24(statsDir(sessionPath), `${anonId}.json`);
|
|
45399
45773
|
}
|
|
45400
45774
|
function readTokenStats(sessionPath, anonId) {
|
|
45401
45775
|
const path = tokenFileFor(sessionPath, anonId);
|
|
45402
45776
|
if (!existsSync17(path))
|
|
45403
45777
|
return null;
|
|
45404
45778
|
try {
|
|
45405
|
-
return JSON.parse(
|
|
45779
|
+
return JSON.parse(readFileSync16(path, "utf-8"));
|
|
45406
45780
|
} catch {
|
|
45407
45781
|
return null;
|
|
45408
45782
|
}
|
|
@@ -45550,7 +45924,7 @@ ${segs.join(" \xB7 ")}`;
|
|
|
45550
45924
|
}
|
|
45551
45925
|
function writeStatusFile(sessionPath, manifest, status, opts) {
|
|
45552
45926
|
try {
|
|
45553
|
-
writeFileSync11(
|
|
45927
|
+
writeFileSync11(join24(sessionPath, "status.txt"), `${renderTeamStats(sessionPath, manifest, status, opts)}
|
|
45554
45928
|
`, "utf-8");
|
|
45555
45929
|
} catch {}
|
|
45556
45930
|
}
|
|
@@ -45578,11 +45952,11 @@ import {
|
|
|
45578
45952
|
createWriteStream as createWriteStream2,
|
|
45579
45953
|
existsSync as existsSync18,
|
|
45580
45954
|
mkdirSync as mkdirSync11,
|
|
45581
|
-
readFileSync as
|
|
45582
|
-
readdirSync as
|
|
45955
|
+
readFileSync as readFileSync17,
|
|
45956
|
+
readdirSync as readdirSync3,
|
|
45583
45957
|
writeFileSync as writeFileSync12
|
|
45584
45958
|
} from "fs";
|
|
45585
|
-
import { join as
|
|
45959
|
+
import { join as join25, resolve as resolve3 } from "path";
|
|
45586
45960
|
function classifyRunOutput(opts) {
|
|
45587
45961
|
const { outputSize, stdoutTail, stderr, minOutputBytes } = opts;
|
|
45588
45962
|
const apiError = API_ERROR_RE.exec(stdoutTail);
|
|
@@ -45643,18 +46017,18 @@ function setupSession(sessionPath, models, input) {
|
|
|
45643
46017
|
if (models.length === 0) {
|
|
45644
46018
|
throw new Error("At least one model is required");
|
|
45645
46019
|
}
|
|
45646
|
-
if (existsSync18(
|
|
46020
|
+
if (existsSync18(join25(sessionPath, "manifest.json"))) {
|
|
45647
46021
|
throw new Error(`Session already exists at ${sessionPath}. Use a new directory path or delete the existing session first.`);
|
|
45648
46022
|
}
|
|
45649
46023
|
const sentinels = models.filter(isSentinelModel);
|
|
45650
46024
|
if (sentinels.length > 0) {
|
|
45651
46025
|
throw new Error(`Invalid model(s) for team run: ${sentinels.join(", ")}. These are Claude Code agent selectors, not external model IDs. Use real external models (e.g., "gemini-2.0-flash", "gpt-4o", "or@deepseek/deepseek-r1"). For Claude models, use a Task agent instead of the team tool.`);
|
|
45652
46026
|
}
|
|
45653
|
-
mkdirSync11(
|
|
45654
|
-
mkdirSync11(
|
|
46027
|
+
mkdirSync11(join25(sessionPath, "work"), { recursive: true });
|
|
46028
|
+
mkdirSync11(join25(sessionPath, "errors"), { recursive: true });
|
|
45655
46029
|
if (input !== undefined) {
|
|
45656
|
-
writeFileSync12(
|
|
45657
|
-
} else if (!existsSync18(
|
|
46030
|
+
writeFileSync12(join25(sessionPath, "input.md"), input, "utf-8");
|
|
46031
|
+
} else if (!existsSync18(join25(sessionPath, "input.md"))) {
|
|
45658
46032
|
throw new Error(`No input.md found at ${sessionPath} and no input provided`);
|
|
45659
46033
|
}
|
|
45660
46034
|
const ids = models.map((_, i) => String(i + 1).padStart(2, "0"));
|
|
@@ -45671,9 +46045,9 @@ function setupSession(sessionPath, models, input) {
|
|
|
45671
46045
|
model: models[i],
|
|
45672
46046
|
assignedAt: now
|
|
45673
46047
|
};
|
|
45674
|
-
mkdirSync11(
|
|
46048
|
+
mkdirSync11(join25(sessionPath, "work", anonId), { recursive: true });
|
|
45675
46049
|
}
|
|
45676
|
-
writeFileSync12(
|
|
46050
|
+
writeFileSync12(join25(sessionPath, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
|
|
45677
46051
|
const status = {
|
|
45678
46052
|
startedAt: now,
|
|
45679
46053
|
models: Object.fromEntries(Object.keys(manifest.models).map((id) => [
|
|
@@ -45687,17 +46061,17 @@ function setupSession(sessionPath, models, input) {
|
|
|
45687
46061
|
}
|
|
45688
46062
|
]))
|
|
45689
46063
|
};
|
|
45690
|
-
writeFileSync12(
|
|
46064
|
+
writeFileSync12(join25(sessionPath, "status.json"), JSON.stringify(status, null, 2), "utf-8");
|
|
45691
46065
|
return manifest;
|
|
45692
46066
|
}
|
|
45693
46067
|
async function runModels(sessionPath, opts = {}) {
|
|
45694
46068
|
const timeoutMs = (opts.timeout ?? 300) * 1000;
|
|
45695
|
-
const manifest = JSON.parse(
|
|
45696
|
-
const statusPath =
|
|
45697
|
-
const inputPath =
|
|
45698
|
-
const inputContent =
|
|
46069
|
+
const manifest = JSON.parse(readFileSync17(join25(sessionPath, "manifest.json"), "utf-8"));
|
|
46070
|
+
const statusPath = join25(sessionPath, "status.json");
|
|
46071
|
+
const inputPath = join25(sessionPath, "input.md");
|
|
46072
|
+
const inputContent = readFileSync17(inputPath, "utf-8");
|
|
45699
46073
|
await prehydrateCredentialsForSpawn(Object.values(manifest.models).map((m) => m.model));
|
|
45700
|
-
const statusCache = JSON.parse(
|
|
46074
|
+
const statusCache = JSON.parse(readFileSync17(statusPath, "utf-8"));
|
|
45701
46075
|
function updateModelStatus(id, update) {
|
|
45702
46076
|
statusCache.models[id] = { ...statusCache.models[id], ...update };
|
|
45703
46077
|
writeFileSync12(statusPath, JSON.stringify(statusCache, null, 2), "utf-8");
|
|
@@ -45716,8 +46090,8 @@ async function runModels(sessionPath, opts = {}) {
|
|
|
45716
46090
|
process.on("SIGINT", sigintHandler);
|
|
45717
46091
|
const completionPromises = [];
|
|
45718
46092
|
for (const [anonId, entry] of Object.entries(manifest.models)) {
|
|
45719
|
-
const outputPath =
|
|
45720
|
-
const errorLogPath =
|
|
46093
|
+
const outputPath = join25(sessionPath, `response-${anonId}.md`);
|
|
46094
|
+
const errorLogPath = join25(sessionPath, "errors", `${anonId}.log`);
|
|
45721
46095
|
const args = ["--model", entry.model, "-y", "--stdin", "--quiet", ...opts.claudeFlags ?? []];
|
|
45722
46096
|
updateModelStatus(anonId, {
|
|
45723
46097
|
state: "RUNNING",
|
|
@@ -45899,30 +46273,30 @@ async function runModels(sessionPath, opts = {}) {
|
|
|
45899
46273
|
return statusCache;
|
|
45900
46274
|
}
|
|
45901
46275
|
async function judgeResponses(sessionPath, opts = {}) {
|
|
45902
|
-
const responseFiles =
|
|
46276
|
+
const responseFiles = readdirSync3(sessionPath).filter((f) => f.startsWith("response-") && f.endsWith(".md")).sort();
|
|
45903
46277
|
if (responseFiles.length < 2) {
|
|
45904
46278
|
throw new Error(`Need at least 2 responses to judge, found ${responseFiles.length}`);
|
|
45905
46279
|
}
|
|
45906
46280
|
const responses = {};
|
|
45907
46281
|
for (const file2 of responseFiles) {
|
|
45908
46282
|
const id = file2.replace(/^response-/, "").replace(/\.md$/, "");
|
|
45909
|
-
responses[id] =
|
|
46283
|
+
responses[id] = readFileSync17(join25(sessionPath, file2), "utf-8");
|
|
45910
46284
|
}
|
|
45911
|
-
const input =
|
|
46285
|
+
const input = readFileSync17(join25(sessionPath, "input.md"), "utf-8");
|
|
45912
46286
|
const judgePrompt = buildJudgePrompt(input, responses);
|
|
45913
|
-
writeFileSync12(
|
|
46287
|
+
writeFileSync12(join25(sessionPath, "judge-prompt.md"), judgePrompt, "utf-8");
|
|
45914
46288
|
const judgeModels = opts.judges ?? getDefaultJudgeModels(sessionPath);
|
|
45915
|
-
const judgePath =
|
|
46289
|
+
const judgePath = join25(sessionPath, "judging");
|
|
45916
46290
|
mkdirSync11(judgePath, { recursive: true });
|
|
45917
46291
|
setupSession(judgePath, judgeModels, judgePrompt);
|
|
45918
46292
|
await runModels(judgePath, { claudeFlags: opts.claudeFlags });
|
|
45919
46293
|
const votes = parseJudgeVotes(judgePath, Object.keys(responses));
|
|
45920
46294
|
const verdict = aggregateVerdict(votes, Object.keys(responses));
|
|
45921
|
-
writeFileSync12(
|
|
46295
|
+
writeFileSync12(join25(sessionPath, "verdict.md"), formatVerdict(verdict, sessionPath), "utf-8");
|
|
45922
46296
|
return verdict;
|
|
45923
46297
|
}
|
|
45924
46298
|
function getStatus(sessionPath) {
|
|
45925
|
-
return JSON.parse(
|
|
46299
|
+
return JSON.parse(readFileSync17(join25(sessionPath, "status.json"), "utf-8"));
|
|
45926
46300
|
}
|
|
45927
46301
|
function fisherYatesShuffle(arr) {
|
|
45928
46302
|
for (let i = arr.length - 1;i > 0; i--) {
|
|
@@ -45932,7 +46306,7 @@ function fisherYatesShuffle(arr) {
|
|
|
45932
46306
|
return arr;
|
|
45933
46307
|
}
|
|
45934
46308
|
function getDefaultJudgeModels(sessionPath) {
|
|
45935
|
-
const manifest = JSON.parse(
|
|
46309
|
+
const manifest = JSON.parse(readFileSync17(join25(sessionPath, "manifest.json"), "utf-8"));
|
|
45936
46310
|
return Object.values(manifest.models).map((e) => e.model);
|
|
45937
46311
|
}
|
|
45938
46312
|
function buildJudgePrompt(input, responses) {
|
|
@@ -45990,12 +46364,12 @@ function buildJudgePrompt(input, responses) {
|
|
|
45990
46364
|
}
|
|
45991
46365
|
function parseJudgeVotes(judgePath, responseIds) {
|
|
45992
46366
|
const votes = [];
|
|
45993
|
-
const responseFiles =
|
|
46367
|
+
const responseFiles = readdirSync3(judgePath).filter((f) => f.startsWith("response-") && f.endsWith(".md")).sort();
|
|
45994
46368
|
for (const file2 of responseFiles) {
|
|
45995
46369
|
const judgeId = file2.replace(/^response-/, "").replace(/\.md$/, "");
|
|
45996
46370
|
let content;
|
|
45997
46371
|
try {
|
|
45998
|
-
content =
|
|
46372
|
+
content = readFileSync17(join25(judgePath, file2), "utf-8");
|
|
45999
46373
|
} catch {
|
|
46000
46374
|
continue;
|
|
46001
46375
|
}
|
|
@@ -46047,7 +46421,7 @@ function aggregateVerdict(votes, responseIds) {
|
|
|
46047
46421
|
function formatVerdict(verdict, sessionPath) {
|
|
46048
46422
|
let manifest = null;
|
|
46049
46423
|
try {
|
|
46050
|
-
manifest = JSON.parse(
|
|
46424
|
+
manifest = JSON.parse(readFileSync17(join25(sessionPath, "manifest.json"), "utf-8"));
|
|
46051
46425
|
} catch {}
|
|
46052
46426
|
let output = `# Team Verdict
|
|
46053
46427
|
|
|
@@ -46102,14 +46476,14 @@ __export(exports_mcp_server, {
|
|
|
46102
46476
|
parseAnthropicSse: () => parseAnthropicSse,
|
|
46103
46477
|
formatTeamResult: () => formatTeamResult
|
|
46104
46478
|
});
|
|
46105
|
-
import { existsSync as existsSync19, mkdirSync as mkdirSync12, readFileSync as
|
|
46106
|
-
import { homedir as
|
|
46107
|
-
import { dirname as
|
|
46479
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync12, readFileSync as readFileSync18, readdirSync as readdirSync4, writeFileSync as writeFileSync13 } from "fs";
|
|
46480
|
+
import { homedir as homedir24 } from "os";
|
|
46481
|
+
import { dirname as dirname8, join as join26 } from "path";
|
|
46108
46482
|
import { fileURLToPath } from "url";
|
|
46109
46483
|
async function loadAllModels(forceRefresh = false) {
|
|
46110
46484
|
if (!forceRefresh && existsSync19(ALL_MODELS_CACHE_PATH2)) {
|
|
46111
46485
|
try {
|
|
46112
|
-
const cacheData = JSON.parse(
|
|
46486
|
+
const cacheData = JSON.parse(readFileSync18(ALL_MODELS_CACHE_PATH2, "utf-8"));
|
|
46113
46487
|
const lastUpdated = new Date(cacheData.lastUpdated);
|
|
46114
46488
|
const ageInDays = (Date.now() - lastUpdated.getTime()) / (1000 * 60 * 60 * 24);
|
|
46115
46489
|
if (ageInDays <= CACHE_MAX_AGE_DAYS) {
|
|
@@ -46128,7 +46502,7 @@ async function loadAllModels(forceRefresh = false) {
|
|
|
46128
46502
|
return models;
|
|
46129
46503
|
} catch {
|
|
46130
46504
|
if (existsSync19(ALL_MODELS_CACHE_PATH2)) {
|
|
46131
|
-
const cacheData = JSON.parse(
|
|
46505
|
+
const cacheData = JSON.parse(readFileSync18(ALL_MODELS_CACHE_PATH2, "utf-8"));
|
|
46132
46506
|
return cacheData.models || [];
|
|
46133
46507
|
}
|
|
46134
46508
|
return [];
|
|
@@ -46695,7 +47069,7 @@ Use with: run_prompt(model="${results[0].model.id}", prompt="your prompt")`;
|
|
|
46695
47069
|
let stderrFull = stderr_snippet || "";
|
|
46696
47070
|
if (error_log_path) {
|
|
46697
47071
|
try {
|
|
46698
|
-
stderrFull =
|
|
47072
|
+
stderrFull = readFileSync18(error_log_path, "utf-8");
|
|
46699
47073
|
} catch {}
|
|
46700
47074
|
}
|
|
46701
47075
|
const sessionData = {};
|
|
@@ -46703,26 +47077,26 @@ Use with: run_prompt(model="${results[0].model.id}", prompt="your prompt")`;
|
|
|
46703
47077
|
const sp = session_path;
|
|
46704
47078
|
for (const file2 of ["status.json", "manifest.json", "input.md"]) {
|
|
46705
47079
|
try {
|
|
46706
|
-
sessionData[file2] =
|
|
47080
|
+
sessionData[file2] = readFileSync18(join26(sp, file2), "utf-8");
|
|
46707
47081
|
} catch {}
|
|
46708
47082
|
}
|
|
46709
47083
|
try {
|
|
46710
|
-
const errorDir =
|
|
47084
|
+
const errorDir = join26(sp, "errors");
|
|
46711
47085
|
if (existsSync19(errorDir)) {
|
|
46712
|
-
for (const f of
|
|
47086
|
+
for (const f of readdirSync4(errorDir)) {
|
|
46713
47087
|
if (f.endsWith(".log")) {
|
|
46714
47088
|
try {
|
|
46715
|
-
sessionData[`errors/${f}`] =
|
|
47089
|
+
sessionData[`errors/${f}`] = readFileSync18(join26(errorDir, f), "utf-8");
|
|
46716
47090
|
} catch {}
|
|
46717
47091
|
}
|
|
46718
47092
|
}
|
|
46719
47093
|
}
|
|
46720
47094
|
} catch {}
|
|
46721
47095
|
try {
|
|
46722
|
-
for (const f of
|
|
47096
|
+
for (const f of readdirSync4(sp)) {
|
|
46723
47097
|
if (f.startsWith("response-") && f.endsWith(".md")) {
|
|
46724
47098
|
try {
|
|
46725
|
-
const content =
|
|
47099
|
+
const content = readFileSync18(join26(sp, f), "utf-8");
|
|
46726
47100
|
sessionData[f] = content.slice(0, 200) + (content.length > 200 ? "... (truncated)" : "");
|
|
46727
47101
|
} catch {}
|
|
46728
47102
|
}
|
|
@@ -46731,9 +47105,9 @@ Use with: run_prompt(model="${results[0].model.id}", prompt="your prompt")`;
|
|
|
46731
47105
|
}
|
|
46732
47106
|
let version2 = "unknown";
|
|
46733
47107
|
try {
|
|
46734
|
-
const pkgPath =
|
|
47108
|
+
const pkgPath = join26(__dirname2, "../package.json");
|
|
46735
47109
|
if (existsSync19(pkgPath)) {
|
|
46736
|
-
version2 = JSON.parse(
|
|
47110
|
+
version2 = JSON.parse(readFileSync18(pkgPath, "utf-8")).version;
|
|
46737
47111
|
}
|
|
46738
47112
|
} catch {}
|
|
46739
47113
|
const report = {
|
|
@@ -47130,9 +47504,9 @@ var init_mcp_server = __esm(() => {
|
|
|
47130
47504
|
import_dotenv2 = __toESM(require_main(), 1);
|
|
47131
47505
|
import_dotenv2.config({ quiet: true });
|
|
47132
47506
|
__filename2 = fileURLToPath(import.meta.url);
|
|
47133
|
-
__dirname2 =
|
|
47134
|
-
CLAUDISH_CACHE_DIR =
|
|
47135
|
-
ALL_MODELS_CACHE_PATH2 =
|
|
47507
|
+
__dirname2 = dirname8(__filename2);
|
|
47508
|
+
CLAUDISH_CACHE_DIR = join26(homedir24(), ".claudish");
|
|
47509
|
+
ALL_MODELS_CACHE_PATH2 = join26(CLAUDISH_CACHE_DIR, "all-models.json");
|
|
47136
47510
|
NEXT_STEP = {
|
|
47137
47511
|
nonzero_exit: "read the evidence log, then retry or drop the model",
|
|
47138
47512
|
timeout: "raise `timeout`, or pick a faster model",
|
|
@@ -47157,7 +47531,7 @@ var exports_serve_command = {};
|
|
|
47157
47531
|
__export(exports_serve_command, {
|
|
47158
47532
|
serveCommand: () => serveCommand
|
|
47159
47533
|
});
|
|
47160
|
-
import { existsSync as existsSync20, readFileSync as
|
|
47534
|
+
import { existsSync as existsSync20, readFileSync as readFileSync19 } from "fs";
|
|
47161
47535
|
function parseServeArgs(args) {
|
|
47162
47536
|
const out = {};
|
|
47163
47537
|
for (let i = 0;i < args.length; i++) {
|
|
@@ -47181,7 +47555,7 @@ function loadModelMap(path) {
|
|
|
47181
47555
|
}
|
|
47182
47556
|
let raw2;
|
|
47183
47557
|
try {
|
|
47184
|
-
raw2 =
|
|
47558
|
+
raw2 = readFileSync19(path, "utf-8");
|
|
47185
47559
|
} catch (e) {
|
|
47186
47560
|
throw new Error(`failed to read --models file ${path}: ${e instanceof Error ? e.message : String(e)}`);
|
|
47187
47561
|
}
|
|
@@ -47253,6 +47627,127 @@ var init_serve_command = __esm(() => {
|
|
|
47253
47627
|
init_proxy_server();
|
|
47254
47628
|
});
|
|
47255
47629
|
|
|
47630
|
+
// src/behavior-command.ts
|
|
47631
|
+
var exports_behavior_command = {};
|
|
47632
|
+
__export(exports_behavior_command, {
|
|
47633
|
+
behaviorCommand: () => behaviorCommand
|
|
47634
|
+
});
|
|
47635
|
+
function severityColor(sev) {
|
|
47636
|
+
if (sev === "fix")
|
|
47637
|
+
return green(sev);
|
|
47638
|
+
if (sev === "warn")
|
|
47639
|
+
return yellow(sev);
|
|
47640
|
+
return dim2(sev);
|
|
47641
|
+
}
|
|
47642
|
+
function showRules(json2) {
|
|
47643
|
+
const config3 = parseBehaviorConfig(loadConfig().behavior);
|
|
47644
|
+
const rows = BUILTIN_RULES.map((rule) => ({
|
|
47645
|
+
id: rule.id,
|
|
47646
|
+
severity: resolveSeverity(rule.id, rule.defaultSeverity, config3),
|
|
47647
|
+
defaultSeverity: rule.defaultSeverity,
|
|
47648
|
+
intercepts: rule.interceptsTools ?? [],
|
|
47649
|
+
description: rule.description
|
|
47650
|
+
}));
|
|
47651
|
+
if (json2) {
|
|
47652
|
+
console.log(JSON.stringify({ rules: rows, observer: config3.observer ?? null }, null, 2));
|
|
47653
|
+
return;
|
|
47654
|
+
}
|
|
47655
|
+
console.log(bold2(`
|
|
47656
|
+
Behavior rules
|
|
47657
|
+
`));
|
|
47658
|
+
for (const r of rows) {
|
|
47659
|
+
const overridden = r.severity !== r.defaultSeverity ? dim2(` (default ${r.defaultSeverity})`) : "";
|
|
47660
|
+
console.log(` ${severityColor(r.severity).padEnd(18)} ${r.id}${overridden}`);
|
|
47661
|
+
console.log(` ${dim2(r.description)}`);
|
|
47662
|
+
if (r.intercepts.length > 0) {
|
|
47663
|
+
console.log(` ${dim2(`repairs: ${r.intercepts.join(", ")}`)}`);
|
|
47664
|
+
}
|
|
47665
|
+
console.log();
|
|
47666
|
+
}
|
|
47667
|
+
console.log(dim2(` Rules are inactive for native Claude models by design.
|
|
47668
|
+
`));
|
|
47669
|
+
const obs = config3.observer;
|
|
47670
|
+
const obsState = obs?.enabled ? obs.mode ?? "suggest" : "off";
|
|
47671
|
+
console.log(` observer: ${obsState === "off" ? dim2("off") : green(obsState)}`);
|
|
47672
|
+
if (obs?.model)
|
|
47673
|
+
console.log(` ${dim2(`observer model: ${obs.model}`)}`);
|
|
47674
|
+
console.log();
|
|
47675
|
+
}
|
|
47676
|
+
function showCorpus(write, json2) {
|
|
47677
|
+
const result = buildCorpus({ write });
|
|
47678
|
+
if (json2) {
|
|
47679
|
+
console.log(JSON.stringify(result, null, 2));
|
|
47680
|
+
return;
|
|
47681
|
+
}
|
|
47682
|
+
const degraded = result.records.filter((r) => r.outcome === "degraded");
|
|
47683
|
+
const ok = result.records.filter((r) => r.outcome === "ok");
|
|
47684
|
+
const catchable = degraded.filter((r) => r.observedPaths.length > 0);
|
|
47685
|
+
console.log(bold2(`
|
|
47686
|
+
Behavior divergence corpus
|
|
47687
|
+
`));
|
|
47688
|
+
console.log(` transcripts scanned : ${result.scanned}`);
|
|
47689
|
+
console.log(` plan-exit records : ${result.records.length}`);
|
|
47690
|
+
console.log(` ${green("plan found")} : ${ok.length}`);
|
|
47691
|
+
console.log(` ${yellow("degraded (no plan)")} : ${degraded.length}`);
|
|
47692
|
+
console.log(` of those, a rule would have fired on ${catchable.length}
|
|
47693
|
+
`);
|
|
47694
|
+
const byModel = new Map;
|
|
47695
|
+
for (const r of result.records) {
|
|
47696
|
+
const m = r.model ?? "unknown";
|
|
47697
|
+
const e = byModel.get(m) ?? { ok: 0, degraded: 0 };
|
|
47698
|
+
if (r.outcome === "degraded")
|
|
47699
|
+
e.degraded++;
|
|
47700
|
+
else
|
|
47701
|
+
e.ok++;
|
|
47702
|
+
byModel.set(m, e);
|
|
47703
|
+
}
|
|
47704
|
+
if (byModel.size > 0) {
|
|
47705
|
+
console.log(bold2(` by model (degraded / ok)
|
|
47706
|
+
`));
|
|
47707
|
+
for (const [model, v] of [...byModel.entries()].sort((a, b) => b[1].degraded - a[1].degraded || b[1].ok - a[1].ok)) {
|
|
47708
|
+
const flag = v.degraded > 0 ? yellow(String(v.degraded)) : dim2("0");
|
|
47709
|
+
console.log(` ${model.padEnd(26)} ${flag} / ${v.ok}`);
|
|
47710
|
+
}
|
|
47711
|
+
console.log();
|
|
47712
|
+
}
|
|
47713
|
+
if (result.outputPath) {
|
|
47714
|
+
console.log(dim2(` appended to ${result.outputPath}
|
|
47715
|
+
`));
|
|
47716
|
+
} else if (write) {
|
|
47717
|
+
console.log(dim2(` nothing to write (no records found)
|
|
47718
|
+
`));
|
|
47719
|
+
} else {
|
|
47720
|
+
console.log(dim2(` pass --write to append these records to the divergence log
|
|
47721
|
+
`));
|
|
47722
|
+
}
|
|
47723
|
+
}
|
|
47724
|
+
async function behaviorCommand(argv) {
|
|
47725
|
+
const json2 = argv.includes("--json");
|
|
47726
|
+
const write = argv.includes("--write");
|
|
47727
|
+
const action = argv.find((a) => !a.startsWith("-")) ?? "rules";
|
|
47728
|
+
switch (action) {
|
|
47729
|
+
case "rules":
|
|
47730
|
+
showRules(json2);
|
|
47731
|
+
return;
|
|
47732
|
+
case "corpus":
|
|
47733
|
+
showCorpus(write, json2);
|
|
47734
|
+
return;
|
|
47735
|
+
default:
|
|
47736
|
+
console.error(`Unknown action "${action}".
|
|
47737
|
+
|
|
47738
|
+
` + `Usage:
|
|
47739
|
+
` + ` claudish behavior rules [--json]
|
|
47740
|
+
` + ` claudish behavior corpus [--write] [--json]
|
|
47741
|
+
`);
|
|
47742
|
+
process.exit(1);
|
|
47743
|
+
}
|
|
47744
|
+
}
|
|
47745
|
+
var green = (s) => `\x1B[32m${s}\x1B[0m`, yellow = (s) => `\x1B[33m${s}\x1B[0m`, dim2 = (s) => `\x1B[2m${s}\x1B[0m`, bold2 = (s) => `\x1B[1m${s}\x1B[0m`;
|
|
47746
|
+
var init_behavior_command = __esm(() => {
|
|
47747
|
+
init_behavior();
|
|
47748
|
+
init_profile_config();
|
|
47749
|
+
});
|
|
47750
|
+
|
|
47256
47751
|
// src/auth/credentials/source.ts
|
|
47257
47752
|
function describeSourceSync(p, config3) {
|
|
47258
47753
|
if (p.isLocal)
|
|
@@ -48169,8 +48664,8 @@ function assembleStyles() {
|
|
|
48169
48664
|
styles.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);
|
|
48170
48665
|
Object.defineProperties(styles, {
|
|
48171
48666
|
rgbToAnsi256: {
|
|
48172
|
-
value(red,
|
|
48173
|
-
if (red ===
|
|
48667
|
+
value(red, green2, blue) {
|
|
48668
|
+
if (red === green2 && green2 === blue) {
|
|
48174
48669
|
if (red < 8) {
|
|
48175
48670
|
return 16;
|
|
48176
48671
|
}
|
|
@@ -48179,7 +48674,7 @@ function assembleStyles() {
|
|
|
48179
48674
|
}
|
|
48180
48675
|
return Math.round((red - 8) / 247 * 24) + 232;
|
|
48181
48676
|
}
|
|
48182
|
-
return 16 + 36 * Math.round(red / 255 * 5) + 6 * Math.round(
|
|
48677
|
+
return 16 + 36 * Math.round(red / 255 * 5) + 6 * Math.round(green2 / 255 * 5) + Math.round(blue / 255 * 5);
|
|
48183
48678
|
},
|
|
48184
48679
|
enumerable: false
|
|
48185
48680
|
},
|
|
@@ -48215,24 +48710,24 @@ function assembleStyles() {
|
|
|
48215
48710
|
return 90 + (code - 8);
|
|
48216
48711
|
}
|
|
48217
48712
|
let red;
|
|
48218
|
-
let
|
|
48713
|
+
let green2;
|
|
48219
48714
|
let blue;
|
|
48220
48715
|
if (code >= 232) {
|
|
48221
48716
|
red = ((code - 232) * 10 + 8) / 255;
|
|
48222
|
-
|
|
48717
|
+
green2 = red;
|
|
48223
48718
|
blue = red;
|
|
48224
48719
|
} else {
|
|
48225
48720
|
code -= 16;
|
|
48226
48721
|
const remainder = code % 36;
|
|
48227
48722
|
red = Math.floor(code / 36) / 5;
|
|
48228
|
-
|
|
48723
|
+
green2 = Math.floor(remainder / 6) / 5;
|
|
48229
48724
|
blue = remainder % 6 / 5;
|
|
48230
48725
|
}
|
|
48231
|
-
const value = Math.max(red,
|
|
48726
|
+
const value = Math.max(red, green2, blue) * 2;
|
|
48232
48727
|
if (value === 0) {
|
|
48233
48728
|
return 30;
|
|
48234
48729
|
}
|
|
48235
|
-
let result = 30 + (Math.round(blue) << 2 | Math.round(
|
|
48730
|
+
let result = 30 + (Math.round(blue) << 2 | Math.round(green2) << 1 | Math.round(red));
|
|
48236
48731
|
if (value === 2) {
|
|
48237
48732
|
result += 60;
|
|
48238
48733
|
}
|
|
@@ -48241,7 +48736,7 @@ function assembleStyles() {
|
|
|
48241
48736
|
enumerable: false
|
|
48242
48737
|
},
|
|
48243
48738
|
rgbToAnsi: {
|
|
48244
|
-
value: (red,
|
|
48739
|
+
value: (red, green2, blue) => styles.ansi256ToAnsi(styles.rgbToAnsi256(red, green2, blue)),
|
|
48245
48740
|
enumerable: false
|
|
48246
48741
|
},
|
|
48247
48742
|
hexToAnsi: {
|
|
@@ -48251,7 +48746,7 @@ function assembleStyles() {
|
|
|
48251
48746
|
});
|
|
48252
48747
|
return styles;
|
|
48253
48748
|
}
|
|
48254
|
-
var ANSI_BACKGROUND_OFFSET = 10, wrapAnsi16 = (offset = 0) => (code) => `\x1B[${code + offset}m`, wrapAnsi256 = (offset = 0) => (code) => `\x1B[${38 + offset};5;${code}m`, wrapAnsi16m = (offset = 0) => (red,
|
|
48749
|
+
var ANSI_BACKGROUND_OFFSET = 10, wrapAnsi16 = (offset = 0) => (code) => `\x1B[${code + offset}m`, wrapAnsi256 = (offset = 0) => (code) => `\x1B[${38 + offset};5;${code}m`, wrapAnsi16m = (offset = 0) => (red, green2, blue) => `\x1B[${38 + offset};2;${red};${green2};${blue}m`, styles, modifierNames, foregroundColorNames, backgroundColorNames, colorNames, ansiStyles, ansi_styles_default;
|
|
48255
48750
|
var init_ansi_styles = __esm(() => {
|
|
48256
48751
|
styles = {
|
|
48257
48752
|
modifier: {
|
|
@@ -58653,7 +59148,7 @@ var init_RemoveFileError = __esm(() => {
|
|
|
58653
59148
|
|
|
58654
59149
|
// ../../node_modules/.bun/@inquirer+external-editor@2.0.1+04f2146be16c61ef/node_modules/@inquirer/external-editor/dist/index.js
|
|
58655
59150
|
import { spawn as spawn3, spawnSync as spawnSync2 } from "child_process";
|
|
58656
|
-
import { readFileSync as
|
|
59151
|
+
import { readFileSync as readFileSync20, unlinkSync as unlinkSync6, writeFileSync as writeFileSync14 } from "fs";
|
|
58657
59152
|
import path from "path";
|
|
58658
59153
|
import os from "os";
|
|
58659
59154
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
@@ -58769,7 +59264,7 @@ class ExternalEditor {
|
|
|
58769
59264
|
}
|
|
58770
59265
|
readTemporaryFile() {
|
|
58771
59266
|
try {
|
|
58772
|
-
const tempFileBuffer =
|
|
59267
|
+
const tempFileBuffer = readFileSync20(this.tempFile);
|
|
58773
59268
|
if (tempFileBuffer.length === 0) {
|
|
58774
59269
|
this.text = "";
|
|
58775
59270
|
} else {
|
|
@@ -59964,15 +60459,15 @@ async function geminiQuotaHandler() {
|
|
|
59964
60459
|
}
|
|
59965
60460
|
}
|
|
59966
60461
|
async function codexQuotaHandler() {
|
|
59967
|
-
const { readFileSync:
|
|
59968
|
-
const { join:
|
|
59969
|
-
const { homedir:
|
|
59970
|
-
const credPath =
|
|
60462
|
+
const { readFileSync: readFileSync21, existsSync: existsSync21 } = await import("fs");
|
|
60463
|
+
const { join: join27 } = await import("path");
|
|
60464
|
+
const { homedir: homedir25 } = await import("os");
|
|
60465
|
+
const credPath = join27(homedir25(), ".claudish", "codex-oauth.json");
|
|
59971
60466
|
if (!existsSync21(credPath)) {
|
|
59972
60467
|
console.error(`${RED}No Codex credentials found.${R} Run: ${B}claudish login codex${R}`);
|
|
59973
60468
|
process.exit(1);
|
|
59974
60469
|
}
|
|
59975
|
-
const creds = JSON.parse(
|
|
60470
|
+
const creds = JSON.parse(readFileSync21(credPath, "utf-8"));
|
|
59976
60471
|
let email3 = "";
|
|
59977
60472
|
try {
|
|
59978
60473
|
const parts = creds.access_token.split(".");
|
|
@@ -60024,9 +60519,9 @@ async function codexQuotaHandler() {
|
|
|
60024
60519
|
}
|
|
60025
60520
|
let modelSlugs = [];
|
|
60026
60521
|
try {
|
|
60027
|
-
const modelsPath =
|
|
60522
|
+
const modelsPath = join27(homedir25(), ".codex", "models_cache.json");
|
|
60028
60523
|
if (existsSync21(modelsPath)) {
|
|
60029
|
-
const cache2 = JSON.parse(
|
|
60524
|
+
const cache2 = JSON.parse(readFileSync21(modelsPath, "utf-8"));
|
|
60030
60525
|
modelSlugs = (cache2.models || []).map((m) => m.slug || m.id).filter(Boolean);
|
|
60031
60526
|
}
|
|
60032
60527
|
} catch {}
|
|
@@ -61819,7 +62314,7 @@ function tokBarCells(tokensPerSec, maxTokPerSec, tokWidth) {
|
|
|
61819
62314
|
const raw2 = Math.round(tokWidth * Math.max(0, tokensPerSec) / denom);
|
|
61820
62315
|
return Math.min(tokWidth, Math.max(0, raw2));
|
|
61821
62316
|
}
|
|
61822
|
-
var C,
|
|
62317
|
+
var C, bold3, 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;
|
|
61823
62318
|
var init_theme2 = __esm(() => {
|
|
61824
62319
|
C = {
|
|
61825
62320
|
bg: "#000000",
|
|
@@ -61850,10 +62345,10 @@ var init_theme2 = __esm(() => {
|
|
|
61850
62345
|
chipKeyBg: "#3a3a3a",
|
|
61851
62346
|
chipLabelBg: "#222222"
|
|
61852
62347
|
};
|
|
61853
|
-
|
|
62348
|
+
bold3 = createTextAttributes({ bold: true });
|
|
61854
62349
|
A = {
|
|
61855
|
-
bold:
|
|
61856
|
-
boldIf: (enabled) => enabled ?
|
|
62350
|
+
bold: bold3,
|
|
62351
|
+
boldIf: (enabled) => enabled ? bold3 : undefined
|
|
61857
62352
|
};
|
|
61858
62353
|
LATENCY_BUCKETS = [
|
|
61859
62354
|
{ maxMs: 500, hex: "#1f8f3b" },
|
|
@@ -63991,28 +64486,28 @@ import {
|
|
|
63991
64486
|
copyFileSync as copyFileSync2,
|
|
63992
64487
|
existsSync as existsSync21,
|
|
63993
64488
|
mkdirSync as mkdirSync13,
|
|
63994
|
-
readFileSync as
|
|
63995
|
-
readdirSync as
|
|
64489
|
+
readFileSync as readFileSync21,
|
|
64490
|
+
readdirSync as readdirSync5,
|
|
63996
64491
|
unlinkSync as unlinkSync7,
|
|
63997
64492
|
writeFileSync as writeFileSync15
|
|
63998
64493
|
} from "fs";
|
|
63999
|
-
import { homedir as
|
|
64000
|
-
import { dirname as
|
|
64494
|
+
import { homedir as homedir25 } from "os";
|
|
64495
|
+
import { dirname as dirname9, join as join27 } from "path";
|
|
64001
64496
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
64002
64497
|
function getVersion3() {
|
|
64003
64498
|
return VERSION;
|
|
64004
64499
|
}
|
|
64005
64500
|
function clearAllModelCaches() {
|
|
64006
|
-
const cacheDir =
|
|
64501
|
+
const cacheDir = join27(homedir25(), ".claudish");
|
|
64007
64502
|
if (!existsSync21(cacheDir))
|
|
64008
64503
|
return;
|
|
64009
64504
|
const cachePatterns = ["pricing-cache.json", "recommended-models-cache.json"];
|
|
64010
64505
|
let cleared = 0;
|
|
64011
64506
|
try {
|
|
64012
|
-
const files =
|
|
64507
|
+
const files = readdirSync5(cacheDir);
|
|
64013
64508
|
for (const file2 of files) {
|
|
64014
64509
|
if (cachePatterns.includes(file2)) {
|
|
64015
|
-
unlinkSync7(
|
|
64510
|
+
unlinkSync7(join27(cacheDir, file2));
|
|
64016
64511
|
cleared++;
|
|
64017
64512
|
}
|
|
64018
64513
|
}
|
|
@@ -64422,14 +64917,14 @@ Usage: claudish --models --provider <slug>`);
|
|
|
64422
64917
|
});
|
|
64423
64918
|
config3.resolvedDefaultProvider = resolved;
|
|
64424
64919
|
if (resolved.legacyAutoPromoted && !config3.quiet) {
|
|
64425
|
-
const markerFile =
|
|
64920
|
+
const markerFile = join27(homedir25(), ".claudish", ".legacy-litellm-hint-shown");
|
|
64426
64921
|
if (!existsSync21(markerFile)) {
|
|
64427
64922
|
const hint = buildLegacyHint(resolved);
|
|
64428
64923
|
if (hint) {
|
|
64429
64924
|
console.error(hint);
|
|
64430
64925
|
}
|
|
64431
64926
|
try {
|
|
64432
|
-
mkdirSync13(
|
|
64927
|
+
mkdirSync13(dirname9(markerFile), { recursive: true });
|
|
64433
64928
|
writeFileSync15(markerFile, new Date().toISOString(), "utf-8");
|
|
64434
64929
|
} catch {}
|
|
64435
64930
|
}
|
|
@@ -65189,261 +65684,261 @@ async function probeModelRouting(models, jsonOutput, options = { live: true, tim
|
|
|
65189
65684
|
function printHelp() {
|
|
65190
65685
|
const useColor = !!process.stdout.isTTY && !process.env.NO_COLOR;
|
|
65191
65686
|
const c = (code) => (s) => useColor ? `\x1B[${code}m${s}\x1B[0m` : s;
|
|
65192
|
-
const
|
|
65193
|
-
const
|
|
65687
|
+
const bold4 = c("1");
|
|
65688
|
+
const dim3 = c("2");
|
|
65194
65689
|
const cyan = c("36");
|
|
65195
|
-
const
|
|
65196
|
-
const
|
|
65690
|
+
const green2 = c("32");
|
|
65691
|
+
const yellow2 = c("33");
|
|
65197
65692
|
const magenta = c("35");
|
|
65198
65693
|
const blue = c("34");
|
|
65199
|
-
const h = (title) =>
|
|
65694
|
+
const h = (title) => bold4(cyan(`\u258C ${title}`));
|
|
65200
65695
|
console.log(`
|
|
65201
|
-
${
|
|
65202
|
-
${
|
|
65696
|
+
${bold4("claudish")} ${dim3("\xB7")} Run Claude Code with any AI model
|
|
65697
|
+
${dim3("OpenRouter \xB7 Gemini \xB7 OpenAI \xB7 xAI \xB7 MiniMax \xB7 Kimi \xB7 GLM \xB7 Z.AI \xB7 Sakana \xB7 Poe \xB7 LiteLLM \xB7 Local")}
|
|
65203
65698
|
|
|
65204
65699
|
${h("USAGE")}
|
|
65205
|
-
${
|
|
65206
|
-
${
|
|
65207
|
-
${
|
|
65208
|
-
${
|
|
65700
|
+
${green2("claudish")} ${dim3("# Interactive mode (default, model selector)")}
|
|
65701
|
+
${green2("claudish")} ${yellow2("[OPTIONS] <claude-args...>")} ${dim3("# Single-shot mode (requires --model)")}
|
|
65702
|
+
${green2("claudish")} ${green2("--team")} ${yellow2("a,b,c")} ${yellow2('"prompt"')} ${dim3("# Run models in parallel (magmux grid)")}
|
|
65703
|
+
${green2("claudish")} ${green2("--team")} ${yellow2("a,b,c")} ${green2("-f")} ${yellow2("input.md")} ${dim3("# Team mode with file input")}
|
|
65209
65704
|
|
|
65210
65705
|
${h("MODEL ROUTING")}
|
|
65211
|
-
${
|
|
65212
|
-
${magenta("google@gemini-3-pro")} ${
|
|
65213
|
-
${magenta("openrouter@google/gemini-3-pro")} ${
|
|
65214
|
-
${magenta("oai@gpt-5.3")} ${
|
|
65215
|
-
${magenta("ollama@llama3.2:3")} ${
|
|
65216
|
-
${magenta("ollama@llama3.2:0")} ${
|
|
65217
|
-
|
|
65218
|
-
${
|
|
65219
|
-
${magenta("g, gemini")} ${
|
|
65220
|
-
${magenta("oai")} ${
|
|
65221
|
-
${magenta("cx, codex")} ${
|
|
65222
|
-
${magenta("or")} ${
|
|
65223
|
-
${magenta("x-ai, xai, grok")} ${
|
|
65224
|
-
${magenta("mm, mmax")} ${
|
|
65225
|
-
${magenta("mmc")} ${
|
|
65226
|
-
${magenta("kimi, moon")} ${
|
|
65227
|
-
${magenta("kc")} ${
|
|
65228
|
-
${magenta("glm, zhipu")} ${
|
|
65229
|
-
${magenta("gc")} ${
|
|
65230
|
-
${magenta("z-ai, zai")} ${
|
|
65231
|
-
${magenta("oc, llama, lc, meta")} ${
|
|
65232
|
-
${magenta("zen")} ${
|
|
65233
|
-
${magenta("zengo, zgo")} ${
|
|
65234
|
-
${magenta("v, vertex")} ${
|
|
65235
|
-
${magenta("go")} ${
|
|
65236
|
-
${magenta("poe")} ${
|
|
65237
|
-
${magenta("litellm, ll")} ${
|
|
65238
|
-
${magenta("ds")} ${
|
|
65239
|
-
${magenta("sakana, fugu")} ${
|
|
65240
|
-
${magenta("sc")} ${
|
|
65241
|
-
${magenta("ollama")} ${
|
|
65242
|
-
${magenta("lms, lmstudio")} ${
|
|
65243
|
-
${magenta("vllm")} ${
|
|
65244
|
-
${magenta("mlx")} ${
|
|
65245
|
-
|
|
65246
|
-
${
|
|
65247
|
-
${
|
|
65248
|
-
${
|
|
65249
|
-
${
|
|
65250
|
-
${
|
|
65251
|
-
${
|
|
65252
|
-
${
|
|
65253
|
-
${
|
|
65254
|
-
${
|
|
65255
|
-
${
|
|
65256
|
-
${
|
|
65257
|
-
${
|
|
65258
|
-
|
|
65259
|
-
${
|
|
65706
|
+
${bold4("New syntax:")} ${yellow2("provider@model[:concurrency]")}
|
|
65707
|
+
${magenta("google@gemini-3-pro")} ${dim3("Direct Google API (explicit)")}
|
|
65708
|
+
${magenta("openrouter@google/gemini-3-pro")} ${dim3("OpenRouter (explicit)")}
|
|
65709
|
+
${magenta("oai@gpt-5.3")} ${dim3("Direct OpenAI API (shortcut)")}
|
|
65710
|
+
${magenta("ollama@llama3.2:3")} ${dim3("Local Ollama, 3 concurrent requests")}
|
|
65711
|
+
${magenta("ollama@llama3.2:0")} ${dim3("Local Ollama, no limits")}
|
|
65712
|
+
|
|
65713
|
+
${bold4("Provider shortcuts:")}
|
|
65714
|
+
${magenta("g, gemini")} ${dim3("->")} Google Gemini ${dim3("google@gemini-3-pro")}
|
|
65715
|
+
${magenta("oai")} ${dim3("->")} OpenAI Direct ${dim3("oai@gpt-5.3")}
|
|
65716
|
+
${magenta("cx, codex")} ${dim3("->")} OpenAI Codex ${dim3("cx@gpt-5.3 (Responses API)")}
|
|
65717
|
+
${magenta("or")} ${dim3("->")} OpenRouter ${dim3("or@openai/gpt-5.3")}
|
|
65718
|
+
${magenta("x-ai, xai, grok")} ${dim3("->")} xAI / Grok ${dim3("x-ai@grok-3")}
|
|
65719
|
+
${magenta("mm, mmax")} ${dim3("->")} MiniMax Direct ${dim3("mm@MiniMax-M2.1")}
|
|
65720
|
+
${magenta("mmc")} ${dim3("->")} MiniMax Coding ${dim3("mmc@MiniMax-M2.1")}
|
|
65721
|
+
${magenta("kimi, moon")} ${dim3("->")} Kimi Direct ${dim3("kimi@kimi-k2-thinking-turbo")}
|
|
65722
|
+
${magenta("kc")} ${dim3("->")} Kimi Coding ${dim3("kc@kimi-k2-thinking-turbo")}
|
|
65723
|
+
${magenta("glm, zhipu")} ${dim3("->")} GLM Direct ${dim3("glm@glm-4.7")}
|
|
65724
|
+
${magenta("gc")} ${dim3("->")} GLM Coding ${dim3("gc@glm-4.7")}
|
|
65725
|
+
${magenta("z-ai, zai")} ${dim3("->")} Z.AI Direct ${dim3("z-ai@glm-4.7")}
|
|
65726
|
+
${magenta("oc, llama, lc, meta")} ${dim3("->")} OllamaCloud ${dim3("oc@llama-3.1")}
|
|
65727
|
+
${magenta("zen")} ${dim3("->")} OpenCode Zen ${dim3("zen@grok-code")}
|
|
65728
|
+
${magenta("zengo, zgo")} ${dim3("->")} OpenCode Zen Go ${dim3("zengo@grok-code")}
|
|
65729
|
+
${magenta("v, vertex")} ${dim3("->")} Vertex AI ${dim3("v@gemini-2.5-flash")}
|
|
65730
|
+
${magenta("go")} ${dim3("->")} Gemini Code Assist ${dim3("go@gemini-2.5-flash")}
|
|
65731
|
+
${magenta("poe")} ${dim3("->")} Poe ${dim3("poe@GPT-4o")}
|
|
65732
|
+
${magenta("litellm, ll")} ${dim3("->")} LiteLLM ${dim3("ll@gpt-4o (needs LITELLM_BASE_URL)")}
|
|
65733
|
+
${magenta("ds")} ${dim3("->")} DeepSeek ${dim3("ds@deepseek-chat")}
|
|
65734
|
+
${magenta("sakana, fugu")} ${dim3("->")} Sakana Fugu ${dim3("fugu@fugu-ultra")}
|
|
65735
|
+
${magenta("sc")} ${dim3("->")} Sakana Subscription ${dim3("sc@fugu-ultra")}
|
|
65736
|
+
${magenta("ollama")} ${dim3("->")} Ollama (local) ${dim3("ollama@llama3.2")}
|
|
65737
|
+
${magenta("lms, lmstudio")} ${dim3("->")} LM Studio (local) ${dim3("lms@qwen")}
|
|
65738
|
+
${magenta("vllm")} ${dim3("->")} vLLM (local) ${dim3("vllm@model")}
|
|
65739
|
+
${magenta("mlx")} ${dim3("->")} MLX (local) ${dim3("mlx@model")}
|
|
65740
|
+
|
|
65741
|
+
${bold4("Native auto-detection")} ${dim3("(when no provider specified):")}
|
|
65742
|
+
${yellow2("google/*, gemini-*")} ${dim3("->")} Google API
|
|
65743
|
+
${yellow2("openai/*, gpt-*, o1-*")} ${dim3("->")} OpenAI API
|
|
65744
|
+
${yellow2("x-ai/*, grok-*")} ${dim3("->")} xAI
|
|
65745
|
+
${yellow2("meta-llama/*, llama-*")} ${dim3("->")} OllamaCloud
|
|
65746
|
+
${yellow2("minimax/*, abab-*")} ${dim3("->")} MiniMax API
|
|
65747
|
+
${yellow2("moonshot/*, kimi-*")} ${dim3("->")} Kimi API
|
|
65748
|
+
${yellow2("zhipu/*, glm-*")} ${dim3("->")} GLM API
|
|
65749
|
+
${yellow2("sakana/*, fugu-*")} ${dim3("->")} Sakana Fugu
|
|
65750
|
+
${yellow2("poe:*")} ${dim3("->")} Poe
|
|
65751
|
+
${yellow2("anthropic/*, claude-*")} ${dim3("->")} Native Anthropic
|
|
65752
|
+
${yellow2("(unknown vendor/)")} ${dim3("->")} Error (use openrouter@vendor/model)
|
|
65753
|
+
|
|
65754
|
+
${dim3("A defaultProvider (config / --default-provider) catches bare names that match no rule.")}
|
|
65260
65755
|
|
|
65261
65756
|
${h("OPTIONS")}
|
|
65262
|
-
${
|
|
65263
|
-
${
|
|
65264
|
-
${
|
|
65265
|
-
${
|
|
65266
|
-
${
|
|
65267
|
-
${
|
|
65268
|
-
${
|
|
65269
|
-
${
|
|
65270
|
-
${
|
|
65271
|
-
${
|
|
65272
|
-
${
|
|
65273
|
-
${
|
|
65274
|
-
${
|
|
65275
|
-
${
|
|
65276
|
-
${
|
|
65277
|
-
${
|
|
65278
|
-
${
|
|
65279
|
-
${
|
|
65280
|
-
${
|
|
65281
|
-
${
|
|
65282
|
-
${
|
|
65283
|
-
${
|
|
65284
|
-
${
|
|
65285
|
-
${
|
|
65286
|
-
${
|
|
65287
|
-
${
|
|
65288
|
-
${
|
|
65289
|
-
${
|
|
65290
|
-
${
|
|
65291
|
-
${
|
|
65292
|
-
${
|
|
65293
|
-
${
|
|
65294
|
-
${
|
|
65295
|
-
${
|
|
65296
|
-
${
|
|
65297
|
-
${
|
|
65298
|
-
${
|
|
65299
|
-
${
|
|
65300
|
-
${
|
|
65301
|
-
${
|
|
65302
|
-
${
|
|
65303
|
-
${
|
|
65757
|
+
${green2("-i, --interactive")} Run in interactive mode (default when no prompt given)
|
|
65758
|
+
${green2("-m, --model")} ${yellow2("<model>")} Model to use (required for single-shot mode)
|
|
65759
|
+
${green2("--profile")} ${yellow2("<name>")} Use named profile for model mapping (default profile if omitted)
|
|
65760
|
+
${green2("--default-provider")} ${yellow2("<name>")} Fallback provider for bare model names (builtin or customEndpoints key)
|
|
65761
|
+
${dim3("Precedence: this flag > CLAUDISH_DEFAULT_PROVIDER env > config.json")}
|
|
65762
|
+
${green2("--anthropic-api-billing")} Use your real ANTHROPIC_API_KEY for native Claude models
|
|
65763
|
+
${dim3("(metered API billing). Default: the key is hidden so Claude Code")}
|
|
65764
|
+
${dim3("uses your claude.ai subscription. Env: CLAUDISH_ANTHROPIC_API_BILLING")}
|
|
65765
|
+
${dim3("Config: anthropicApiBilling: true")}
|
|
65766
|
+
${green2("--config")} ${yellow2("<file>")} Use THIS config file for the run, fully replacing the machine
|
|
65767
|
+
${dim3("global (~/.claudish/config.json) AND project (.claudish.json).")}
|
|
65768
|
+
${dim3("A file naming no op:// source never touches 1Password (no prompt).")}
|
|
65769
|
+
${dim3("Env vars still resolve first. Env: CLAUDISH_CONFIG")}
|
|
65770
|
+
${green2("--op")} ${yellow2("<op://glob>")} Load API keys from a 1Password item glob (SDK-based, no op CLI)
|
|
65771
|
+
${green2("--op")} ${yellow2("<glob>")} ${green2("--list")} Preview which fields the glob would import (names only, no values)
|
|
65772
|
+
${green2("--op-env")} ${yellow2("<id>")} Load env vars from a 1Password Environment (highest priority)
|
|
65773
|
+
${green2("--port")} ${yellow2("<port>")} Proxy server port (default: random)
|
|
65774
|
+
${green2("-d, --debug-claudish")} Enable claudish debug logging to file (logs/claudish_*.log)
|
|
65775
|
+
${dim3('Always-on: CLAUDISH_DEBUG=1 env var or "debug": true in config.json')}
|
|
65776
|
+
${green2("--no-debug-claudish")} Force debug logging off for this run (when globally enabled)
|
|
65777
|
+
${green2("--log-off")} Disable always-on structural logging (~/.claudish/logs/)
|
|
65778
|
+
${green2("--log-diag")} ${yellow2("<mode>")} Diagnostic output: auto (default), logfile, off
|
|
65779
|
+
${dim3('Also: CLAUDISH_DIAG_MODE env var or "diagMode" in config.json')}
|
|
65780
|
+
${green2("--log-level")} ${yellow2("<level>")} Log verbosity: debug (full), info (truncated), minimal (labels)
|
|
65781
|
+
${green2("-q, --quiet")} Suppress [claudish] log messages (default in single-shot mode)
|
|
65782
|
+
${green2("-v, --verbose")} Show [claudish] log messages (default in interactive mode)
|
|
65783
|
+
${green2("--json")} Output JSON for tool integration (implies --quiet)
|
|
65784
|
+
${green2("--stdin")} Read prompt from stdin (large prompts / piping)
|
|
65785
|
+
${green2("--free")} Show only FREE models in the interactive selector
|
|
65786
|
+
${green2("--monitor")} Monitor mode - proxy to REAL Anthropic API and log traffic
|
|
65787
|
+
${green2("--advisor")} ${yellow2('"m1,m2[:collector]"')} Multi-model advisor replacement (implies --monitor)
|
|
65788
|
+
${green2("-y, --auto-approve")} Skip permission prompts (--dangerously-skip-permissions)
|
|
65789
|
+
${green2("--no-auto-approve")} Explicitly enable permission prompts (default)
|
|
65790
|
+
${green2("--dangerous")} Pass --dangerouslyDisableSandbox to Claude Code
|
|
65791
|
+
${green2("--cost-track")} Enable cost tracking for API usage
|
|
65792
|
+
${green2("--cost-audit")} Show cost analysis report
|
|
65793
|
+
${green2("--cost-reset")} Reset accumulated cost statistics
|
|
65794
|
+
${green2("--version")} Show version information
|
|
65795
|
+
${green2("-h, --help")} Show this help message
|
|
65796
|
+
${green2("--help-ai")} Show AI agent usage guide (file-based patterns, sub-agents)
|
|
65797
|
+
${green2("--init")} Install Claudish skill in current project (.claude/skills/)
|
|
65798
|
+
${green2("--")} Separator: everything after passes directly to Claude Code
|
|
65304
65799
|
|
|
65305
65800
|
${h("MODEL DISCOVERY")}
|
|
65306
|
-
${
|
|
65307
|
-
${
|
|
65308
|
-
${
|
|
65309
|
-
${
|
|
65310
|
-
${
|
|
65311
|
-
${
|
|
65312
|
-
${
|
|
65313
|
-
${
|
|
65314
|
-
${
|
|
65315
|
-
${
|
|
65316
|
-
${
|
|
65317
|
-
${
|
|
65318
|
-
${
|
|
65319
|
-
${
|
|
65801
|
+
${green2("--models")} Top 100 ranked (Firebase + local providers)
|
|
65802
|
+
${green2("--models --provider")} ${yellow2("<slug>")} Filter the catalog to one provider
|
|
65803
|
+
${dim3("e.g. --provider opencode-zen, anthropic, openai")}
|
|
65804
|
+
${green2("--providers")} Every provider + active-model count
|
|
65805
|
+
${green2("-s, --models-search")} ${yellow2("<query>")} Fuzzy search: id, brand synonyms (chatgpt,
|
|
65806
|
+
${dim3("claude, grok), gateways (zen, oc, codex), caps")}
|
|
65807
|
+
${green2("--models-top")} Curated recommended models (flagship + fast)
|
|
65808
|
+
${green2("--probe")} ${yellow2("<models...>")} Probe each provider in the fallback chain with
|
|
65809
|
+
${dim3("a real 1-token request (may incur tiny cost)")}
|
|
65810
|
+
${green2("--no-probe")} Skip live requests, show static chain only
|
|
65811
|
+
${green2("--probe-timeout")} ${yellow2("<secs>")} Per-link timeout for live probes (default: 40)
|
|
65812
|
+
${green2("--models-refresh")} Force refresh the slim model catalog from Firebase
|
|
65813
|
+
${green2("--models-skip-update")} Skip the launcher catalog warm step (offline)
|
|
65814
|
+
${green2("--json")} JSON output (with --models / --models-top / --probe)
|
|
65320
65815
|
|
|
65321
65816
|
${h("TEAM MODE")}
|
|
65322
|
-
${
|
|
65323
|
-
${
|
|
65324
|
-
${
|
|
65325
|
-
${
|
|
65817
|
+
${green2("--team")} ${yellow2("<models>")} Run multiple models in parallel (comma-separated)
|
|
65818
|
+
${dim3('Example: --team minimax-m2.5,kimi-k2.5 "prompt"')}
|
|
65819
|
+
${green2("--mode")} ${yellow2("<mode>")} Team mode: default (grid), interactive, json
|
|
65820
|
+
${green2("-f, --file")} ${yellow2("<path>")} Read prompt from file (use with --team or single-shot)
|
|
65326
65821
|
|
|
65327
|
-
${h("MODEL MAPPING")} ${
|
|
65328
|
-
${
|
|
65329
|
-
${
|
|
65330
|
-
${
|
|
65331
|
-
${
|
|
65822
|
+
${h("MODEL MAPPING")} ${dim3("(per-role override)")}
|
|
65823
|
+
${green2("--model-opus")} ${yellow2("<model>")} Model for Opus role (planning, complex tasks)
|
|
65824
|
+
${green2("--model-sonnet")} ${yellow2("<model>")} Model for Sonnet role (default coding)
|
|
65825
|
+
${green2("--model-haiku")} ${yellow2("<model>")} Model for Haiku role (fast tasks, background)
|
|
65826
|
+
${green2("--model-subagent")} ${yellow2("<model>")} Model for sub-agents (Task tool)
|
|
65332
65827
|
|
|
65333
65828
|
${h("SUBCOMMANDS")}
|
|
65334
|
-
${
|
|
65335
|
-
${
|
|
65336
|
-
${
|
|
65337
|
-
${
|
|
65338
|
-
${
|
|
65339
|
-
${
|
|
65340
|
-
|
|
65341
|
-
${
|
|
65342
|
-
${
|
|
65343
|
-
${
|
|
65344
|
-
${
|
|
65345
|
-
${
|
|
65346
|
-
${
|
|
65347
|
-
${
|
|
65348
|
-
${
|
|
65349
|
-
${
|
|
65350
|
-
|
|
65351
|
-
${
|
|
65352
|
-
${
|
|
65353
|
-
${
|
|
65354
|
-
${
|
|
65355
|
-
|
|
65356
|
-
${h("1PASSWORD")} ${
|
|
65357
|
-
${
|
|
65358
|
-
${
|
|
65359
|
-
${
|
|
65360
|
-
${
|
|
65361
|
-
${
|
|
65362
|
-
${
|
|
65363
|
-
${
|
|
65829
|
+
${green2("claudish config")} Open the interactive config TUI (profiles,
|
|
65830
|
+
${dim3("providers, routing, 1Password)")}
|
|
65831
|
+
${green2("claudish providers")} ${yellow2("[--json]")} Show provider credential status (no key material)
|
|
65832
|
+
${green2("claudish quota")} ${yellow2("[provider]")} Show remaining quota/usage (alias: usage)
|
|
65833
|
+
${green2("claudish serve")} ${yellow2("--port <n> --models <p>")} Run the Claude Desktop redirect gateway
|
|
65834
|
+
${green2("claudish update")} Check for updates and install the latest version
|
|
65835
|
+
|
|
65836
|
+
${bold4("Profiles:")}
|
|
65837
|
+
${green2("claudish init")} ${yellow2("[--local|--global]")} Setup wizard - create config + first profile
|
|
65838
|
+
${green2("claudish profile list")} ${yellow2("[scope]")} List all profiles (both scopes by default)
|
|
65839
|
+
${green2("claudish profile add")} ${yellow2("[scope]")} Add a new profile
|
|
65840
|
+
${green2("claudish profile remove")} ${yellow2("[name] [scope]")} Remove a profile
|
|
65841
|
+
${green2("claudish profile use")} ${yellow2("[name] [scope]")} Set default profile
|
|
65842
|
+
${green2("claudish profile show")} ${yellow2("[name] [scope]")} Show profile details
|
|
65843
|
+
${green2("claudish profile edit")} ${yellow2("[name] [scope]")} Edit a profile
|
|
65844
|
+
${dim3("scope = --local (.claudish.json) | --global (~/.claudish/config.json) | (prompted)")}
|
|
65845
|
+
|
|
65846
|
+
${bold4("Authentication:")}
|
|
65847
|
+
${green2("claudish login")} ${yellow2("[provider]")} Login to an OAuth provider (interactive if omitted)
|
|
65848
|
+
${green2("claudish logout")} ${yellow2("[provider]")} Clear OAuth credentials
|
|
65849
|
+
${dim3("Providers: gemini, kimi")}
|
|
65850
|
+
|
|
65851
|
+
${h("1PASSWORD")} ${dim3("(SDK-based \u2014 no op CLI needed for secrets)")}
|
|
65852
|
+
${dim3("Auth via OP_SERVICE_ACCOUNT_TOKEN, or OP_ACCOUNT / onepasswordAccount config (DesktopAuth).")}
|
|
65853
|
+
${green2("--op")} ${yellow2("<glob> --list")} Preview which fields a glob would import (names only)
|
|
65854
|
+
${green2("--op")} ${yellow2("<glob>")} ${yellow2("[...args]")} Resolve a glob into env vars, then run a session
|
|
65855
|
+
${dim3("Inline op import requires a GLOB (self-names via field labels)")}
|
|
65856
|
+
${dim3('Example: claudish --op "op://Jack/Keys/**" --model gpt-4o "task"')}
|
|
65857
|
+
${green2("--op-env")} ${yellow2("<id>")} Load a 1Password Environment (highest-priority source)
|
|
65858
|
+
${dim3("Persistent setup (single refs, sets, environments, account): claudish config -> 1Password tab")}
|
|
65364
65859
|
|
|
65365
65860
|
${h("CLAUDE CODE FLAG PASSTHROUGH")}
|
|
65366
|
-
${
|
|
65367
|
-
${
|
|
65368
|
-
${
|
|
65369
|
-
${
|
|
65370
|
-
${
|
|
65371
|
-
${
|
|
65861
|
+
${dim3("Any unrecognized flag is forwarded to Claude Code. Claudish flags can appear in any order.")}
|
|
65862
|
+
${green2("claudish")} --model grok ${yellow2("--agent test")} ${yellow2('"task"')} ${dim3("# --agent passes through")}
|
|
65863
|
+
${green2("claudish")} --model grok ${yellow2("--effort high")} --stdin ${yellow2('"task"')} ${dim3("# --effort passes, --stdin stays")}
|
|
65864
|
+
${green2("claudish")} --model grok ${yellow2("--permission-mode plan")} -i ${dim3("# works in interactive too")}
|
|
65865
|
+
${dim3("Use -- when a Claude Code flag value starts with '-':")}
|
|
65866
|
+
${green2("claudish")} --model grok ${green2("--")} ${yellow2('--system-prompt "-verbose mode" "task"')}
|
|
65372
65867
|
|
|
65373
65868
|
${h("CUSTOM MODELS & ENDPOINTS")}
|
|
65374
|
-
${
|
|
65375
|
-
${
|
|
65376
|
-
${
|
|
65377
|
-
${
|
|
65869
|
+
${dim3("Claudish accepts ANY valid model ID from the Firebase catalog, even if not in --models:")}
|
|
65870
|
+
${green2("claudish")} --model ${yellow2("openrouter@your_provider/custom-model-123")} ${yellow2('"task"')}
|
|
65871
|
+
${dim3("Named custom endpoints live in ~/.claudish/config.json under 'customEndpoints' and route via @:")}
|
|
65872
|
+
${green2("claudish")} --model ${yellow2("my-vllm@llama3.1-70b")} ${yellow2('"task"')}
|
|
65378
65873
|
|
|
65379
65874
|
${h("MODES")}
|
|
65380
|
-
${
|
|
65381
|
-
${
|
|
65875
|
+
${green2("\u2022")} ${bold4("Interactive")} ${dim3("(default):")} shows model selector, starts a persistent session
|
|
65876
|
+
${green2("\u2022")} ${bold4("Single-shot")} ${dim3("(--model):")} runs one task headless and exits
|
|
65382
65877
|
|
|
65383
65878
|
${h("NOTES")}
|
|
65384
|
-
${
|
|
65385
|
-
${
|
|
65386
|
-
${
|
|
65387
|
-
${
|
|
65879
|
+
${yellow2("\u2022")} Permission prompts are ${bold4("ENABLED")} by default (normal Claude Code behavior)
|
|
65880
|
+
${yellow2("\u2022")} Use ${green2("-y")} / ${green2("--auto-approve")} to skip permission prompts
|
|
65881
|
+
${yellow2("\u2022")} Model selector appears ONLY in interactive mode when ${green2("--model")} not specified
|
|
65882
|
+
${yellow2("\u2022")} ${green2("--dangerous")} disables the sandbox \u2014 use with extreme caution
|
|
65388
65883
|
|
|
65389
65884
|
${h("ENVIRONMENT VARIABLES")}
|
|
65390
|
-
${
|
|
65885
|
+
${dim3("Claudish auto-loads a .env file from the current directory.")}
|
|
65391
65886
|
|
|
65392
|
-
${
|
|
65887
|
+
${bold4("Claude Code installation:")}
|
|
65393
65888
|
${blue("CLAUDE_PATH")} Custom path to Claude Code binary
|
|
65394
|
-
${
|
|
65889
|
+
${dim3("Search: CLAUDE_PATH -> ~/.claude/local/claude -> PATH")}
|
|
65395
65890
|
|
|
65396
|
-
${
|
|
65891
|
+
${bold4("API keys")} ${dim3("(at least one required for cloud models):")}
|
|
65397
65892
|
${blue("OPENROUTER_API_KEY")} OpenRouter (default backend)
|
|
65398
|
-
${blue("GEMINI_API_KEY")} Google Gemini ${
|
|
65399
|
-
${blue("OPENAI_API_KEY")} OpenAI ${
|
|
65400
|
-
${blue("OPENAI_CODEX_API_KEY")} OpenAI Codex / Responses API ${
|
|
65401
|
-
${blue("XAI_API_KEY")} xAI / Grok ${
|
|
65402
|
-
${blue("MINIMAX_API_KEY")} MiniMax ${
|
|
65403
|
-
${blue("MINIMAX_CODING_API_KEY")} MiniMax Coding Plan ${
|
|
65404
|
-
${blue("MOONSHOT_API_KEY")} Kimi / Moonshot ${
|
|
65405
|
-
${blue("KIMI_CODING_API_KEY")} Kimi Coding Plan ${
|
|
65406
|
-
${blue("ZHIPU_API_KEY")} GLM / Zhipu ${
|
|
65407
|
-
${blue("GLM_CODING_API_KEY")} GLM Coding Plan ${
|
|
65408
|
-
${blue("ZAI_API_KEY")} Z.AI ${
|
|
65409
|
-
${blue("DEEPSEEK_API_KEY")} DeepSeek ${
|
|
65410
|
-
${blue("SAKANA_API_KEY")} Sakana Fugu ${
|
|
65411
|
-
${blue("SAKANA_SUBSCRIPTION_API_KEY")} Sakana Fugu Subscription ${
|
|
65412
|
-
${blue("OLLAMA_API_KEY")} OllamaCloud ${
|
|
65413
|
-
${blue("OPENCODE_API_KEY")} OpenCode Zen ${
|
|
65414
|
-
${blue("POE_API_KEY")} Poe ${
|
|
65415
|
-
${blue("LITELLM_API_KEY")} LiteLLM ${
|
|
65416
|
-
${blue("VERTEX_API_KEY")} Vertex AI Express ${
|
|
65417
|
-
${blue("VERTEX_PROJECT")} Vertex AI project ID ${
|
|
65418
|
-
${blue("VERTEX_LOCATION")} Vertex AI region ${
|
|
65893
|
+
${blue("GEMINI_API_KEY")} Google Gemini ${dim3("(g@, gemini@; alias GOOGLE_API_KEY)")}
|
|
65894
|
+
${blue("OPENAI_API_KEY")} OpenAI ${dim3("(oai@)")}
|
|
65895
|
+
${blue("OPENAI_CODEX_API_KEY")} OpenAI Codex / Responses API ${dim3("(cx@, codex@)")}
|
|
65896
|
+
${blue("XAI_API_KEY")} xAI / Grok ${dim3("(x-ai@, grok@)")}
|
|
65897
|
+
${blue("MINIMAX_API_KEY")} MiniMax ${dim3("(mm@, mmax@)")}
|
|
65898
|
+
${blue("MINIMAX_CODING_API_KEY")} MiniMax Coding Plan ${dim3("(mmc@)")}
|
|
65899
|
+
${blue("MOONSHOT_API_KEY")} Kimi / Moonshot ${dim3("(kimi@, moon@; alias KIMI_API_KEY)")}
|
|
65900
|
+
${blue("KIMI_CODING_API_KEY")} Kimi Coding Plan ${dim3("(kc@)")}
|
|
65901
|
+
${blue("ZHIPU_API_KEY")} GLM / Zhipu ${dim3("(glm@, zhipu@; alias GLM_API_KEY)")}
|
|
65902
|
+
${blue("GLM_CODING_API_KEY")} GLM Coding Plan ${dim3("(gc@; alias ZAI_CODING_API_KEY)")}
|
|
65903
|
+
${blue("ZAI_API_KEY")} Z.AI ${dim3("(z-ai@, zai@)")}
|
|
65904
|
+
${blue("DEEPSEEK_API_KEY")} DeepSeek ${dim3("(ds@)")}
|
|
65905
|
+
${blue("SAKANA_API_KEY")} Sakana Fugu ${dim3("(sakana@, fugu@)")}
|
|
65906
|
+
${blue("SAKANA_SUBSCRIPTION_API_KEY")} Sakana Fugu Subscription ${dim3("(sc@; separate subscription key)")}
|
|
65907
|
+
${blue("OLLAMA_API_KEY")} OllamaCloud ${dim3("(oc@, llama@)")}
|
|
65908
|
+
${blue("OPENCODE_API_KEY")} OpenCode Zen ${dim3("(zen@; optional - free models work without it)")}
|
|
65909
|
+
${blue("POE_API_KEY")} Poe ${dim3("(poe@)")}
|
|
65910
|
+
${blue("LITELLM_API_KEY")} LiteLLM ${dim3("(litellm@, ll@; needs LITELLM_BASE_URL)")}
|
|
65911
|
+
${blue("VERTEX_API_KEY")} Vertex AI Express ${dim3("(v@)")}
|
|
65912
|
+
${blue("VERTEX_PROJECT")} Vertex AI project ID ${dim3("(OAuth mode, v@)")}
|
|
65913
|
+
${blue("VERTEX_LOCATION")} Vertex AI region ${dim3("(default: us-central1)")}
|
|
65419
65914
|
${blue("ANTHROPIC_API_KEY")} Placeholder (prevents Claude Code dialog)
|
|
65420
65915
|
${blue("ANTHROPIC_AUTH_TOKEN")} Placeholder (prevents Claude Code login screen)
|
|
65421
65916
|
|
|
65422
|
-
${
|
|
65917
|
+
${bold4("Custom / base-URL overrides:")}
|
|
65423
65918
|
${blue("GEMINI_BASE_URL")} Custom Gemini endpoint
|
|
65424
65919
|
${blue("OPENAI_BASE_URL")} Custom OpenAI / Azure endpoint
|
|
65425
65920
|
${blue("MINIMAX_BASE_URL")} Custom MiniMax endpoint
|
|
65426
|
-
${blue("MOONSHOT_BASE_URL")} Custom Kimi / Moonshot endpoint ${
|
|
65427
|
-
${blue("ZHIPU_BASE_URL")} Custom GLM / Zhipu endpoint ${
|
|
65428
|
-
${blue("SAKANA_BASE_URL")} Custom Sakana endpoint ${
|
|
65429
|
-
${blue("LITELLM_BASE_URL")} LiteLLM gateway base URL ${
|
|
65430
|
-
${blue("OLLAMACLOUD_BASE_URL")} OllamaCloud ${
|
|
65431
|
-
${blue("OPENCODE_BASE_URL")} OpenCode Zen ${
|
|
65432
|
-
|
|
65433
|
-
${
|
|
65434
|
-
${blue("OLLAMA_BASE_URL")} Ollama server ${
|
|
65435
|
-
${blue("LMSTUDIO_BASE_URL")} LM Studio server ${
|
|
65436
|
-
${blue("VLLM_BASE_URL")} vLLM server ${
|
|
65437
|
-
${blue("MLX_BASE_URL")} MLX server ${
|
|
65438
|
-
|
|
65439
|
-
${
|
|
65440
|
-
${blue("CLAUDISH_MODEL")} Default model ${
|
|
65441
|
-
${blue("CLAUDISH_DEFAULT_PROVIDER")} Fallback provider for bare names ${
|
|
65921
|
+
${blue("MOONSHOT_BASE_URL")} Custom Kimi / Moonshot endpoint ${dim3("(alias KIMI_BASE_URL)")}
|
|
65922
|
+
${blue("ZHIPU_BASE_URL")} Custom GLM / Zhipu endpoint ${dim3("(alias GLM_BASE_URL)")}
|
|
65923
|
+
${blue("SAKANA_BASE_URL")} Custom Sakana endpoint ${dim3("(default: https://api.sakana.ai)")}
|
|
65924
|
+
${blue("LITELLM_BASE_URL")} LiteLLM gateway base URL ${dim3("(required for ll@)")}
|
|
65925
|
+
${blue("OLLAMACLOUD_BASE_URL")} OllamaCloud ${dim3("(default: https://ollama.com)")}
|
|
65926
|
+
${blue("OPENCODE_BASE_URL")} OpenCode Zen ${dim3("(default: https://opencode.ai/zen)")}
|
|
65927
|
+
|
|
65928
|
+
${bold4("Local providers:")}
|
|
65929
|
+
${blue("OLLAMA_BASE_URL")} Ollama server ${dim3("(default: http://localhost:11434; alias OLLAMA_HOST)")}
|
|
65930
|
+
${blue("LMSTUDIO_BASE_URL")} LM Studio server ${dim3("(default: http://localhost:1234)")}
|
|
65931
|
+
${blue("VLLM_BASE_URL")} vLLM server ${dim3("(default: http://localhost:8000)")}
|
|
65932
|
+
${blue("MLX_BASE_URL")} MLX server ${dim3("(default: http://127.0.0.1:8080)")}
|
|
65933
|
+
|
|
65934
|
+
${bold4("Claudish settings:")}
|
|
65935
|
+
${blue("CLAUDISH_MODEL")} Default model ${dim3("(default: openai/gpt-5.3)")}
|
|
65936
|
+
${blue("CLAUDISH_DEFAULT_PROVIDER")} Fallback provider for bare names ${dim3("(see --default-provider)")}
|
|
65442
65937
|
${blue("CLAUDISH_PORT")} Default proxy port
|
|
65443
65938
|
${blue("CLAUDISH_CONTEXT_WINDOW")} Override context window size
|
|
65444
65939
|
${blue("CLAUDISH_DIAG_MODE")} Diagnostic output: auto / logfile / off
|
|
65445
|
-
${blue("CLAUDISH_DEBUG")} Always enable debug logging: 1 / true ${
|
|
65446
|
-
${blue("CLAUDISH_ANTHROPIC_API_BILLING")} Bill native Claude to your API key ${
|
|
65940
|
+
${blue("CLAUDISH_DEBUG")} Always enable debug logging: 1 / true ${dim3("(same as -d)")}
|
|
65941
|
+
${blue("CLAUDISH_ANTHROPIC_API_BILLING")} Bill native Claude to your API key ${dim3("(see --anthropic-api-billing)")}
|
|
65447
65942
|
${blue("CLAUDISH_MCP_TOOLS")} MCP tool gating: all / low-level / agentic / channel
|
|
65448
65943
|
${blue("CLAUDISH_MODEL_OPUS")} Override model for Opus role
|
|
65449
65944
|
${blue("CLAUDISH_MODEL_SONNET")} Override model for Sonnet role
|
|
@@ -65451,47 +65946,47 @@ ${h("ENVIRONMENT VARIABLES")}
|
|
|
65451
65946
|
${blue("CLAUDISH_MODEL_SUBAGENT")} Override model for sub-agents
|
|
65452
65947
|
${blue("NO_COLOR")} Set to disable colored output
|
|
65453
65948
|
|
|
65454
|
-
${
|
|
65949
|
+
${bold4("1Password auth:")}
|
|
65455
65950
|
${blue("OP_SERVICE_ACCOUNT_TOKEN")} Service-account token (preferred for headless)
|
|
65456
|
-
${blue("OP_ACCOUNT")} Account URL for DesktopAuth ${
|
|
65951
|
+
${blue("OP_ACCOUNT")} Account URL for DesktopAuth ${dim3("(e.g. my-team.1password.com)")}
|
|
65457
65952
|
|
|
65458
65953
|
${h("EXAMPLES")}
|
|
65459
|
-
${
|
|
65460
|
-
${
|
|
65461
|
-
${
|
|
65954
|
+
${dim3("# Interactive (default) - model selector")}
|
|
65955
|
+
${green2("claudish")}
|
|
65956
|
+
${green2("claudish")} --free ${dim3("# only FREE models")}
|
|
65462
65957
|
|
|
65463
|
-
${
|
|
65464
|
-
${
|
|
65465
|
-
${
|
|
65466
|
-
${
|
|
65958
|
+
${dim3("# Explicit provider routing")}
|
|
65959
|
+
${green2("claudish")} --model ${magenta("google@gemini-3-pro")} ${yellow2('"implement auth"')}
|
|
65960
|
+
${green2("claudish")} --model ${magenta("oai@gpt-5.3")} ${yellow2('"add tests for login"')}
|
|
65961
|
+
${green2("claudish")} --model ${magenta("openrouter@deepseek/deepseek-r1")} ${yellow2('"unknown vendor"')}
|
|
65467
65962
|
|
|
65468
|
-
${
|
|
65469
|
-
${
|
|
65470
|
-
${
|
|
65963
|
+
${dim3("# Native auto-detection (provider inferred from model name)")}
|
|
65964
|
+
${green2("claudish")} --model ${yellow2("gpt-4o")} ${yellow2('"routes to OpenAI"')}
|
|
65965
|
+
${green2("claudish")} --model ${yellow2("gemini-2.5-pro")} ${yellow2('"routes to Google"')}
|
|
65471
65966
|
|
|
65472
|
-
${
|
|
65473
|
-
${
|
|
65967
|
+
${dim3("# Per-role model mapping")}
|
|
65968
|
+
${green2("claudish")} --model-opus ${magenta("oai@gpt-5.3")} --model-sonnet ${magenta("google@gemini-3-pro")}
|
|
65474
65969
|
|
|
65475
|
-
${
|
|
65476
|
-
${
|
|
65970
|
+
${dim3("# stdin for large prompts (diffs, code review)")}
|
|
65971
|
+
${dim3("git diff |")} ${green2("claudish")} --stdin --model ${magenta("oai@gpt-5.3")} ${yellow2('"Review these changes"')}
|
|
65477
65972
|
|
|
65478
|
-
${
|
|
65479
|
-
${
|
|
65480
|
-
${
|
|
65481
|
-
${
|
|
65973
|
+
${dim3("# Local models with concurrency control")}
|
|
65974
|
+
${green2("claudish")} --model ${magenta("ollama@llama3.2:3")} ${yellow2('"3 concurrent requests"')}
|
|
65975
|
+
${green2("claudish")} --model ${magenta("lms@qwen2.5-coder")} ${yellow2('"LM Studio shortcut"')}
|
|
65976
|
+
${green2("claudish")} --model ${yellow2('"http://localhost:8000/mistral"')} ${yellow2('"any OpenAI-compatible URL"')}
|
|
65482
65977
|
|
|
65483
|
-
${
|
|
65484
|
-
${
|
|
65978
|
+
${dim3("# Autonomous (no prompts, no sandbox) \u2014 use with caution")}
|
|
65979
|
+
${green2("claudish")} -y --dangerous ${yellow2('"refactor entire codebase"')}
|
|
65485
65980
|
|
|
65486
65981
|
${h("MORE INFO")}
|
|
65487
|
-
${
|
|
65488
|
-
${
|
|
65982
|
+
${dim3("GitHub:")} ${blue("https://github.com/MadAppGang/claude-code")}
|
|
65983
|
+
${dim3("OpenRouter:")} ${blue("https://openrouter.ai")}
|
|
65489
65984
|
`);
|
|
65490
65985
|
}
|
|
65491
65986
|
function printAIAgentGuide() {
|
|
65492
65987
|
try {
|
|
65493
|
-
const guidePath =
|
|
65494
|
-
const guideContent =
|
|
65988
|
+
const guidePath = join27(__dirname3, "../AI_AGENT_GUIDE.md");
|
|
65989
|
+
const guideContent = readFileSync21(guidePath, "utf-8");
|
|
65495
65990
|
console.log(guideContent);
|
|
65496
65991
|
} catch (error46) {
|
|
65497
65992
|
console.error("Error reading AI Agent Guide:");
|
|
@@ -65507,10 +66002,10 @@ async function initializeClaudishSkill() {
|
|
|
65507
66002
|
console.log(`\uD83D\uDD27 Initializing Claudish skill in current project...
|
|
65508
66003
|
`);
|
|
65509
66004
|
const cwd = process.cwd();
|
|
65510
|
-
const claudeDir =
|
|
65511
|
-
const skillsDir =
|
|
65512
|
-
const claudishSkillDir =
|
|
65513
|
-
const skillFile =
|
|
66005
|
+
const claudeDir = join27(cwd, ".claude");
|
|
66006
|
+
const skillsDir = join27(claudeDir, "skills");
|
|
66007
|
+
const claudishSkillDir = join27(skillsDir, "claudish-usage");
|
|
66008
|
+
const skillFile = join27(claudishSkillDir, "SKILL.md");
|
|
65514
66009
|
if (existsSync21(skillFile)) {
|
|
65515
66010
|
console.log("\u2705 Claudish skill already installed at:");
|
|
65516
66011
|
console.log(` ${skillFile}
|
|
@@ -65518,7 +66013,7 @@ async function initializeClaudishSkill() {
|
|
|
65518
66013
|
console.log("\uD83D\uDCA1 To reinstall, delete the file and run 'claudish --init' again.");
|
|
65519
66014
|
return;
|
|
65520
66015
|
}
|
|
65521
|
-
const sourceSkillPath =
|
|
66016
|
+
const sourceSkillPath = join27(__dirname3, "../skills/claudish-usage/SKILL.md");
|
|
65522
66017
|
if (!existsSync21(sourceSkillPath)) {
|
|
65523
66018
|
console.error("\u274C Error: Claudish skill file not found in installation.");
|
|
65524
66019
|
console.error(` Expected at: ${sourceSkillPath}`);
|
|
@@ -65609,7 +66104,7 @@ var init_cli = __esm(() => {
|
|
|
65609
66104
|
init_routing_rules();
|
|
65610
66105
|
init_provider_resolver();
|
|
65611
66106
|
__filename3 = fileURLToPath2(import.meta.url);
|
|
65612
|
-
__dirname3 =
|
|
66107
|
+
__dirname3 = dirname9(__filename3);
|
|
65613
66108
|
});
|
|
65614
66109
|
|
|
65615
66110
|
// src/update-checker.ts
|
|
@@ -65621,24 +66116,24 @@ __export(exports_update_checker, {
|
|
|
65621
66116
|
clearCache: () => clearCache,
|
|
65622
66117
|
checkForUpdates: () => checkForUpdates
|
|
65623
66118
|
});
|
|
65624
|
-
import { existsSync as existsSync22, mkdirSync as mkdirSync14, readFileSync as
|
|
65625
|
-
import { homedir as
|
|
65626
|
-
import { join as
|
|
66119
|
+
import { existsSync as existsSync22, mkdirSync as mkdirSync14, readFileSync as readFileSync22, unlinkSync as unlinkSync8, writeFileSync as writeFileSync16 } from "fs";
|
|
66120
|
+
import { homedir as homedir26, platform as platform2, tmpdir } from "os";
|
|
66121
|
+
import { join as join28 } from "path";
|
|
65627
66122
|
function getCacheFilePath() {
|
|
65628
66123
|
let cacheDir;
|
|
65629
66124
|
if (isWindows) {
|
|
65630
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
65631
|
-
cacheDir =
|
|
66125
|
+
const localAppData = process.env.LOCALAPPDATA || join28(homedir26(), "AppData", "Local");
|
|
66126
|
+
cacheDir = join28(localAppData, "claudish");
|
|
65632
66127
|
} else {
|
|
65633
|
-
cacheDir =
|
|
66128
|
+
cacheDir = join28(homedir26(), ".cache", "claudish");
|
|
65634
66129
|
}
|
|
65635
66130
|
try {
|
|
65636
66131
|
if (!existsSync22(cacheDir)) {
|
|
65637
66132
|
mkdirSync14(cacheDir, { recursive: true });
|
|
65638
66133
|
}
|
|
65639
|
-
return
|
|
66134
|
+
return join28(cacheDir, "update-check.json");
|
|
65640
66135
|
} catch {
|
|
65641
|
-
return
|
|
66136
|
+
return join28(tmpdir(), "claudish-update-check.json");
|
|
65642
66137
|
}
|
|
65643
66138
|
}
|
|
65644
66139
|
function readCache() {
|
|
@@ -65647,7 +66142,7 @@ function readCache() {
|
|
|
65647
66142
|
if (!existsSync22(cachePath)) {
|
|
65648
66143
|
return null;
|
|
65649
66144
|
}
|
|
65650
|
-
const data = JSON.parse(
|
|
66145
|
+
const data = JSON.parse(readFileSync22(cachePath, "utf-8"));
|
|
65651
66146
|
return data;
|
|
65652
66147
|
} catch {
|
|
65653
66148
|
return null;
|
|
@@ -66549,15 +67044,15 @@ var init_local_liveness = __esm(() => {
|
|
|
66549
67044
|
});
|
|
66550
67045
|
|
|
66551
67046
|
// src/providers/probe-catalog.ts
|
|
66552
|
-
import { existsSync as existsSync23, mkdirSync as mkdirSync15, readFileSync as
|
|
66553
|
-
import { homedir as
|
|
66554
|
-
import { dirname as
|
|
67047
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync15, readFileSync as readFileSync23, writeFileSync as writeFileSync17 } from "fs";
|
|
67048
|
+
import { homedir as homedir27 } from "os";
|
|
67049
|
+
import { dirname as dirname10, join as join29 } from "path";
|
|
66555
67050
|
function readProbeModelsCache(path2 = PROBE_MODELS_CACHE_PATH) {
|
|
66556
67051
|
if (!existsSync23(path2))
|
|
66557
67052
|
return null;
|
|
66558
67053
|
let raw2;
|
|
66559
67054
|
try {
|
|
66560
|
-
raw2 = JSON.parse(
|
|
67055
|
+
raw2 = JSON.parse(readFileSync23(path2, "utf-8"));
|
|
66561
67056
|
} catch {
|
|
66562
67057
|
return null;
|
|
66563
67058
|
}
|
|
@@ -66566,7 +67061,7 @@ function readProbeModelsCache(path2 = PROBE_MODELS_CACHE_PATH) {
|
|
|
66566
67061
|
return raw2;
|
|
66567
67062
|
}
|
|
66568
67063
|
function writeProbeModelsCache(data, path2 = PROBE_MODELS_CACHE_PATH) {
|
|
66569
|
-
mkdirSync15(
|
|
67064
|
+
mkdirSync15(dirname10(path2), { recursive: true });
|
|
66570
67065
|
writeFileSync17(path2, JSON.stringify(data), "utf-8");
|
|
66571
67066
|
}
|
|
66572
67067
|
function isCacheFresh(data, ttlMs = CACHE_TTL_MS4) {
|
|
@@ -66686,7 +67181,7 @@ function isValidResponse(raw2) {
|
|
|
66686
67181
|
var PROBE_MODELS_URL = "https://us-central1-claudish-6da10.cloudfunctions.net/probeModels", CACHE_TTL_MS4, FETCH_TIMEOUT_MS3 = 15000, PROBE_MODELS_CACHE_PATH, _inFlight = null;
|
|
66687
67182
|
var init_probe_catalog = __esm(() => {
|
|
66688
67183
|
CACHE_TTL_MS4 = 60 * 60 * 1000;
|
|
66689
|
-
PROBE_MODELS_CACHE_PATH =
|
|
67184
|
+
PROBE_MODELS_CACHE_PATH = join29(homedir27(), ".claudish", "probe-models.json");
|
|
66690
67185
|
});
|
|
66691
67186
|
|
|
66692
67187
|
// src/tui/constants.ts
|
|
@@ -73026,12 +73521,12 @@ import {
|
|
|
73026
73521
|
existsSync as existsSync24,
|
|
73027
73522
|
mkdirSync as mkdirSync16,
|
|
73028
73523
|
openSync as openSync5,
|
|
73029
|
-
readFileSync as
|
|
73524
|
+
readFileSync as readFileSync24,
|
|
73030
73525
|
unlinkSync as unlinkSync9,
|
|
73031
73526
|
writeFileSync as writeFileSync18
|
|
73032
73527
|
} from "fs";
|
|
73033
|
-
import { homedir as
|
|
73034
|
-
import { join as
|
|
73528
|
+
import { homedir as homedir28, tmpdir as tmpdir2 } from "os";
|
|
73529
|
+
import { join as join30 } from "path";
|
|
73035
73530
|
import { isatty } from "tty";
|
|
73036
73531
|
function releaseTerminalIsolation() {
|
|
73037
73532
|
if (!restoreTerminal)
|
|
@@ -73066,14 +73561,14 @@ function isProxyAuthMode(config3) {
|
|
|
73066
73561
|
}
|
|
73067
73562
|
function managedSettingsPath() {
|
|
73068
73563
|
if (isWindows2()) {
|
|
73069
|
-
return
|
|
73564
|
+
return join30(process.env.PROGRAMDATA || "C:\\ProgramData", "ClaudeCode", "managed-settings.json");
|
|
73070
73565
|
}
|
|
73071
73566
|
if (process.platform === "darwin") {
|
|
73072
73567
|
return "/Library/Application Support/ClaudeCode/managed-settings.json";
|
|
73073
73568
|
}
|
|
73074
73569
|
return "/etc/claude-code/managed-settings.json";
|
|
73075
73570
|
}
|
|
73076
|
-
function managedSettingsForcesClaudeAi(readFile =
|
|
73571
|
+
function managedSettingsForcesClaudeAi(readFile = readFileSync24) {
|
|
73077
73572
|
try {
|
|
73078
73573
|
const raw2 = readFile(managedSettingsPath(), "utf-8");
|
|
73079
73574
|
const parsed = JSON.parse(raw2);
|
|
@@ -73087,9 +73582,9 @@ function isWindows2() {
|
|
|
73087
73582
|
}
|
|
73088
73583
|
function createStatusLineScript(tokenFilePath) {
|
|
73089
73584
|
const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
|
|
73090
|
-
const claudishDir =
|
|
73585
|
+
const claudishDir = join30(homeDir, ".claudish");
|
|
73091
73586
|
const timestamp = Date.now();
|
|
73092
|
-
const scriptPath =
|
|
73587
|
+
const scriptPath = join30(claudishDir, `status-${timestamp}.js`);
|
|
73093
73588
|
const escapedTokenPath = tokenFilePath.replace(/\\/g, "\\\\");
|
|
73094
73589
|
const script = `
|
|
73095
73590
|
const fs = require('fs');
|
|
@@ -73212,13 +73707,13 @@ process.stdin.on('end', () => {
|
|
|
73212
73707
|
}
|
|
73213
73708
|
function createTempSettingsFile(_modelDisplay, port, proxyAuthMode) {
|
|
73214
73709
|
const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
|
|
73215
|
-
const claudishDir =
|
|
73710
|
+
const claudishDir = join30(homeDir, ".claudish");
|
|
73216
73711
|
try {
|
|
73217
73712
|
mkdirSync16(claudishDir, { recursive: true });
|
|
73218
73713
|
} catch {}
|
|
73219
73714
|
const timestamp = Date.now();
|
|
73220
|
-
const tempPath =
|
|
73221
|
-
const tokenFilePath =
|
|
73715
|
+
const tempPath = join30(claudishDir, `settings-${timestamp}.json`);
|
|
73716
|
+
const tokenFilePath = join30(claudishDir, `tokens-${port}.json`);
|
|
73222
73717
|
let statusCommand;
|
|
73223
73718
|
if (isWindows2()) {
|
|
73224
73719
|
const scriptPath = createStatusLineScript(tokenFilePath);
|
|
@@ -73262,7 +73757,7 @@ function mergeUserSettingsIfPresent(config3, tempSettingsPath, statusLine, proxy
|
|
|
73262
73757
|
if (userSettingsValue.trimStart().startsWith("{")) {
|
|
73263
73758
|
userSettings = JSON.parse(userSettingsValue);
|
|
73264
73759
|
} else {
|
|
73265
|
-
const rawUserSettings =
|
|
73760
|
+
const rawUserSettings = readFileSync24(userSettingsValue, "utf-8");
|
|
73266
73761
|
userSettings = JSON.parse(rawUserSettings);
|
|
73267
73762
|
}
|
|
73268
73763
|
userSettings.statusLine = statusLine;
|
|
@@ -73433,8 +73928,8 @@ async function runClaudeWithProxy(config3, proxyUrl, onCleanup) {
|
|
|
73433
73928
|
console.error("Install it from: https://claude.com/claude-code");
|
|
73434
73929
|
console.error(`
|
|
73435
73930
|
Or set CLAUDE_PATH to your custom installation:`);
|
|
73436
|
-
const home =
|
|
73437
|
-
const localPath = isWindows2() ?
|
|
73931
|
+
const home = homedir28();
|
|
73932
|
+
const localPath = isWindows2() ? join30(home, ".claude", "local", "claude.exe") : join30(home, ".claude", "local", "claude");
|
|
73438
73933
|
console.error(` export CLAUDE_PATH=${localPath}`);
|
|
73439
73934
|
process.exit(1);
|
|
73440
73935
|
}
|
|
@@ -73518,16 +74013,16 @@ async function findClaudeBinary() {
|
|
|
73518
74013
|
return process.env.CLAUDE_PATH;
|
|
73519
74014
|
}
|
|
73520
74015
|
}
|
|
73521
|
-
const home =
|
|
73522
|
-
const localPath = isWindows3 ?
|
|
74016
|
+
const home = homedir28();
|
|
74017
|
+
const localPath = isWindows3 ? join30(home, ".claude", "local", "claude.exe") : join30(home, ".claude", "local", "claude");
|
|
73523
74018
|
if (existsSync24(localPath)) {
|
|
73524
74019
|
return localPath;
|
|
73525
74020
|
}
|
|
73526
74021
|
if (isWindows3) {
|
|
73527
74022
|
const windowsPaths = [
|
|
73528
|
-
|
|
73529
|
-
|
|
73530
|
-
|
|
74023
|
+
join30(home, "AppData", "Roaming", "npm", "claude.cmd"),
|
|
74024
|
+
join30(home, ".npm-global", "claude.cmd"),
|
|
74025
|
+
join30(home, "node_modules", ".bin", "claude.cmd")
|
|
73531
74026
|
];
|
|
73532
74027
|
for (const path2 of windowsPaths) {
|
|
73533
74028
|
if (existsSync24(path2)) {
|
|
@@ -73538,11 +74033,11 @@ async function findClaudeBinary() {
|
|
|
73538
74033
|
const commonPaths = [
|
|
73539
74034
|
"/usr/local/bin/claude",
|
|
73540
74035
|
"/opt/homebrew/bin/claude",
|
|
73541
|
-
|
|
73542
|
-
|
|
73543
|
-
|
|
74036
|
+
join30(home, ".npm-global/bin/claude"),
|
|
74037
|
+
join30(home, ".local/bin/claude"),
|
|
74038
|
+
join30(home, "node_modules/.bin/claude"),
|
|
73544
74039
|
"/data/data/com.termux/files/usr/bin/claude",
|
|
73545
|
-
|
|
74040
|
+
join30(home, "../usr/bin/claude")
|
|
73546
74041
|
];
|
|
73547
74042
|
for (const path2 of commonPaths) {
|
|
73548
74043
|
if (existsSync24(path2)) {
|
|
@@ -73603,17 +74098,17 @@ __export(exports_diag_output, {
|
|
|
73603
74098
|
LogFileDiagOutput: () => LogFileDiagOutput
|
|
73604
74099
|
});
|
|
73605
74100
|
import { createWriteStream as createWriteStream3, mkdirSync as mkdirSync17, unlinkSync as unlinkSync10, writeFileSync as writeFileSync19 } from "fs";
|
|
73606
|
-
import { homedir as
|
|
73607
|
-
import { join as
|
|
74101
|
+
import { homedir as homedir29 } from "os";
|
|
74102
|
+
import { join as join31 } from "path";
|
|
73608
74103
|
function getClaudishDir() {
|
|
73609
|
-
const dir =
|
|
74104
|
+
const dir = join31(homedir29(), ".claudish");
|
|
73610
74105
|
try {
|
|
73611
74106
|
mkdirSync17(dir, { recursive: true });
|
|
73612
74107
|
} catch {}
|
|
73613
74108
|
return dir;
|
|
73614
74109
|
}
|
|
73615
74110
|
function getDiagLogPath() {
|
|
73616
|
-
return
|
|
74111
|
+
return join31(getClaudishDir(), `diag-${process.pid}.log`);
|
|
73617
74112
|
}
|
|
73618
74113
|
|
|
73619
74114
|
class LogFileDiagOutput {
|
|
@@ -73824,9 +74319,9 @@ __export(exports_team_grid, {
|
|
|
73824
74319
|
});
|
|
73825
74320
|
import { spawn as spawn5 } from "child_process";
|
|
73826
74321
|
import { execSync as execSync2 } from "child_process";
|
|
73827
|
-
import { existsSync as existsSync25, readFileSync as
|
|
74322
|
+
import { existsSync as existsSync25, readFileSync as readFileSync25, writeFileSync as writeFileSync20 } from "fs";
|
|
73828
74323
|
import { connect as netConnect } from "net";
|
|
73829
|
-
import { dirname as
|
|
74324
|
+
import { dirname as dirname11, join as join32 } from "path";
|
|
73830
74325
|
import { setTimeout as wait } from "timers/promises";
|
|
73831
74326
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
73832
74327
|
function resolveRouteInfo(modelId) {
|
|
@@ -73919,21 +74414,21 @@ function buildPaneHeader(model, prompt, bg) {
|
|
|
73919
74414
|
}
|
|
73920
74415
|
function findMagmuxBinary() {
|
|
73921
74416
|
const thisFile = fileURLToPath3(import.meta.url);
|
|
73922
|
-
const thisDir =
|
|
73923
|
-
const pkgRoot =
|
|
74417
|
+
const thisDir = dirname11(thisFile);
|
|
74418
|
+
const pkgRoot = join32(thisDir, "..");
|
|
73924
74419
|
const platform3 = process.platform;
|
|
73925
74420
|
const arch = process.arch;
|
|
73926
|
-
const bundledMagmux =
|
|
74421
|
+
const bundledMagmux = join32(pkgRoot, "native", `magmux-${platform3}-${arch}`);
|
|
73927
74422
|
if (existsSync25(bundledMagmux))
|
|
73928
74423
|
return bundledMagmux;
|
|
73929
74424
|
try {
|
|
73930
74425
|
const pkgName = `@claudish/magmux-${platform3}-${arch}`;
|
|
73931
74426
|
let searchDir = pkgRoot;
|
|
73932
74427
|
for (let i = 0;i < 5; i++) {
|
|
73933
|
-
const candidate =
|
|
74428
|
+
const candidate = join32(searchDir, "node_modules", pkgName, "bin", "magmux");
|
|
73934
74429
|
if (existsSync25(candidate))
|
|
73935
74430
|
return candidate;
|
|
73936
|
-
const parent =
|
|
74431
|
+
const parent = dirname11(searchDir);
|
|
73937
74432
|
if (parent === searchDir)
|
|
73938
74433
|
break;
|
|
73939
74434
|
searchDir = parent;
|
|
@@ -74037,9 +74532,9 @@ async function runWithGrid(sessionPath, models, input, opts) {
|
|
|
74037
74532
|
const keep = opts?.keep ?? false;
|
|
74038
74533
|
const manifest = setupSession(sessionPath, models, input);
|
|
74039
74534
|
const startedAt = new Date().toISOString();
|
|
74040
|
-
const gridfilePath =
|
|
74041
|
-
const prompt =
|
|
74042
|
-
const rawPrompt =
|
|
74535
|
+
const gridfilePath = join32(sessionPath, "gridfile.txt");
|
|
74536
|
+
const prompt = readFileSync25(join32(sessionPath, "input.md"), "utf-8").replace(/'/g, "'\\''").replace(/\n/g, " ");
|
|
74537
|
+
const rawPrompt = readFileSync25(join32(sessionPath, "input.md"), "utf-8");
|
|
74043
74538
|
const usedBannerColors = new Set;
|
|
74044
74539
|
const gridLines = Object.entries(manifest.models).map(([anonId]) => {
|
|
74045
74540
|
const model = manifest.models[anonId].model;
|
|
@@ -74070,7 +74565,7 @@ async function runWithGrid(sessionPath, models, input, opts) {
|
|
|
74070
74565
|
});
|
|
74071
74566
|
const [{ results }] = await Promise.all([subscription, procExit]);
|
|
74072
74567
|
const status = buildTeamStatus(manifest, startedAt, results?.panes ?? null);
|
|
74073
|
-
const statusPath =
|
|
74568
|
+
const statusPath = join32(sessionPath, "status.json");
|
|
74074
74569
|
writeFileSync20(statusPath, JSON.stringify(status, null, 2), "utf-8");
|
|
74075
74570
|
return status;
|
|
74076
74571
|
}
|
|
@@ -74094,8 +74589,8 @@ var init_team_grid = __esm(() => {
|
|
|
74094
74589
|
init_op_source();
|
|
74095
74590
|
init_startup_trace();
|
|
74096
74591
|
var import_dotenv3 = __toESM(require_main(), 1);
|
|
74097
|
-
import { existsSync as existsSync26, readFileSync as
|
|
74098
|
-
import { join as
|
|
74592
|
+
import { existsSync as existsSync26, readFileSync as readFileSync26 } from "fs";
|
|
74593
|
+
import { join as join33, resolve as resolve4 } from "path";
|
|
74099
74594
|
import_dotenv3.config({ quiet: true });
|
|
74100
74595
|
function classifyStartupKind() {
|
|
74101
74596
|
const argv = process.argv.slice(2);
|
|
@@ -74228,6 +74723,7 @@ var isStatsCommand = firstPositional === "stats";
|
|
|
74228
74723
|
var isConfigCommand = firstPositional === "config";
|
|
74229
74724
|
var isServeCommand = firstPositional === "serve";
|
|
74230
74725
|
var isProvidersCommand = firstPositional === "providers";
|
|
74726
|
+
var isBehaviorCommand = firstPositional === "behavior";
|
|
74231
74727
|
var isLoginCommand = firstPositional === "login";
|
|
74232
74728
|
var isLogoutCommand = firstPositional === "logout";
|
|
74233
74729
|
var isQuotaCommand = firstPositional === "quota" || firstPositional === "usage";
|
|
@@ -74243,6 +74739,12 @@ if (isMcpMode) {
|
|
|
74243
74739
|
console.error(`[claudish serve] ${e instanceof Error ? e.message : String(e)}`);
|
|
74244
74740
|
process.exit(1);
|
|
74245
74741
|
}));
|
|
74742
|
+
} else if (isBehaviorCommand) {
|
|
74743
|
+
const behaviorArgIndex = args.indexOf("behavior");
|
|
74744
|
+
Promise.resolve().then(() => (init_behavior_command(), exports_behavior_command)).then((m) => m.behaviorCommand(args.slice(behaviorArgIndex + 1)).catch((e) => {
|
|
74745
|
+
console.error(`[claudish behavior] ${e instanceof Error ? e.message : String(e)}`);
|
|
74746
|
+
process.exit(1);
|
|
74747
|
+
}));
|
|
74246
74748
|
} else if (isProvidersCommand) {
|
|
74247
74749
|
const json2 = args.includes("--json");
|
|
74248
74750
|
Promise.resolve().then(() => (init_providers_command(), exports_providers_command)).then((m) => m.providersCommand({ json: json2 }).catch((e) => {
|
|
@@ -74329,14 +74831,14 @@ async function runCli() {
|
|
|
74329
74831
|
if (cliConfig.team && cliConfig.team.length > 0) {
|
|
74330
74832
|
let prompt = cliConfig.claudeArgs.join(" ");
|
|
74331
74833
|
if (cliConfig.inputFile) {
|
|
74332
|
-
prompt =
|
|
74834
|
+
prompt = readFileSync26(cliConfig.inputFile, "utf-8");
|
|
74333
74835
|
}
|
|
74334
74836
|
if (!prompt.trim()) {
|
|
74335
74837
|
console.error("Error: --team requires a prompt (positional args or -f <file>)");
|
|
74336
74838
|
process.exit(1);
|
|
74337
74839
|
}
|
|
74338
74840
|
const mode = cliConfig.teamMode ?? "default";
|
|
74339
|
-
const sessionPath =
|
|
74841
|
+
const sessionPath = join33(process.cwd(), `.claudish-team-${Date.now()}`);
|
|
74340
74842
|
if (mode === "json") {
|
|
74341
74843
|
const { setupSession: setupSession2, runModels: runModels2 } = await Promise.resolve().then(() => (init_team_orchestrator(), exports_team_orchestrator));
|
|
74342
74844
|
setupSession2(sessionPath, cliConfig.team, prompt);
|
|
@@ -74346,9 +74848,9 @@ async function runCli() {
|
|
|
74346
74848
|
});
|
|
74347
74849
|
const result = { ...status2, responses: {} };
|
|
74348
74850
|
for (const anonId of Object.keys(status2.models)) {
|
|
74349
|
-
const responsePath =
|
|
74851
|
+
const responsePath = join33(sessionPath, `response-${anonId}.md`);
|
|
74350
74852
|
try {
|
|
74351
|
-
const raw2 =
|
|
74853
|
+
const raw2 = readFileSync26(responsePath, "utf-8").trim();
|
|
74352
74854
|
try {
|
|
74353
74855
|
result.responses[anonId] = JSON.parse(raw2);
|
|
74354
74856
|
} catch {
|