@rely-ai/caliber 1.5.6 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/bin.js +398 -895
  2. package/package.json +1 -1
package/dist/bin.js CHANGED
@@ -51,17 +51,17 @@ var init_constants = __esm({
51
51
 
52
52
  // src/cli.ts
53
53
  import { Command } from "commander";
54
- import fs28 from "fs";
55
- import path22 from "path";
54
+ import fs27 from "fs";
55
+ import path21 from "path";
56
56
  import { fileURLToPath } from "url";
57
57
 
58
58
  // src/commands/onboard.ts
59
- import chalk7 from "chalk";
60
- import ora3 from "ora";
61
- import readline4 from "readline";
59
+ import chalk6 from "chalk";
60
+ import ora2 from "ora";
61
+ import readline3 from "readline";
62
62
  import select4 from "@inquirer/select";
63
63
  import checkbox from "@inquirer/checkbox";
64
- import fs22 from "fs";
64
+ import fs21 from "fs";
65
65
 
66
66
  // src/fingerprint/index.ts
67
67
  import fs6 from "fs";
@@ -520,6 +520,11 @@ var DEFAULT_MODELS = {
520
520
  cursor: "default",
521
521
  "claude-cli": "default"
522
522
  };
523
+ var DEFAULT_FAST_MODELS = {
524
+ anthropic: "claude-haiku-4-5-20251001",
525
+ vertex: "claude-haiku-4-5-20251001",
526
+ openai: "gpt-4.1-mini"
527
+ };
523
528
  function loadConfig() {
524
529
  const envConfig = resolveFromEnv();
525
530
  if (envConfig) return envConfig;
@@ -591,7 +596,12 @@ function getConfigFilePath() {
591
596
  return CONFIG_FILE;
592
597
  }
593
598
  function getFastModel() {
594
- return process.env.CALIBER_FAST_MODEL || process.env.ANTHROPIC_SMALL_FAST_MODEL || void 0;
599
+ if (process.env.CALIBER_FAST_MODEL) return process.env.CALIBER_FAST_MODEL;
600
+ if (process.env.ANTHROPIC_SMALL_FAST_MODEL) return process.env.ANTHROPIC_SMALL_FAST_MODEL;
601
+ const config = loadConfig();
602
+ if (config?.fastModel) return config.fastModel;
603
+ if (config?.provider) return DEFAULT_FAST_MODELS[config.provider];
604
+ return void 0;
595
605
  }
596
606
 
597
607
  // src/llm/anthropic.ts
@@ -3006,15 +3016,15 @@ function computeGrade(score) {
3006
3016
  // src/scoring/checks/coverage.ts
3007
3017
  import { readFileSync, readdirSync } from "fs";
3008
3018
  import { join } from "path";
3009
- function readFileOrNull(path24) {
3019
+ function readFileOrNull(path23) {
3010
3020
  try {
3011
- return readFileSync(path24, "utf-8");
3021
+ return readFileSync(path23, "utf-8");
3012
3022
  } catch {
3013
3023
  return null;
3014
3024
  }
3015
3025
  }
3016
- function readJsonOrNull(path24) {
3017
- const content = readFileOrNull(path24);
3026
+ function readJsonOrNull(path23) {
3027
+ const content = readFileOrNull(path23);
3018
3028
  if (!content) return null;
3019
3029
  try {
3020
3030
  return JSON.parse(content);
@@ -3382,9 +3392,9 @@ function checkExistence(dir) {
3382
3392
  // src/scoring/checks/quality.ts
3383
3393
  import { readFileSync as readFileSync3 } from "fs";
3384
3394
  import { join as join3 } from "path";
3385
- function readFileOrNull2(path24) {
3395
+ function readFileOrNull2(path23) {
3386
3396
  try {
3387
- return readFileSync3(path24, "utf-8");
3397
+ return readFileSync3(path23, "utf-8");
3388
3398
  } catch {
3389
3399
  return null;
3390
3400
  }
@@ -3537,15 +3547,15 @@ function checkQuality(dir) {
3537
3547
  // src/scoring/checks/accuracy.ts
3538
3548
  import { existsSync as existsSync5, readFileSync as readFileSync4, readdirSync as readdirSync3, statSync } from "fs";
3539
3549
  import { join as join4 } from "path";
3540
- function readFileOrNull3(path24) {
3550
+ function readFileOrNull3(path23) {
3541
3551
  try {
3542
- return readFileSync4(path24, "utf-8");
3552
+ return readFileSync4(path23, "utf-8");
3543
3553
  } catch {
3544
3554
  return null;
3545
3555
  }
3546
3556
  }
3547
- function readJsonOrNull2(path24) {
3548
- const content = readFileOrNull3(path24);
3557
+ function readJsonOrNull2(path23) {
3558
+ const content = readFileOrNull3(path23);
3549
3559
  if (!content) return null;
3550
3560
  try {
3551
3561
  return JSON.parse(content);
@@ -3728,9 +3738,9 @@ function checkAccuracy(dir) {
3728
3738
  // src/scoring/checks/freshness.ts
3729
3739
  import { existsSync as existsSync6, readFileSync as readFileSync5, statSync as statSync2 } from "fs";
3730
3740
  import { join as join5 } from "path";
3731
- function readFileOrNull4(path24) {
3741
+ function readFileOrNull4(path23) {
3732
3742
  try {
3733
- return readFileSync5(path24, "utf-8");
3743
+ return readFileSync5(path23, "utf-8");
3734
3744
  } catch {
3735
3745
  return null;
3736
3746
  }
@@ -3844,9 +3854,9 @@ function checkFreshness(dir) {
3844
3854
  import { existsSync as existsSync7, readFileSync as readFileSync6, readdirSync as readdirSync4 } from "fs";
3845
3855
  import { execSync as execSync7 } from "child_process";
3846
3856
  import { join as join6 } from "path";
3847
- function readFileOrNull5(path24) {
3857
+ function readFileOrNull5(path23) {
3848
3858
  try {
3849
- return readFileSync6(path24, "utf-8");
3859
+ return readFileSync6(path23, "utf-8");
3850
3860
  } catch {
3851
3861
  return null;
3852
3862
  }
@@ -4143,513 +4153,21 @@ function displayScoreDelta(before, after) {
4143
4153
  }
4144
4154
  }
4145
4155
 
4146
- // src/mcp/index.ts
4156
+ // src/commands/recommend.ts
4147
4157
  import chalk5 from "chalk";
4148
4158
  import ora from "ora";
4149
- import readline3 from "readline";
4150
- import fs20 from "fs";
4151
- import path16 from "path";
4152
-
4153
- // src/mcp/search.ts
4154
- var AWESOME_MCP_URL = "https://raw.githubusercontent.com/punkpeye/awesome-mcp-servers/main/README.md";
4155
- var GITHUB_SEARCH_URL = "https://github.com/search";
4156
- var SEARCH_HEADERS = {
4157
- "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
4158
- "Accept": "text/html"
4159
- };
4160
- function parseGitHubSearchHtml(html) {
4161
- try {
4162
- const scriptMatch = html.match(/<script type="application\/json" data-target="react-app\.embeddedData">([\s\S]*?)<\/script>/);
4163
- if (!scriptMatch) {
4164
- return [];
4165
- }
4166
- const data = JSON.parse(scriptMatch[1]);
4167
- const results = data?.payload?.results;
4168
- if (!Array.isArray(results)) {
4169
- return [];
4170
- }
4171
- return results.map((r) => {
4172
- const repo = r.repo?.repository;
4173
- const ownerLogin = repo?.owner_login || "";
4174
- const name = repo?.name || "";
4175
- const description = typeof r.hl_trunc_description === "string" ? r.hl_trunc_description.replace(/<\/?em>/g, "") : null;
4176
- return {
4177
- full_name: `${ownerLogin}/${name}`,
4178
- description,
4179
- stargazers_count: typeof r.followers === "number" ? r.followers : 0,
4180
- pushed_at: repo?.updated_at || "",
4181
- owner_login: ownerLogin
4182
- };
4183
- });
4184
- } catch {
4185
- return [];
4186
- }
4187
- }
4188
- async function searchAllMcpSources(toolDeps) {
4189
- if (toolDeps.length === 0) return [];
4190
- const searches = [
4191
- searchAwesomeMcpLists(toolDeps),
4192
- ...toolDeps.map((dep) => searchGitHub(dep)),
4193
- ...toolDeps.map((dep) => searchVendorOrg(dep))
4194
- ];
4195
- const results = await Promise.all(searches);
4196
- const seen = /* @__PURE__ */ new Map();
4197
- for (const batch of results) {
4198
- for (const candidate of batch) {
4199
- const key = candidate.repoFullName.toLowerCase();
4200
- const existing = seen.get(key);
4201
- if (!existing || candidate.vendor || candidate.stars > existing.stars) {
4202
- seen.set(key, candidate);
4203
- }
4204
- }
4205
- }
4206
- return Array.from(seen.values());
4207
- }
4208
- async function searchAwesomeMcpLists(toolDeps) {
4209
- try {
4210
- const resp = await fetch(AWESOME_MCP_URL, {
4211
- signal: AbortSignal.timeout(1e4)
4212
- });
4213
- if (!resp.ok) return [];
4214
- const markdown = await resp.text();
4215
- const candidates = [];
4216
- const depLower = toolDeps.map((d) => d.toLowerCase().replace(/^@[^/]+\//, ""));
4217
- const itemPattern = /^[-*]\s+\[([^\]]+)\]\(([^)]+)\)\s*[-–—:]\s*(.*)/gm;
4218
- let match;
4219
- while ((match = itemPattern.exec(markdown)) !== null) {
4220
- const [, name, url, description] = match;
4221
- if (!url.includes("github.com")) continue;
4222
- const text = `${name} ${description}`.toLowerCase();
4223
- const matchedDep = depLower.find((d) => text.includes(d));
4224
- if (!matchedDep) continue;
4225
- const repoMatch = url.match(/github\.com\/([^/]+\/[^/]+)/);
4226
- if (!repoMatch) continue;
4227
- candidates.push({
4228
- name: name.trim(),
4229
- repoFullName: repoMatch[1],
4230
- url: url.trim(),
4231
- description: description.trim().slice(0, 200),
4232
- stars: 0,
4233
- lastPush: "",
4234
- vendor: false,
4235
- score: 0,
4236
- reason: "",
4237
- matchedDep: toolDeps.find((d) => d.toLowerCase().replace(/^@[^/]+\//, "") === matchedDep) || matchedDep
4238
- });
4239
- }
4240
- return candidates;
4241
- } catch {
4242
- return [];
4243
- }
4244
- }
4245
- async function searchGitHub(dep) {
4246
- const depName = dep.replace(/^@[^/]+\//, "");
4247
- try {
4248
- const query = encodeURIComponent(`${depName} mcp server`);
4249
- const url = `${GITHUB_SEARCH_URL}?q=${query}&type=repositories&s=stars&o=desc`;
4250
- const resp = await fetch(url, {
4251
- signal: AbortSignal.timeout(1e4),
4252
- headers: SEARCH_HEADERS
4253
- });
4254
- if (!resp.ok) return [];
4255
- const html = await resp.text();
4256
- const repos = parseGitHubSearchHtml(html).slice(0, 5);
4257
- return repos.map((repo) => ({
4258
- name: repo.full_name.split("/")[1],
4259
- repoFullName: repo.full_name,
4260
- url: `https://github.com/${repo.full_name}`,
4261
- description: repo.description || "",
4262
- stars: repo.stargazers_count,
4263
- lastPush: repo.pushed_at,
4264
- vendor: false,
4265
- score: 0,
4266
- reason: "",
4267
- matchedDep: dep
4268
- }));
4269
- } catch {
4270
- return [];
4271
- }
4272
- }
4273
- async function searchVendorOrg(dep) {
4274
- const depName = dep.replace(/^@([^/]+)\/.*/, "$1").replace(/^@/, "");
4275
- const orgName = depName.toLowerCase();
4276
- try {
4277
- const query = encodeURIComponent(`mcp org:${orgName}`);
4278
- const url = `${GITHUB_SEARCH_URL}?q=${query}&type=repositories&s=stars&o=desc`;
4279
- const resp = await fetch(url, {
4280
- signal: AbortSignal.timeout(1e4),
4281
- headers: SEARCH_HEADERS
4282
- });
4283
- if (!resp.ok) return [];
4284
- const html = await resp.text();
4285
- const repos = parseGitHubSearchHtml(html).slice(0, 5);
4286
- return repos.map((repo) => ({
4287
- name: repo.full_name.split("/")[1],
4288
- repoFullName: repo.full_name,
4289
- url: `https://github.com/${repo.full_name}`,
4290
- description: repo.description || "",
4291
- stars: repo.stargazers_count,
4292
- lastPush: repo.pushed_at,
4293
- vendor: repo.owner_login.toLowerCase() === orgName,
4294
- score: 0,
4295
- reason: "",
4296
- matchedDep: dep
4297
- }));
4298
- } catch {
4299
- return [];
4300
- }
4301
- }
4302
-
4303
- // src/mcp/prompts.ts
4304
- var SCORE_MCP_PROMPT = `You evaluate MCP (Model Context Protocol) server candidates for relevance to a software project.
4305
-
4306
- Score each candidate from 0-100 based on:
4307
- - **Relevance** (40%): How directly does it match the project's detected tool dependencies?
4308
- - **Capabilities** (30%): Does it provide meaningful read+write operations (not just read-only)?
4309
- - **Quality signals** (30%): Stars, recent activity, vendor/official status
4310
-
4311
- Return a JSON array where each element has:
4312
- - "index": the candidate's index number
4313
- - "score": relevance score 0-100
4314
- - "reason": one-liner explaining the score (max 80 chars)
4315
-
4316
- Be selective. Only score candidates that would genuinely help developers working on this project.
4317
- Return ONLY the JSON array.`;
4318
- var EXTRACT_CONFIG_PROMPT = `You extract MCP server configuration from a README file.
4319
-
4320
- Look for the MCP server's configuration block \u2014 typically a JSON snippet showing how to add it to claude_desktop_config.json, .mcp.json, or similar.
4321
-
4322
- Return a JSON object with:
4323
- - "command": the executable command (e.g., "npx", "uvx", "node", "docker")
4324
- - "args": array of arguments (e.g., ["-y", "@supabase/mcp-server"])
4325
- - "env": array of objects, each with:
4326
- - "key": environment variable name (e.g., "SUPABASE_ACCESS_TOKEN")
4327
- - "description": brief description of what this value is (e.g., "Personal access token from dashboard")
4328
- - "required": boolean
4329
-
4330
- If the README shows multiple configuration methods, prefer npx > uvx > node > docker.
4331
- If you cannot determine the configuration, return {"command": "", "args": [], "env": []}.
4332
- Return ONLY the JSON object.`;
4333
-
4334
- // src/mcp/validate.ts
4335
- var MIN_STARS = 100;
4336
- var MAX_AGE_DAYS = 180;
4337
- async function validateAndScore(candidates, toolDeps) {
4338
- const qualityFiltered = candidates.filter((c) => {
4339
- if (c.vendor) return true;
4340
- if (c.stars > 0 && c.stars < MIN_STARS) return false;
4341
- if (c.lastPush) {
4342
- const pushDate = new Date(c.lastPush);
4343
- const daysAgo = (Date.now() - pushDate.getTime()) / (1e3 * 60 * 60 * 24);
4344
- if (daysAgo > MAX_AGE_DAYS) return false;
4345
- }
4346
- return true;
4347
- });
4348
- if (qualityFiltered.length === 0) return [];
4349
- try {
4350
- return await scoreWithLLM(qualityFiltered, toolDeps);
4351
- } catch {
4352
- return qualityFiltered.slice(0, 5).map((c) => ({
4353
- ...c,
4354
- score: 50,
4355
- reason: c.description.slice(0, 80)
4356
- }));
4357
- }
4358
- }
4359
- async function scoreWithLLM(candidates, toolDeps) {
4360
- const candidateList = candidates.map((c, i) => {
4361
- const vendorTag = c.vendor ? " [VENDOR/OFFICIAL]" : "";
4362
- return `${i}. "${c.name}"${vendorTag} (${c.stars} stars) \u2014 ${c.description.slice(0, 100)}`;
4363
- }).join("\n");
4364
- const scored = await llmJsonCall({
4365
- system: SCORE_MCP_PROMPT,
4366
- prompt: `TOOL DEPENDENCIES IN PROJECT:
4367
- ${toolDeps.join(", ")}
4368
-
4369
- MCP SERVER CANDIDATES:
4370
- ${candidateList}`,
4371
- maxTokens: 4e3
4372
- });
4373
- if (!Array.isArray(scored)) return [];
4374
- return scored.filter((s) => s.score >= 60 && s.index >= 0 && s.index < candidates.length).sort((a, b) => b.score - a.score).slice(0, 5).map((s) => ({
4375
- ...candidates[s.index],
4376
- score: s.score,
4377
- reason: s.reason || candidates[s.index].description.slice(0, 80)
4378
- }));
4379
- }
4380
-
4381
- // src/mcp/config-extract.ts
4382
- async function fetchReadme(repoFullName) {
4383
- try {
4384
- const resp = await fetch(
4385
- `https://raw.githubusercontent.com/${repoFullName}/HEAD/README.md`,
4386
- { signal: AbortSignal.timeout(1e4) }
4387
- );
4388
- if (resp.ok) return await resp.text();
4389
- } catch {
4390
- }
4391
- try {
4392
- const resp = await fetch(
4393
- `https://raw.githubusercontent.com/${repoFullName}/main/README.md`,
4394
- { signal: AbortSignal.timeout(1e4) }
4395
- );
4396
- if (resp.ok) return await resp.text();
4397
- } catch {
4398
- }
4399
- return null;
4400
- }
4401
- async function extractMcpConfig(readme, serverName) {
4402
- try {
4403
- const truncated = readme.length > 15e3 ? readme.slice(0, 15e3) : readme;
4404
- const result = await llmJsonCall({
4405
- system: EXTRACT_CONFIG_PROMPT,
4406
- prompt: `MCP Server: ${serverName}
4407
-
4408
- README:
4409
- ${truncated}`,
4410
- maxTokens: 2e3
4411
- });
4412
- if (!result || !result.command) return null;
4413
- return {
4414
- command: result.command,
4415
- args: Array.isArray(result.args) ? result.args : [],
4416
- env: Array.isArray(result.env) ? result.env : []
4417
- };
4418
- } catch {
4419
- return null;
4420
- }
4421
- }
4422
-
4423
- // src/mcp/index.ts
4424
- async function discoverAndInstallMcps(targetAgent, fingerprint, dir) {
4425
- console.log(chalk5.hex("#6366f1").bold("\n MCP Server Discovery\n"));
4426
- const toolDeps = fingerprint.tools;
4427
- if (toolDeps.length === 0) {
4428
- console.log(chalk5.dim(" No external tools or services detected \u2014 skipping MCP discovery"));
4429
- return { installed: 0, names: [] };
4430
- }
4431
- const spinner = ora(`Searching MCP servers for ${toolDeps.length} detected tool${toolDeps.length === 1 ? "" : "s"}...`).start();
4432
- console.log(chalk5.dim(` Detected: ${toolDeps.join(", ")}`));
4433
- const existingMcps = getExistingMcpNames(fingerprint, targetAgent);
4434
- const filteredDeps = toolDeps.filter((d) => {
4435
- const lower = d.toLowerCase();
4436
- return !existingMcps.some((name) => name.includes(lower) || lower.includes(name));
4437
- });
4438
- if (filteredDeps.length === 0) {
4439
- spinner.succeed(chalk5.dim("All detected tools already have MCP servers configured"));
4440
- return { installed: 0, names: [] };
4441
- }
4442
- const candidates = await searchAllMcpSources(filteredDeps);
4443
- if (candidates.length === 0) {
4444
- spinner.succeed(chalk5.dim("No MCP servers found for detected tools"));
4445
- return { installed: 0, names: [] };
4446
- }
4447
- spinner.succeed(`Found ${candidates.length} candidate${candidates.length === 1 ? "" : "s"} for ${filteredDeps.join(", ")}`);
4448
- const scoreSpinner = ora("Scoring MCP candidates...").start();
4449
- const scored = await validateAndScore(candidates, filteredDeps);
4450
- if (scored.length === 0) {
4451
- scoreSpinner.succeed(chalk5.dim("No quality MCP servers passed validation"));
4452
- console.log(chalk5.dim(` Candidates checked: ${candidates.map((c) => c.name).join(", ")}`));
4453
- return { installed: 0, names: [] };
4454
- }
4455
- scoreSpinner.succeed(`${scored.length} quality MCP server${scored.length === 1 ? "" : "s"} found`);
4456
- console.log(chalk5.dim(` Scored: ${scored.map((c) => `${c.name} (${c.score})`).join(", ")}`));
4457
- const selected = await interactiveSelect(scored);
4458
- if (!selected || selected.length === 0) {
4459
- return { installed: 0, names: [] };
4460
- }
4461
- const mcpServers = {};
4462
- const installedNames = [];
4463
- for (const mcp of selected) {
4464
- console.log(chalk5.bold(`
4465
- Configuring ${mcp.name}...`));
4466
- const readme = await fetchReadme(mcp.repoFullName);
4467
- if (!readme) {
4468
- console.log(chalk5.yellow(` Could not fetch README for ${mcp.repoFullName} \u2014 skipping`));
4469
- console.log(chalk5.dim(` Manual setup: ${mcp.url}`));
4470
- continue;
4471
- }
4472
- const config = await extractMcpConfig(readme, mcp.name);
4473
- if (!config || !config.command) {
4474
- console.log(chalk5.yellow(` Could not extract config for ${mcp.name} \u2014 skipping`));
4475
- console.log(chalk5.dim(` Manual setup: ${mcp.url}`));
4476
- continue;
4477
- }
4478
- const env = {};
4479
- for (const envVar of config.env) {
4480
- if (!envVar.required) continue;
4481
- const value = await promptInput2(` ? ${envVar.key} (${envVar.description})`);
4482
- if (value) {
4483
- env[envVar.key] = value;
4484
- }
4485
- }
4486
- const serverConfig = {
4487
- command: config.command
4488
- };
4489
- if (config.args.length > 0) serverConfig.args = config.args;
4490
- if (Object.keys(env).length > 0) serverConfig.env = env;
4491
- mcpServers[mcp.name] = serverConfig;
4492
- installedNames.push(mcp.name);
4493
- console.log(` ${chalk5.green("\u2713")} ${mcp.name} configured`);
4494
- }
4495
- if (installedNames.length === 0) {
4496
- return { installed: 0, names: [] };
4497
- }
4498
- if (targetAgent.includes("claude") || targetAgent.includes("codex")) {
4499
- writeMcpJson(path16.join(dir, ".mcp.json"), mcpServers);
4500
- }
4501
- if (targetAgent.includes("cursor")) {
4502
- const cursorDir = path16.join(dir, ".cursor");
4503
- if (!fs20.existsSync(cursorDir)) fs20.mkdirSync(cursorDir, { recursive: true });
4504
- writeMcpJson(path16.join(cursorDir, "mcp.json"), mcpServers);
4505
- }
4506
- return { installed: installedNames.length, names: installedNames };
4507
- }
4508
- function writeMcpJson(filePath, mcpServers) {
4509
- let existing = {};
4510
- try {
4511
- if (fs20.existsSync(filePath)) {
4512
- const parsed = JSON.parse(fs20.readFileSync(filePath, "utf-8"));
4513
- if (parsed.mcpServers) existing = parsed.mcpServers;
4514
- }
4515
- } catch {
4516
- }
4517
- const merged = { ...existing, ...mcpServers };
4518
- fs20.writeFileSync(filePath, JSON.stringify({ mcpServers: merged }, null, 2) + "\n");
4519
- }
4520
- function getExistingMcpNames(fingerprint, targetAgent) {
4521
- const names = [];
4522
- if (targetAgent.includes("claude")) {
4523
- if (fingerprint.existingConfigs.claudeMcpServers) {
4524
- names.push(...Object.keys(fingerprint.existingConfigs.claudeMcpServers).map((k) => k.toLowerCase()));
4525
- }
4526
- }
4527
- if (targetAgent.includes("cursor")) {
4528
- if (fingerprint.existingConfigs.cursorMcpServers) {
4529
- names.push(...Object.keys(fingerprint.existingConfigs.cursorMcpServers).map((k) => k.toLowerCase()));
4530
- }
4531
- }
4532
- return names;
4533
- }
4534
- function promptInput2(question) {
4535
- const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
4536
- return new Promise((resolve2) => {
4537
- rl.question(chalk5.cyan(`${question}: `), (answer) => {
4538
- rl.close();
4539
- resolve2(answer.trim());
4540
- });
4541
- });
4542
- }
4543
- async function interactiveSelect(candidates) {
4544
- if (!process.stdin.isTTY) {
4545
- console.log(chalk5.bold("\n Available MCP servers:\n"));
4546
- for (const c of candidates) {
4547
- const vendorTag = c.vendor ? chalk5.blue(" (vendor)") : "";
4548
- console.log(` ${String(c.score).padStart(3)} ${c.name}${vendorTag} ${chalk5.dim(c.reason)}`);
4549
- }
4550
- console.log("");
4551
- return null;
4552
- }
4553
- const selected = /* @__PURE__ */ new Set();
4554
- let cursor = 0;
4555
- const { stdin, stdout } = process;
4556
- let lineCount = 0;
4557
- function render() {
4558
- const lines = [];
4559
- lines.push(chalk5.bold(" Select MCP servers to install:"));
4560
- lines.push("");
4561
- for (let i = 0; i < candidates.length; i++) {
4562
- const c = candidates[i];
4563
- const check = selected.has(i) ? chalk5.green("[x]") : "[ ]";
4564
- const ptr = i === cursor ? chalk5.cyan(">") : " ";
4565
- const scoreColor = c.score >= 90 ? chalk5.green : c.score >= 70 ? chalk5.yellow : chalk5.dim;
4566
- const vendorTag = c.vendor ? chalk5.blue(" (vendor)") : "";
4567
- lines.push(` ${ptr} ${check} ${scoreColor(String(c.score).padStart(3))} ${c.name}${vendorTag} ${chalk5.dim(c.reason.slice(0, 40))}`);
4568
- }
4569
- lines.push("");
4570
- lines.push(chalk5.dim(" \u2191\u2193 navigate \u23B5 toggle a all n none \u23CE install q skip"));
4571
- return lines.join("\n");
4572
- }
4573
- function draw(initial) {
4574
- if (!initial && lineCount > 0) {
4575
- stdout.write(`\x1B[${lineCount}A`);
4576
- }
4577
- stdout.write("\x1B[0J");
4578
- const output = render();
4579
- stdout.write(output + "\n");
4580
- lineCount = output.split("\n").length;
4581
- }
4582
- return new Promise((resolve2) => {
4583
- console.log("");
4584
- draw(true);
4585
- stdin.setRawMode(true);
4586
- stdin.resume();
4587
- stdin.setEncoding("utf8");
4588
- function cleanup() {
4589
- stdin.removeListener("data", onData);
4590
- stdin.setRawMode(false);
4591
- stdin.pause();
4592
- }
4593
- function onData(key) {
4594
- switch (key) {
4595
- case "\x1B[A":
4596
- cursor = (cursor - 1 + candidates.length) % candidates.length;
4597
- draw(false);
4598
- break;
4599
- case "\x1B[B":
4600
- cursor = (cursor + 1) % candidates.length;
4601
- draw(false);
4602
- break;
4603
- case " ":
4604
- selected.has(cursor) ? selected.delete(cursor) : selected.add(cursor);
4605
- draw(false);
4606
- break;
4607
- case "a":
4608
- candidates.forEach((_, i) => selected.add(i));
4609
- draw(false);
4610
- break;
4611
- case "n":
4612
- selected.clear();
4613
- draw(false);
4614
- break;
4615
- case "\r":
4616
- case "\n":
4617
- cleanup();
4618
- if (selected.size === 0) {
4619
- console.log(chalk5.dim("\n No MCP servers selected.\n"));
4620
- resolve2(null);
4621
- } else {
4622
- resolve2(Array.from(selected).sort().map((i) => candidates[i]));
4623
- }
4624
- break;
4625
- case "q":
4626
- case "\x1B":
4627
- case "":
4628
- cleanup();
4629
- console.log(chalk5.dim("\n Skipped MCP server installation.\n"));
4630
- resolve2(null);
4631
- break;
4632
- }
4633
- }
4634
- stdin.on("data", onData);
4635
- });
4636
- }
4637
-
4638
- // src/commands/recommend.ts
4639
- import chalk6 from "chalk";
4640
- import ora2 from "ora";
4641
4159
  import select3 from "@inquirer/select";
4642
4160
  import { mkdirSync, readFileSync as readFileSync7, readdirSync as readdirSync5, existsSync as existsSync9, writeFileSync } from "fs";
4643
4161
  import { join as join8, dirname as dirname2 } from "path";
4644
4162
 
4645
4163
  // src/scanner/index.ts
4646
- import fs21 from "fs";
4647
- import path17 from "path";
4164
+ import fs20 from "fs";
4165
+ import path16 from "path";
4648
4166
  import crypto2 from "crypto";
4649
4167
  function scanLocalState(dir) {
4650
4168
  const items = [];
4651
- const claudeMdPath = path17.join(dir, "CLAUDE.md");
4652
- if (fs21.existsSync(claudeMdPath)) {
4169
+ const claudeMdPath = path16.join(dir, "CLAUDE.md");
4170
+ if (fs20.existsSync(claudeMdPath)) {
4653
4171
  items.push({
4654
4172
  type: "rule",
4655
4173
  platform: "claude",
@@ -4658,10 +4176,10 @@ function scanLocalState(dir) {
4658
4176
  path: claudeMdPath
4659
4177
  });
4660
4178
  }
4661
- const skillsDir = path17.join(dir, ".claude", "skills");
4662
- if (fs21.existsSync(skillsDir)) {
4663
- for (const file of fs21.readdirSync(skillsDir).filter((f) => f.endsWith(".md"))) {
4664
- const filePath = path17.join(skillsDir, file);
4179
+ const skillsDir = path16.join(dir, ".claude", "skills");
4180
+ if (fs20.existsSync(skillsDir)) {
4181
+ for (const file of fs20.readdirSync(skillsDir).filter((f) => f.endsWith(".md"))) {
4182
+ const filePath = path16.join(skillsDir, file);
4665
4183
  items.push({
4666
4184
  type: "skill",
4667
4185
  platform: "claude",
@@ -4671,10 +4189,10 @@ function scanLocalState(dir) {
4671
4189
  });
4672
4190
  }
4673
4191
  }
4674
- const mcpJsonPath = path17.join(dir, ".mcp.json");
4675
- if (fs21.existsSync(mcpJsonPath)) {
4192
+ const mcpJsonPath = path16.join(dir, ".mcp.json");
4193
+ if (fs20.existsSync(mcpJsonPath)) {
4676
4194
  try {
4677
- const mcpJson = JSON.parse(fs21.readFileSync(mcpJsonPath, "utf-8"));
4195
+ const mcpJson = JSON.parse(fs20.readFileSync(mcpJsonPath, "utf-8"));
4678
4196
  if (mcpJson.mcpServers) {
4679
4197
  for (const name of Object.keys(mcpJson.mcpServers)) {
4680
4198
  items.push({
@@ -4689,8 +4207,8 @@ function scanLocalState(dir) {
4689
4207
  } catch {
4690
4208
  }
4691
4209
  }
4692
- const agentsMdPath = path17.join(dir, "AGENTS.md");
4693
- if (fs21.existsSync(agentsMdPath)) {
4210
+ const agentsMdPath = path16.join(dir, "AGENTS.md");
4211
+ if (fs20.existsSync(agentsMdPath)) {
4694
4212
  items.push({
4695
4213
  type: "rule",
4696
4214
  platform: "codex",
@@ -4699,12 +4217,12 @@ function scanLocalState(dir) {
4699
4217
  path: agentsMdPath
4700
4218
  });
4701
4219
  }
4702
- const codexSkillsDir = path17.join(dir, ".agents", "skills");
4703
- if (fs21.existsSync(codexSkillsDir)) {
4220
+ const codexSkillsDir = path16.join(dir, ".agents", "skills");
4221
+ if (fs20.existsSync(codexSkillsDir)) {
4704
4222
  try {
4705
- for (const name of fs21.readdirSync(codexSkillsDir)) {
4706
- const skillFile = path17.join(codexSkillsDir, name, "SKILL.md");
4707
- if (fs21.existsSync(skillFile)) {
4223
+ for (const name of fs20.readdirSync(codexSkillsDir)) {
4224
+ const skillFile = path16.join(codexSkillsDir, name, "SKILL.md");
4225
+ if (fs20.existsSync(skillFile)) {
4708
4226
  items.push({
4709
4227
  type: "skill",
4710
4228
  platform: "codex",
@@ -4717,8 +4235,8 @@ function scanLocalState(dir) {
4717
4235
  } catch {
4718
4236
  }
4719
4237
  }
4720
- const cursorrulesPath = path17.join(dir, ".cursorrules");
4721
- if (fs21.existsSync(cursorrulesPath)) {
4238
+ const cursorrulesPath = path16.join(dir, ".cursorrules");
4239
+ if (fs20.existsSync(cursorrulesPath)) {
4722
4240
  items.push({
4723
4241
  type: "rule",
4724
4242
  platform: "cursor",
@@ -4727,10 +4245,10 @@ function scanLocalState(dir) {
4727
4245
  path: cursorrulesPath
4728
4246
  });
4729
4247
  }
4730
- const cursorRulesDir = path17.join(dir, ".cursor", "rules");
4731
- if (fs21.existsSync(cursorRulesDir)) {
4732
- for (const file of fs21.readdirSync(cursorRulesDir).filter((f) => f.endsWith(".mdc"))) {
4733
- const filePath = path17.join(cursorRulesDir, file);
4248
+ const cursorRulesDir = path16.join(dir, ".cursor", "rules");
4249
+ if (fs20.existsSync(cursorRulesDir)) {
4250
+ for (const file of fs20.readdirSync(cursorRulesDir).filter((f) => f.endsWith(".mdc"))) {
4251
+ const filePath = path16.join(cursorRulesDir, file);
4734
4252
  items.push({
4735
4253
  type: "rule",
4736
4254
  platform: "cursor",
@@ -4740,12 +4258,12 @@ function scanLocalState(dir) {
4740
4258
  });
4741
4259
  }
4742
4260
  }
4743
- const cursorSkillsDir = path17.join(dir, ".cursor", "skills");
4744
- if (fs21.existsSync(cursorSkillsDir)) {
4261
+ const cursorSkillsDir = path16.join(dir, ".cursor", "skills");
4262
+ if (fs20.existsSync(cursorSkillsDir)) {
4745
4263
  try {
4746
- for (const name of fs21.readdirSync(cursorSkillsDir)) {
4747
- const skillFile = path17.join(cursorSkillsDir, name, "SKILL.md");
4748
- if (fs21.existsSync(skillFile)) {
4264
+ for (const name of fs20.readdirSync(cursorSkillsDir)) {
4265
+ const skillFile = path16.join(cursorSkillsDir, name, "SKILL.md");
4266
+ if (fs20.existsSync(skillFile)) {
4749
4267
  items.push({
4750
4268
  type: "skill",
4751
4269
  platform: "cursor",
@@ -4758,10 +4276,10 @@ function scanLocalState(dir) {
4758
4276
  } catch {
4759
4277
  }
4760
4278
  }
4761
- const cursorMcpPath = path17.join(dir, ".cursor", "mcp.json");
4762
- if (fs21.existsSync(cursorMcpPath)) {
4279
+ const cursorMcpPath = path16.join(dir, ".cursor", "mcp.json");
4280
+ if (fs20.existsSync(cursorMcpPath)) {
4763
4281
  try {
4764
- const mcpJson = JSON.parse(fs21.readFileSync(cursorMcpPath, "utf-8"));
4282
+ const mcpJson = JSON.parse(fs20.readFileSync(cursorMcpPath, "utf-8"));
4765
4283
  if (mcpJson.mcpServers) {
4766
4284
  for (const name of Object.keys(mcpJson.mcpServers)) {
4767
4285
  items.push({
@@ -4779,7 +4297,7 @@ function scanLocalState(dir) {
4779
4297
  return items;
4780
4298
  }
4781
4299
  function hashFile(filePath) {
4782
- const text = fs21.readFileSync(filePath, "utf-8");
4300
+ const text = fs20.readFileSync(filePath, "utf-8");
4783
4301
  return crypto2.createHash("sha256").update(JSON.stringify({ text })).digest("hex");
4784
4302
  }
4785
4303
  function hashJson(obj) {
@@ -4941,8 +4459,9 @@ async function searchAllProviders(technologies, platform) {
4941
4459
  }
4942
4460
  return combined;
4943
4461
  }
4944
- async function scoreWithLLM2(candidates, projectContext, technologies) {
4462
+ async function scoreWithLLM(candidates, projectContext, technologies) {
4945
4463
  const candidateList = candidates.map((c, i) => `${i}. "${c.name}" \u2014 ${c.reason || "no description"}`).join("\n");
4464
+ const fastModel = getFastModel();
4946
4465
  const scored = await llmJsonCall({
4947
4466
  system: `You evaluate whether AI agent skills and tools are relevant to a specific software project.
4948
4467
  Given a project context and a list of candidates, score each one's relevance from 0-100 and provide a brief reason (max 80 chars).
@@ -4970,7 +4489,8 @@ ${technologies.join(", ")}
4970
4489
 
4971
4490
  CANDIDATES:
4972
4491
  ${candidateList}`,
4973
- maxTokens: 8e3
4492
+ maxTokens: 8e3,
4493
+ ...fastModel ? { model: fastModel } : {}
4974
4494
  });
4975
4495
  if (!Array.isArray(scored)) return [];
4976
4496
  return scored.filter((s) => s.score >= 60 && s.index >= 0 && s.index < candidates.length).sort((a, b) => b.score - a.score).slice(0, 20).map((s) => ({
@@ -5092,7 +4612,7 @@ async function recommendCommand() {
5092
4612
  ]
5093
4613
  });
5094
4614
  if (!proceed) {
5095
- console.log(chalk6.dim(" Cancelled.\n"));
4615
+ console.log(chalk5.dim(" Cancelled.\n"));
5096
4616
  return;
5097
4617
  }
5098
4618
  await searchAndInstallSkills();
@@ -5107,11 +4627,11 @@ async function searchAndInstallSkills() {
5107
4627
  ...extractTopDeps()
5108
4628
  ].filter(Boolean))];
5109
4629
  if (technologies.length === 0) {
5110
- console.log(chalk6.yellow("Could not detect any languages or dependencies. Try running from a project root."));
4630
+ console.log(chalk5.yellow("Could not detect any languages or dependencies. Try running from a project root."));
5111
4631
  throw new Error("__exit__");
5112
4632
  }
5113
4633
  const primaryPlatform = platforms.includes("claude") ? "claude" : platforms[0];
5114
- const searchSpinner = ora2("Searching skill registries...").start();
4634
+ const searchSpinner = ora("Searching skill registries...").start();
5115
4635
  const allCandidates = await searchAllProviders(technologies, primaryPlatform);
5116
4636
  if (!allCandidates.length) {
5117
4637
  searchSpinner.succeed("No skills found matching your tech stack.");
@@ -5124,15 +4644,15 @@ async function searchAndInstallSkills() {
5124
4644
  return;
5125
4645
  }
5126
4646
  searchSpinner.succeed(
5127
- `Found ${allCandidates.length} skills` + (filteredCount > 0 ? chalk6.dim(` (${filteredCount} already installed)`) : "")
4647
+ `Found ${allCandidates.length} skills` + (filteredCount > 0 ? chalk5.dim(` (${filteredCount} already installed)`) : "")
5128
4648
  );
5129
4649
  let results;
5130
4650
  const config = loadConfig();
5131
4651
  if (config) {
5132
- const scoreSpinner = ora2("Scoring relevance for your project...").start();
4652
+ const scoreSpinner = ora("Scoring relevance for your project...").start();
5133
4653
  try {
5134
4654
  const projectContext = buildProjectContext(fingerprint);
5135
- results = await scoreWithLLM2(newCandidates, projectContext, technologies);
4655
+ results = await scoreWithLLM(newCandidates, projectContext, technologies);
5136
4656
  if (results.length === 0) {
5137
4657
  scoreSpinner.succeed("No highly relevant skills found for your specific project.");
5138
4658
  return;
@@ -5145,7 +4665,7 @@ async function searchAndInstallSkills() {
5145
4665
  } else {
5146
4666
  results = newCandidates.slice(0, 20);
5147
4667
  }
5148
- const fetchSpinner = ora2("Verifying skill availability...").start();
4668
+ const fetchSpinner = ora("Verifying skill availability...").start();
5149
4669
  const contentMap = /* @__PURE__ */ new Map();
5150
4670
  await Promise.all(results.map(async (rec) => {
5151
4671
  const content = await fetchSkillContent(rec);
@@ -5158,14 +4678,14 @@ async function searchAndInstallSkills() {
5158
4678
  }
5159
4679
  const unavailableCount = results.length - available.length;
5160
4680
  fetchSpinner.succeed(
5161
- `${available.length} installable skill${available.length > 1 ? "s" : ""}` + (unavailableCount > 0 ? chalk6.dim(` (${unavailableCount} unavailable)`) : "")
4681
+ `${available.length} installable skill${available.length > 1 ? "s" : ""}` + (unavailableCount > 0 ? chalk5.dim(` (${unavailableCount} unavailable)`) : "")
5162
4682
  );
5163
- const selected = await interactiveSelect2(available);
4683
+ const selected = await interactiveSelect(available);
5164
4684
  if (selected?.length) {
5165
4685
  await installSkills(selected, platforms, contentMap);
5166
4686
  }
5167
4687
  }
5168
- async function interactiveSelect2(recs) {
4688
+ async function interactiveSelect(recs) {
5169
4689
  if (!process.stdin.isTTY) {
5170
4690
  printSkills(recs);
5171
4691
  return null;
@@ -5181,30 +4701,30 @@ async function interactiveSelect2(recs) {
5181
4701
  const nameWidth = Math.max(...recs.map((r) => r.name.length), 4) + 2;
5182
4702
  const prefixWidth = 8;
5183
4703
  const scoreWidth = 6;
5184
- lines.push(chalk6.bold(" Skills"));
4704
+ lines.push(chalk5.bold(" Skills"));
5185
4705
  lines.push("");
5186
4706
  if (hasScores) {
5187
- const header = " ".repeat(prefixWidth) + chalk6.dim("Score".padEnd(scoreWidth)) + chalk6.dim("Name".padEnd(nameWidth)) + chalk6.dim("Why");
4707
+ const header = " ".repeat(prefixWidth) + chalk5.dim("Score".padEnd(scoreWidth)) + chalk5.dim("Name".padEnd(nameWidth)) + chalk5.dim("Why");
5188
4708
  lines.push(header);
5189
4709
  } else {
5190
- const header = " ".repeat(prefixWidth) + chalk6.dim("Name".padEnd(nameWidth)) + chalk6.dim("Technology".padEnd(18)) + chalk6.dim("Source");
4710
+ const header = " ".repeat(prefixWidth) + chalk5.dim("Name".padEnd(nameWidth)) + chalk5.dim("Technology".padEnd(18)) + chalk5.dim("Source");
5191
4711
  lines.push(header);
5192
4712
  }
5193
- lines.push(chalk6.dim(" " + "\u2500".repeat(Math.min(cols - 4, 90))));
4713
+ lines.push(chalk5.dim(" " + "\u2500".repeat(Math.min(cols - 4, 90))));
5194
4714
  for (let i = 0; i < recs.length; i++) {
5195
4715
  const rec = recs[i];
5196
- const check = selected.has(i) ? chalk6.green("[x]") : "[ ]";
5197
- const ptr = i === cursor ? chalk6.cyan(">") : " ";
4716
+ const check = selected.has(i) ? chalk5.green("[x]") : "[ ]";
4717
+ const ptr = i === cursor ? chalk5.cyan(">") : " ";
5198
4718
  if (hasScores) {
5199
- const scoreColor = rec.score >= 90 ? chalk6.green : rec.score >= 70 ? chalk6.yellow : chalk6.dim;
4719
+ const scoreColor = rec.score >= 90 ? chalk5.green : rec.score >= 70 ? chalk5.yellow : chalk5.dim;
5200
4720
  const reasonMax = Math.max(cols - prefixWidth - scoreWidth - nameWidth - 2, 20);
5201
- lines.push(` ${ptr} ${check} ${scoreColor(String(rec.score).padStart(3))} ${rec.name.padEnd(nameWidth)}${chalk6.dim(rec.reason.slice(0, reasonMax))}`);
4721
+ lines.push(` ${ptr} ${check} ${scoreColor(String(rec.score).padStart(3))} ${rec.name.padEnd(nameWidth)}${chalk5.dim(rec.reason.slice(0, reasonMax))}`);
5202
4722
  } else {
5203
- lines.push(` ${ptr} ${check} ${rec.name.padEnd(nameWidth)}${rec.detected_technology.padEnd(16)} ${chalk6.dim(rec.source_url || "")}`);
4723
+ lines.push(` ${ptr} ${check} ${rec.name.padEnd(nameWidth)}${rec.detected_technology.padEnd(16)} ${chalk5.dim(rec.source_url || "")}`);
5204
4724
  }
5205
4725
  }
5206
4726
  lines.push("");
5207
- lines.push(chalk6.dim(" \u2191\u2193 navigate \u23B5 toggle a all n none \u23CE install q cancel"));
4727
+ lines.push(chalk5.dim(" \u2191\u2193 navigate \u23B5 toggle a all n none \u23CE install q cancel"));
5208
4728
  return lines.join("\n");
5209
4729
  }
5210
4730
  function draw(initial) {
@@ -5253,7 +4773,7 @@ async function interactiveSelect2(recs) {
5253
4773
  case "\n":
5254
4774
  cleanup();
5255
4775
  if (selected.size === 0) {
5256
- console.log(chalk6.dim("\n No skills selected.\n"));
4776
+ console.log(chalk5.dim("\n No skills selected.\n"));
5257
4777
  resolve2(null);
5258
4778
  } else {
5259
4779
  resolve2(Array.from(selected).sort().map((i) => recs[i]));
@@ -5263,7 +4783,7 @@ async function interactiveSelect2(recs) {
5263
4783
  case "\x1B":
5264
4784
  case "":
5265
4785
  cleanup();
5266
- console.log(chalk6.dim("\n Cancelled.\n"));
4786
+ console.log(chalk5.dim("\n Cancelled.\n"));
5267
4787
  resolve2(null);
5268
4788
  break;
5269
4789
  }
@@ -5310,7 +4830,7 @@ async function fetchSkillContent(rec) {
5310
4830
  return null;
5311
4831
  }
5312
4832
  async function installSkills(recs, platforms, contentMap) {
5313
- const spinner = ora2(`Installing ${recs.length} skill${recs.length > 1 ? "s" : ""}...`).start();
4833
+ const spinner = ora(`Installing ${recs.length} skill${recs.length > 1 ? "s" : ""}...`).start();
5314
4834
  const installed = [];
5315
4835
  for (const rec of recs) {
5316
4836
  const content = contentMap.get(rec.slug);
@@ -5326,7 +4846,7 @@ async function installSkills(recs, platforms, contentMap) {
5326
4846
  if (installed.length > 0) {
5327
4847
  spinner.succeed(`Installed ${installed.length} file${installed.length > 1 ? "s" : ""}`);
5328
4848
  for (const p of installed) {
5329
- console.log(chalk6.green(` \u2713 ${p}`));
4849
+ console.log(chalk5.green(` \u2713 ${p}`));
5330
4850
  }
5331
4851
  } else {
5332
4852
  spinner.fail("No skills were installed");
@@ -5339,19 +4859,19 @@ function printSkills(recs) {
5339
4859
  const nameWidth = Math.max(...recs.map((r) => r.name.length), 4) + 2;
5340
4860
  const scoreWidth = 6;
5341
4861
  const prefixWidth = 2;
5342
- console.log(chalk6.bold("\n Skills\n"));
4862
+ console.log(chalk5.bold("\n Skills\n"));
5343
4863
  if (hasScores) {
5344
- console.log(" ".repeat(prefixWidth) + chalk6.dim("Score".padEnd(scoreWidth)) + chalk6.dim("Name".padEnd(nameWidth)) + chalk6.dim("Why"));
4864
+ console.log(" ".repeat(prefixWidth) + chalk5.dim("Score".padEnd(scoreWidth)) + chalk5.dim("Name".padEnd(nameWidth)) + chalk5.dim("Why"));
5345
4865
  } else {
5346
- console.log(" ".repeat(prefixWidth) + chalk6.dim("Name".padEnd(nameWidth)) + chalk6.dim("Technology".padEnd(18)) + chalk6.dim("Source"));
4866
+ console.log(" ".repeat(prefixWidth) + chalk5.dim("Name".padEnd(nameWidth)) + chalk5.dim("Technology".padEnd(18)) + chalk5.dim("Source"));
5347
4867
  }
5348
- console.log(chalk6.dim(" " + "\u2500".repeat(Math.min(cols - 4, 90))));
4868
+ console.log(chalk5.dim(" " + "\u2500".repeat(Math.min(cols - 4, 90))));
5349
4869
  for (const rec of recs) {
5350
4870
  if (hasScores) {
5351
4871
  const reasonMax = Math.max(cols - prefixWidth - scoreWidth - nameWidth - 2, 20);
5352
- console.log(` ${String(rec.score).padStart(3)} ${rec.name.padEnd(nameWidth)}${chalk6.dim(rec.reason.slice(0, reasonMax))}`);
4872
+ console.log(` ${String(rec.score).padStart(3)} ${rec.name.padEnd(nameWidth)}${chalk5.dim(rec.reason.slice(0, reasonMax))}`);
5353
4873
  } else {
5354
- console.log(` ${rec.name.padEnd(nameWidth)}${rec.detected_technology.padEnd(16)} ${chalk6.dim(rec.source_url || "")}`);
4874
+ console.log(` ${rec.name.padEnd(nameWidth)}${rec.detected_technology.padEnd(16)} ${chalk5.dim(rec.source_url || "")}`);
5355
4875
  }
5356
4876
  }
5357
4877
  console.log("");
@@ -5359,8 +4879,8 @@ function printSkills(recs) {
5359
4879
 
5360
4880
  // src/commands/onboard.ts
5361
4881
  async function initCommand(options) {
5362
- const brand = chalk7.hex("#EB9D83");
5363
- const title = chalk7.hex("#83D1EB");
4882
+ const brand = chalk6.hex("#EB9D83");
4883
+ const title = chalk6.hex("#83D1EB");
5364
4884
  console.log(brand.bold(`
5365
4885
  \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557
5366
4886
  \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557
@@ -5369,21 +4889,21 @@ async function initCommand(options) {
5369
4889
  \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551
5370
4890
  \u255A\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D
5371
4891
  `));
5372
- console.log(chalk7.dim(" Onboard your project for AI-assisted development\n"));
4892
+ console.log(chalk6.dim(" Onboard your project for AI-assisted development\n"));
5373
4893
  console.log(title.bold(" Welcome to Caliber\n"));
5374
- console.log(chalk7.dim(" Caliber analyzes your codebase and creates tailored config files"));
5375
- console.log(chalk7.dim(" so your AI coding agents understand your project from day one.\n"));
4894
+ console.log(chalk6.dim(" Caliber analyzes your codebase and creates tailored config files"));
4895
+ console.log(chalk6.dim(" so your AI coding agents understand your project from day one.\n"));
5376
4896
  console.log(title.bold(" How onboarding works:\n"));
5377
- console.log(chalk7.dim(" 1. Connect Set up your LLM provider"));
5378
- console.log(chalk7.dim(" 2. Discover Analyze your code, dependencies, and structure"));
5379
- console.log(chalk7.dim(" 3. Generate Create config files tailored to your project"));
5380
- console.log(chalk7.dim(" 4. Review Preview, refine, and apply the changes"));
5381
- console.log(chalk7.dim(" 5. Enhance Discover MCP servers for your tools"));
5382
- console.log(chalk7.dim(" 6. Skills Browse community skills for your stack\n"));
4897
+ console.log(chalk6.dim(" 1. Connect Set up your LLM provider"));
4898
+ console.log(chalk6.dim(" 2. Discover Analyze your code, dependencies, and structure"));
4899
+ console.log(chalk6.dim(" 3. Generate Create config files tailored to your project"));
4900
+ console.log(chalk6.dim(" 4. Review Preview, refine, and apply the changes"));
4901
+ console.log(chalk6.dim(" 5. Enhance Discover MCP servers for your tools"));
4902
+ console.log(chalk6.dim(" 6. Skills Browse community skills for your stack\n"));
5383
4903
  console.log(title.bold(" Step 1/6 \u2014 Connect your LLM\n"));
5384
4904
  let config = loadConfig();
5385
4905
  if (!config) {
5386
- console.log(chalk7.dim(" No LLM provider set yet. Choose how to run Caliber:\n"));
4906
+ console.log(chalk6.dim(" No LLM provider set yet. Choose how to run Caliber:\n"));
5387
4907
  try {
5388
4908
  await runInteractiveProviderSetup({
5389
4909
  selectMessage: "How do you want to use Caliber? (choose LLM provider)"
@@ -5394,22 +4914,22 @@ async function initCommand(options) {
5394
4914
  }
5395
4915
  config = loadConfig();
5396
4916
  if (!config) {
5397
- console.log(chalk7.red(" Setup was cancelled or failed.\n"));
4917
+ console.log(chalk6.red(" Setup was cancelled or failed.\n"));
5398
4918
  throw new Error("__exit__");
5399
4919
  }
5400
- console.log(chalk7.green(" \u2713 Provider saved. Let's continue.\n"));
4920
+ console.log(chalk6.green(" \u2713 Provider saved. Let's continue.\n"));
5401
4921
  }
5402
4922
  const displayModel = config.model === "default" && config.provider === "claude-cli" ? process.env.ANTHROPIC_MODEL || "default (inherited from Claude Code)" : config.model;
5403
4923
  const fastModel = getFastModel();
5404
4924
  const modelLine = fastModel ? ` Provider: ${config.provider} | Model: ${displayModel} | Scan: ${fastModel}` : ` Provider: ${config.provider} | Model: ${displayModel}`;
5405
- console.log(chalk7.dim(modelLine + "\n"));
4925
+ console.log(chalk6.dim(modelLine + "\n"));
5406
4926
  console.log(title.bold(" Step 2/6 \u2014 Discover your project\n"));
5407
- console.log(chalk7.dim(" Learning about your languages, dependencies, structure, and existing configs.\n"));
5408
- const spinner = ora3("Analyzing project...").start();
4927
+ console.log(chalk6.dim(" Learning about your languages, dependencies, structure, and existing configs.\n"));
4928
+ const spinner = ora2("Analyzing project...").start();
5409
4929
  const fingerprint = await collectFingerprint(process.cwd());
5410
4930
  spinner.succeed("Project analyzed");
5411
- console.log(chalk7.dim(` Languages: ${fingerprint.languages.join(", ") || "none detected"}`));
5412
- console.log(chalk7.dim(` Files: ${fingerprint.fileTree.length} found
4931
+ console.log(chalk6.dim(` Languages: ${fingerprint.languages.join(", ") || "none detected"}`));
4932
+ console.log(chalk6.dim(` Files: ${fingerprint.fileTree.length} found
5413
4933
  `));
5414
4934
  const targetAgent = options.agent || await promptAgent();
5415
4935
  const preScore = computeLocalScore(process.cwd(), targetAgent);
@@ -5428,28 +4948,28 @@ async function initCommand(options) {
5428
4948
  const hasExistingConfig = !!(fingerprint.existingConfigs.claudeMd || fingerprint.existingConfigs.claudeSettings || fingerprint.existingConfigs.claudeSkills?.length || fingerprint.existingConfigs.cursorrules || fingerprint.existingConfigs.cursorRules?.length || fingerprint.existingConfigs.agentsMd);
5429
4949
  const NON_LLM_CHECKS = /* @__PURE__ */ new Set(["hooks_configured", "agents_md_exists", "permissions_configured", "mcp_servers"]);
5430
4950
  if (hasExistingConfig && baselineScore.score === 100) {
5431
- console.log(chalk7.bold.green(" Your setup is already optimal \u2014 nothing to change.\n"));
5432
- console.log(chalk7.dim(" Run ") + chalk7.hex("#83D1EB")("caliber onboard --force") + chalk7.dim(" to regenerate anyway.\n"));
4951
+ console.log(chalk6.bold.green(" Your setup is already optimal \u2014 nothing to change.\n"));
4952
+ console.log(chalk6.dim(" Run ") + chalk6.hex("#83D1EB")("caliber onboard --force") + chalk6.dim(" to regenerate anyway.\n"));
5433
4953
  if (!options.force) return;
5434
4954
  }
5435
4955
  const allFailingChecks = baselineScore.checks.filter((c) => !c.passed && c.maxPoints > 0);
5436
4956
  const llmFixableChecks = allFailingChecks.filter((c) => !NON_LLM_CHECKS.has(c.id));
5437
4957
  if (hasExistingConfig && llmFixableChecks.length === 0 && allFailingChecks.length > 0 && !options.force) {
5438
- console.log(chalk7.bold.green("\n Your config is fully optimized for LLM generation.\n"));
5439
- console.log(chalk7.dim(" Remaining items need CLI actions:\n"));
4958
+ console.log(chalk6.bold.green("\n Your config is fully optimized for LLM generation.\n"));
4959
+ console.log(chalk6.dim(" Remaining items need CLI actions:\n"));
5440
4960
  for (const check of allFailingChecks) {
5441
- console.log(chalk7.dim(` \u2022 ${check.name}`));
4961
+ console.log(chalk6.dim(` \u2022 ${check.name}`));
5442
4962
  if (check.suggestion) {
5443
- console.log(` ${chalk7.hex("#83D1EB")(check.suggestion)}`);
4963
+ console.log(` ${chalk6.hex("#83D1EB")(check.suggestion)}`);
5444
4964
  }
5445
4965
  }
5446
4966
  console.log("");
5447
- console.log(chalk7.dim(" Run ") + chalk7.hex("#83D1EB")("caliber onboard --force") + chalk7.dim(" to regenerate anyway.\n"));
4967
+ console.log(chalk6.dim(" Run ") + chalk6.hex("#83D1EB")("caliber onboard --force") + chalk6.dim(" to regenerate anyway.\n"));
5448
4968
  return;
5449
4969
  }
5450
4970
  const isEmpty = fingerprint.fileTree.length < 3;
5451
4971
  if (isEmpty) {
5452
- fingerprint.description = await promptInput3("What will you build in this project?");
4972
+ fingerprint.description = await promptInput2("What will you build in this project?");
5453
4973
  }
5454
4974
  let failingChecks;
5455
4975
  let passingChecks;
@@ -5460,24 +4980,24 @@ async function initCommand(options) {
5460
4980
  currentScore = baselineScore.score;
5461
4981
  if (failingChecks.length > 0) {
5462
4982
  console.log(title.bold(" Step 3/6 \u2014 Fine-tuning\n"));
5463
- console.log(chalk7.dim(` Your setup scores ${baselineScore.score}/100 \u2014 fixing ${failingChecks.length} remaining issue${failingChecks.length === 1 ? "" : "s"}:
4983
+ console.log(chalk6.dim(` Your setup scores ${baselineScore.score}/100 \u2014 fixing ${failingChecks.length} remaining issue${failingChecks.length === 1 ? "" : "s"}:
5464
4984
  `));
5465
4985
  for (const check of failingChecks) {
5466
- console.log(chalk7.dim(` \u2022 ${check.name}`));
4986
+ console.log(chalk6.dim(` \u2022 ${check.name}`));
5467
4987
  }
5468
4988
  console.log("");
5469
4989
  }
5470
4990
  } else if (hasExistingConfig) {
5471
4991
  console.log(title.bold(" Step 3/6 \u2014 Improve your setup\n"));
5472
- console.log(chalk7.dim(" Reviewing your existing configs against your codebase"));
5473
- console.log(chalk7.dim(" and preparing improvements.\n"));
4992
+ console.log(chalk6.dim(" Reviewing your existing configs against your codebase"));
4993
+ console.log(chalk6.dim(" and preparing improvements.\n"));
5474
4994
  } else {
5475
4995
  console.log(title.bold(" Step 3/6 \u2014 Build your agent setup\n"));
5476
- console.log(chalk7.dim(" Creating config files tailored to your project.\n"));
4996
+ console.log(chalk6.dim(" Creating config files tailored to your project.\n"));
5477
4997
  }
5478
- console.log(chalk7.dim(" This can take a couple of minutes depending on your model and provider.\n"));
4998
+ console.log(chalk6.dim(" This can take a couple of minutes depending on your model and provider.\n"));
5479
4999
  const genStartTime = Date.now();
5480
- const genSpinner = ora3("Generating setup...").start();
5000
+ const genSpinner = ora2("Generating setup...").start();
5481
5001
  const genMessages = new SpinnerMessages(genSpinner, GENERATION_MESSAGES, { showElapsedTime: true });
5482
5002
  genMessages.start();
5483
5003
  let generatedSetup = null;
@@ -5517,8 +5037,8 @@ async function initCommand(options) {
5517
5037
  if (!generatedSetup) {
5518
5038
  genSpinner.fail("Failed to generate setup.");
5519
5039
  if (rawOutput) {
5520
- console.log(chalk7.dim("\nRaw LLM output (JSON parse failed):"));
5521
- console.log(chalk7.dim(rawOutput.slice(0, 500)));
5040
+ console.log(chalk6.dim("\nRaw LLM output (JSON parse failed):"));
5041
+ console.log(chalk6.dim(rawOutput.slice(0, 500)));
5522
5042
  }
5523
5043
  throw new Error("__exit__");
5524
5044
  }
@@ -5526,7 +5046,7 @@ async function initCommand(options) {
5526
5046
  const mins = Math.floor(elapsedMs / 6e4);
5527
5047
  const secs = Math.floor(elapsedMs % 6e4 / 1e3);
5528
5048
  const timeStr = mins > 0 ? `${mins}m ${secs}s` : `${secs}s`;
5529
- genSpinner.succeed(`Setup generated ${chalk7.dim(`in ${timeStr}`)}`);
5049
+ genSpinner.succeed(`Setup generated ${chalk6.dim(`in ${timeStr}`)}`);
5530
5050
  printSetupSummary(generatedSetup);
5531
5051
  const sessionHistory = [];
5532
5052
  sessionHistory.push({
@@ -5537,11 +5057,11 @@ async function initCommand(options) {
5537
5057
  const setupFiles = collectSetupFiles(generatedSetup);
5538
5058
  const staged = stageFiles(setupFiles, process.cwd());
5539
5059
  const totalChanges = staged.newFiles + staged.modifiedFiles;
5540
- console.log(chalk7.dim(` ${chalk7.green(`${staged.newFiles} new`)} / ${chalk7.yellow(`${staged.modifiedFiles} modified`)} file${totalChanges !== 1 ? "s" : ""}
5060
+ console.log(chalk6.dim(` ${chalk6.green(`${staged.newFiles} new`)} / ${chalk6.yellow(`${staged.modifiedFiles} modified`)} file${totalChanges !== 1 ? "s" : ""}
5541
5061
  `));
5542
5062
  let action;
5543
5063
  if (totalChanges === 0) {
5544
- console.log(chalk7.dim(" No changes needed \u2014 your configs are already up to date.\n"));
5064
+ console.log(chalk6.dim(" No changes needed \u2014 your configs are already up to date.\n"));
5545
5065
  cleanupStaging();
5546
5066
  action = "accept";
5547
5067
  } else {
@@ -5556,12 +5076,12 @@ async function initCommand(options) {
5556
5076
  generatedSetup = await refineLoop(generatedSetup, targetAgent, sessionHistory);
5557
5077
  if (!generatedSetup) {
5558
5078
  cleanupStaging();
5559
- console.log(chalk7.dim("Refinement cancelled. No files were modified."));
5079
+ console.log(chalk6.dim("Refinement cancelled. No files were modified."));
5560
5080
  return;
5561
5081
  }
5562
5082
  const updatedFiles = collectSetupFiles(generatedSetup);
5563
5083
  const restaged = stageFiles(updatedFiles, process.cwd());
5564
- console.log(chalk7.dim(` ${chalk7.green(`${restaged.newFiles} new`)} / ${chalk7.yellow(`${restaged.modifiedFiles} modified`)} file${restaged.newFiles + restaged.modifiedFiles !== 1 ? "s" : ""}
5084
+ console.log(chalk6.dim(` ${chalk6.green(`${restaged.newFiles} new`)} / ${chalk6.yellow(`${restaged.modifiedFiles} modified`)} file${restaged.newFiles + restaged.modifiedFiles !== 1 ? "s" : ""}
5565
5085
  `));
5566
5086
  printSetupSummary(generatedSetup);
5567
5087
  await openReview("terminal", restaged.stagedFiles);
@@ -5569,56 +5089,37 @@ async function initCommand(options) {
5569
5089
  }
5570
5090
  cleanupStaging();
5571
5091
  if (action === "decline") {
5572
- console.log(chalk7.dim("Setup declined. No files were modified."));
5092
+ console.log(chalk6.dim("Setup declined. No files were modified."));
5573
5093
  return;
5574
5094
  }
5575
5095
  if (options.dryRun) {
5576
- console.log(chalk7.yellow("\n[Dry run] Would write the following files:"));
5096
+ console.log(chalk6.yellow("\n[Dry run] Would write the following files:"));
5577
5097
  console.log(JSON.stringify(generatedSetup, null, 2));
5578
5098
  return;
5579
5099
  }
5580
- const writeSpinner = ora3("Writing config files...").start();
5100
+ const writeSpinner = ora2("Writing config files...").start();
5581
5101
  try {
5582
5102
  const result = writeSetup(generatedSetup);
5583
5103
  writeSpinner.succeed("Config files written");
5584
- console.log(chalk7.bold("\nFiles created/updated:"));
5104
+ console.log(chalk6.bold("\nFiles created/updated:"));
5585
5105
  for (const file of result.written) {
5586
- console.log(` ${chalk7.green("\u2713")} ${file}`);
5106
+ console.log(` ${chalk6.green("\u2713")} ${file}`);
5587
5107
  }
5588
5108
  if (result.deleted.length > 0) {
5589
- console.log(chalk7.bold("\nFiles removed:"));
5109
+ console.log(chalk6.bold("\nFiles removed:"));
5590
5110
  for (const file of result.deleted) {
5591
- console.log(` ${chalk7.red("\u2717")} ${file}`);
5111
+ console.log(` ${chalk6.red("\u2717")} ${file}`);
5592
5112
  }
5593
5113
  }
5594
5114
  if (result.backupDir) {
5595
- console.log(chalk7.dim(`
5115
+ console.log(chalk6.dim(`
5596
5116
  Backups saved to ${result.backupDir}`));
5597
5117
  }
5598
5118
  } catch (err) {
5599
5119
  writeSpinner.fail("Failed to write files");
5600
- console.error(chalk7.red(err instanceof Error ? err.message : "Unknown error"));
5120
+ console.error(chalk6.red(err instanceof Error ? err.message : "Unknown error"));
5601
5121
  throw new Error("__exit__");
5602
5122
  }
5603
- console.log(title.bold("\n Step 5/6 \u2014 Enhance with MCP servers\n"));
5604
- console.log(chalk7.dim(" MCP servers connect your AI agents to external tools and services"));
5605
- console.log(chalk7.dim(" like databases, APIs, and platforms your project depends on.\n"));
5606
- if (fingerprint.tools.length > 0) {
5607
- try {
5608
- const mcpResult = await discoverAndInstallMcps(targetAgent, fingerprint, process.cwd());
5609
- if (mcpResult.installed > 0) {
5610
- console.log(chalk7.bold(`
5611
- ${mcpResult.installed} MCP server${mcpResult.installed > 1 ? "s" : ""} configured`));
5612
- for (const name of mcpResult.names) {
5613
- console.log(` ${chalk7.green("\u2713")} ${name}`);
5614
- }
5615
- }
5616
- } catch (err) {
5617
- console.log(chalk7.dim(" MCP discovery skipped: " + (err instanceof Error ? err.message : "unknown error")));
5618
- }
5619
- } else {
5620
- console.log(chalk7.dim(" No external tools or services detected \u2014 skipping MCP discovery.\n"));
5621
- }
5622
5123
  ensurePermissions();
5623
5124
  const sha = getCurrentHeadSha();
5624
5125
  writeState({
@@ -5628,55 +5129,55 @@ async function initCommand(options) {
5628
5129
  });
5629
5130
  console.log("");
5630
5131
  console.log(title.bold(" Keep your configs fresh\n"));
5631
- console.log(chalk7.dim(" Caliber can automatically update your agent configs when your code changes.\n"));
5132
+ console.log(chalk6.dim(" Caliber can automatically update your agent configs when your code changes.\n"));
5632
5133
  const hookChoice = await promptHookType(targetAgent);
5633
5134
  if (hookChoice === "claude" || hookChoice === "both") {
5634
5135
  const hookResult = installHook();
5635
5136
  if (hookResult.installed) {
5636
- console.log(` ${chalk7.green("\u2713")} Claude Code hook installed \u2014 docs update on session end`);
5637
- console.log(chalk7.dim(" Run ") + chalk7.hex("#83D1EB")("caliber hooks --remove") + chalk7.dim(" to disable"));
5137
+ console.log(` ${chalk6.green("\u2713")} Claude Code hook installed \u2014 docs update on session end`);
5138
+ console.log(chalk6.dim(" Run ") + chalk6.hex("#83D1EB")("caliber hooks --remove") + chalk6.dim(" to disable"));
5638
5139
  } else if (hookResult.alreadyInstalled) {
5639
- console.log(chalk7.dim(" Claude Code hook already installed"));
5140
+ console.log(chalk6.dim(" Claude Code hook already installed"));
5640
5141
  }
5641
5142
  const learnResult = installLearningHooks();
5642
5143
  if (learnResult.installed) {
5643
- console.log(` ${chalk7.green("\u2713")} Learning hooks installed \u2014 session insights captured automatically`);
5644
- console.log(chalk7.dim(" Run ") + chalk7.hex("#83D1EB")("caliber learn remove") + chalk7.dim(" to disable"));
5144
+ console.log(` ${chalk6.green("\u2713")} Learning hooks installed \u2014 session insights captured automatically`);
5145
+ console.log(chalk6.dim(" Run ") + chalk6.hex("#83D1EB")("caliber learn remove") + chalk6.dim(" to disable"));
5645
5146
  } else if (learnResult.alreadyInstalled) {
5646
- console.log(chalk7.dim(" Learning hooks already installed"));
5147
+ console.log(chalk6.dim(" Learning hooks already installed"));
5647
5148
  }
5648
5149
  }
5649
5150
  if (hookChoice === "precommit" || hookChoice === "both") {
5650
5151
  const precommitResult = installPreCommitHook();
5651
5152
  if (precommitResult.installed) {
5652
- console.log(` ${chalk7.green("\u2713")} Pre-commit hook installed \u2014 docs refresh before each commit`);
5653
- console.log(chalk7.dim(" Run ") + chalk7.hex("#83D1EB")("caliber hooks --remove") + chalk7.dim(" to disable"));
5153
+ console.log(` ${chalk6.green("\u2713")} Pre-commit hook installed \u2014 docs refresh before each commit`);
5154
+ console.log(chalk6.dim(" Run ") + chalk6.hex("#83D1EB")("caliber hooks --remove") + chalk6.dim(" to disable"));
5654
5155
  } else if (precommitResult.alreadyInstalled) {
5655
- console.log(chalk7.dim(" Pre-commit hook already installed"));
5156
+ console.log(chalk6.dim(" Pre-commit hook already installed"));
5656
5157
  } else {
5657
- console.log(chalk7.yellow(" Could not install pre-commit hook (not a git repository?)"));
5158
+ console.log(chalk6.yellow(" Could not install pre-commit hook (not a git repository?)"));
5658
5159
  }
5659
5160
  }
5660
5161
  if (hookChoice === "skip") {
5661
- console.log(chalk7.dim(" Skipped auto-refresh hooks. Run ") + chalk7.hex("#83D1EB")("caliber hooks --install") + chalk7.dim(" later to enable."));
5162
+ console.log(chalk6.dim(" Skipped auto-refresh hooks. Run ") + chalk6.hex("#83D1EB")("caliber hooks --install") + chalk6.dim(" later to enable."));
5662
5163
  }
5663
5164
  const afterScore = computeLocalScore(process.cwd(), targetAgent);
5664
5165
  if (afterScore.score < baselineScore.score) {
5665
5166
  console.log("");
5666
- console.log(chalk7.yellow(` Score would drop from ${baselineScore.score} to ${afterScore.score} \u2014 reverting changes.`));
5167
+ console.log(chalk6.yellow(` Score would drop from ${baselineScore.score} to ${afterScore.score} \u2014 reverting changes.`));
5667
5168
  try {
5668
5169
  const { restored, removed } = undoSetup();
5669
5170
  if (restored.length > 0 || removed.length > 0) {
5670
- console.log(chalk7.dim(` Reverted ${restored.length + removed.length} file${restored.length + removed.length === 1 ? "" : "s"} from backup.`));
5171
+ console.log(chalk6.dim(` Reverted ${restored.length + removed.length} file${restored.length + removed.length === 1 ? "" : "s"} from backup.`));
5671
5172
  }
5672
5173
  } catch {
5673
5174
  }
5674
- console.log(chalk7.dim(" Run ") + chalk7.hex("#83D1EB")("caliber onboard --force") + chalk7.dim(" to override.\n"));
5175
+ console.log(chalk6.dim(" Run ") + chalk6.hex("#83D1EB")("caliber onboard --force") + chalk6.dim(" to override.\n"));
5675
5176
  return;
5676
5177
  }
5677
5178
  displayScoreDelta(baselineScore, afterScore);
5678
5179
  console.log(title.bold("\n Step 6/6 \u2014 Community skills\n"));
5679
- console.log(chalk7.dim(" Search public skill registries for skills that match your tech stack.\n"));
5180
+ console.log(chalk6.dim(" Search public skill registries for skills that match your tech stack.\n"));
5680
5181
  const wantsSkills = await select4({
5681
5182
  message: "Search public repos for relevant skills to add to this project?",
5682
5183
  choices: [
@@ -5689,16 +5190,16 @@ async function initCommand(options) {
5689
5190
  await searchAndInstallSkills();
5690
5191
  } catch (err) {
5691
5192
  if (err.message !== "__exit__") {
5692
- console.log(chalk7.dim(" Skills search failed: " + (err.message || "unknown error")));
5193
+ console.log(chalk6.dim(" Skills search failed: " + (err.message || "unknown error")));
5693
5194
  }
5694
- console.log(chalk7.dim(" Run ") + chalk7.hex("#83D1EB")("caliber skills") + chalk7.dim(" later to try again.\n"));
5195
+ console.log(chalk6.dim(" Run ") + chalk6.hex("#83D1EB")("caliber skills") + chalk6.dim(" later to try again.\n"));
5695
5196
  }
5696
5197
  } else {
5697
- console.log(chalk7.dim(" Skipped. Run ") + chalk7.hex("#83D1EB")("caliber skills") + chalk7.dim(" later to browse.\n"));
5198
+ console.log(chalk6.dim(" Skipped. Run ") + chalk6.hex("#83D1EB")("caliber skills") + chalk6.dim(" later to browse.\n"));
5698
5199
  }
5699
- console.log(chalk7.bold.green(" Onboarding complete! Your project is ready for AI-assisted development."));
5700
- console.log(chalk7.dim(" Run ") + chalk7.hex("#83D1EB")("caliber undo") + chalk7.dim(" to revert changes.\n"));
5701
- console.log(chalk7.bold(" Next steps:\n"));
5200
+ console.log(chalk6.bold.green(" Onboarding complete! Your project is ready for AI-assisted development."));
5201
+ console.log(chalk6.dim(" Run ") + chalk6.hex("#83D1EB")("caliber undo") + chalk6.dim(" to revert changes.\n"));
5202
+ console.log(chalk6.bold(" Next steps:\n"));
5702
5203
  console.log(` ${title("caliber score")} See your full config breakdown`);
5703
5204
  console.log(` ${title("caliber skills")} Discover community skills for your stack`);
5704
5205
  console.log(` ${title("caliber undo")} Revert all changes from this run`);
@@ -5706,7 +5207,7 @@ async function initCommand(options) {
5706
5207
  }
5707
5208
  async function refineLoop(currentSetup, _targetAgent, sessionHistory) {
5708
5209
  while (true) {
5709
- const message = await promptInput3("\nWhat would you like to change?");
5210
+ const message = await promptInput2("\nWhat would you like to change?");
5710
5211
  if (!message || message.toLowerCase() === "done" || message.toLowerCase() === "accept") {
5711
5212
  return currentSetup;
5712
5213
  }
@@ -5715,12 +5216,12 @@ async function refineLoop(currentSetup, _targetAgent, sessionHistory) {
5715
5216
  }
5716
5217
  const isValid = await classifyRefineIntent(message);
5717
5218
  if (!isValid) {
5718
- console.log(chalk7.dim(" This doesn't look like a config change request."));
5719
- console.log(chalk7.dim(" Describe what to add, remove, or modify in your configs."));
5720
- console.log(chalk7.dim(' Type "done" to accept the current setup.\n'));
5219
+ console.log(chalk6.dim(" This doesn't look like a config change request."));
5220
+ console.log(chalk6.dim(" Describe what to add, remove, or modify in your configs."));
5221
+ console.log(chalk6.dim(' Type "done" to accept the current setup.\n'));
5721
5222
  continue;
5722
5223
  }
5723
- const refineSpinner = ora3("Refining setup...").start();
5224
+ const refineSpinner = ora2("Refining setup...").start();
5724
5225
  const refineMessages = new SpinnerMessages(refineSpinner, REFINE_MESSAGES);
5725
5226
  refineMessages.start();
5726
5227
  const refined = await refineSetup(
@@ -5738,16 +5239,16 @@ async function refineLoop(currentSetup, _targetAgent, sessionHistory) {
5738
5239
  });
5739
5240
  refineSpinner.succeed("Setup updated");
5740
5241
  printSetupSummary(refined);
5741
- console.log(chalk7.dim('Type "done" to accept, or describe more changes.'));
5242
+ console.log(chalk6.dim('Type "done" to accept, or describe more changes.'));
5742
5243
  } else {
5743
5244
  refineSpinner.fail("Refinement failed \u2014 could not parse AI response.");
5744
- console.log(chalk7.dim('Try rephrasing your request, or type "done" to keep the current setup.'));
5245
+ console.log(chalk6.dim('Try rephrasing your request, or type "done" to keep the current setup.'));
5745
5246
  }
5746
5247
  }
5747
5248
  }
5748
5249
  function summarizeSetup(action, setup) {
5749
5250
  const descriptions = setup.fileDescriptions;
5750
- const files = descriptions ? Object.entries(descriptions).map(([path24, desc]) => ` ${path24}: ${desc}`).join("\n") : Object.keys(setup).filter((k) => k !== "targetAgent" && k !== "fileDescriptions").join(", ");
5251
+ const files = descriptions ? Object.entries(descriptions).map(([path23, desc]) => ` ${path23}: ${desc}`).join("\n") : Object.keys(setup).filter((k) => k !== "targetAgent" && k !== "fileDescriptions").join(", ");
5751
5252
  return `${action}. Files:
5752
5253
  ${files}`;
5753
5254
  }
@@ -5798,10 +5299,10 @@ ${JSON.stringify(checkList, null, 2)}`,
5798
5299
  return [];
5799
5300
  }
5800
5301
  }
5801
- function promptInput3(question) {
5802
- const rl = readline4.createInterface({ input: process.stdin, output: process.stdout });
5302
+ function promptInput2(question) {
5303
+ const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
5803
5304
  return new Promise((resolve2) => {
5804
- rl.question(chalk7.cyan(`${question} `), (answer) => {
5305
+ rl.question(chalk6.cyan(`${question} `), (answer) => {
5805
5306
  rl.close();
5806
5307
  resolve2(answer.trim());
5807
5308
  });
@@ -5854,26 +5355,26 @@ function printSetupSummary(setup) {
5854
5355
  const fileDescriptions = setup.fileDescriptions;
5855
5356
  const deletions = setup.deletions;
5856
5357
  console.log("");
5857
- console.log(chalk7.bold(" Proposed changes:\n"));
5358
+ console.log(chalk6.bold(" Proposed changes:\n"));
5858
5359
  const getDescription = (filePath) => {
5859
5360
  return fileDescriptions?.[filePath];
5860
5361
  };
5861
5362
  if (claude) {
5862
5363
  if (claude.claudeMd) {
5863
- const icon = fs22.existsSync("CLAUDE.md") ? chalk7.yellow("~") : chalk7.green("+");
5364
+ const icon = fs21.existsSync("CLAUDE.md") ? chalk6.yellow("~") : chalk6.green("+");
5864
5365
  const desc = getDescription("CLAUDE.md");
5865
- console.log(` ${icon} ${chalk7.bold("CLAUDE.md")}`);
5866
- if (desc) console.log(chalk7.dim(` ${desc}`));
5366
+ console.log(` ${icon} ${chalk6.bold("CLAUDE.md")}`);
5367
+ if (desc) console.log(chalk6.dim(` ${desc}`));
5867
5368
  console.log("");
5868
5369
  }
5869
5370
  const skills = claude.skills;
5870
5371
  if (Array.isArray(skills) && skills.length > 0) {
5871
5372
  for (const skill of skills) {
5872
5373
  const skillPath = `.claude/skills/${skill.name}/SKILL.md`;
5873
- const icon = fs22.existsSync(skillPath) ? chalk7.yellow("~") : chalk7.green("+");
5374
+ const icon = fs21.existsSync(skillPath) ? chalk6.yellow("~") : chalk6.green("+");
5874
5375
  const desc = getDescription(skillPath);
5875
- console.log(` ${icon} ${chalk7.bold(skillPath)}`);
5876
- console.log(chalk7.dim(` ${desc || skill.description || skill.name}`));
5376
+ console.log(` ${icon} ${chalk6.bold(skillPath)}`);
5377
+ console.log(chalk6.dim(` ${desc || skill.description || skill.name}`));
5877
5378
  console.log("");
5878
5379
  }
5879
5380
  }
@@ -5881,40 +5382,40 @@ function printSetupSummary(setup) {
5881
5382
  const codex = setup.codex;
5882
5383
  if (codex) {
5883
5384
  if (codex.agentsMd) {
5884
- const icon = fs22.existsSync("AGENTS.md") ? chalk7.yellow("~") : chalk7.green("+");
5385
+ const icon = fs21.existsSync("AGENTS.md") ? chalk6.yellow("~") : chalk6.green("+");
5885
5386
  const desc = getDescription("AGENTS.md");
5886
- console.log(` ${icon} ${chalk7.bold("AGENTS.md")}`);
5887
- if (desc) console.log(chalk7.dim(` ${desc}`));
5387
+ console.log(` ${icon} ${chalk6.bold("AGENTS.md")}`);
5388
+ if (desc) console.log(chalk6.dim(` ${desc}`));
5888
5389
  console.log("");
5889
5390
  }
5890
5391
  const codexSkills = codex.skills;
5891
5392
  if (Array.isArray(codexSkills) && codexSkills.length > 0) {
5892
5393
  for (const skill of codexSkills) {
5893
5394
  const skillPath = `.agents/skills/${skill.name}/SKILL.md`;
5894
- const icon = fs22.existsSync(skillPath) ? chalk7.yellow("~") : chalk7.green("+");
5395
+ const icon = fs21.existsSync(skillPath) ? chalk6.yellow("~") : chalk6.green("+");
5895
5396
  const desc = getDescription(skillPath);
5896
- console.log(` ${icon} ${chalk7.bold(skillPath)}`);
5897
- console.log(chalk7.dim(` ${desc || skill.description || skill.name}`));
5397
+ console.log(` ${icon} ${chalk6.bold(skillPath)}`);
5398
+ console.log(chalk6.dim(` ${desc || skill.description || skill.name}`));
5898
5399
  console.log("");
5899
5400
  }
5900
5401
  }
5901
5402
  }
5902
5403
  if (cursor) {
5903
5404
  if (cursor.cursorrules) {
5904
- const icon = fs22.existsSync(".cursorrules") ? chalk7.yellow("~") : chalk7.green("+");
5405
+ const icon = fs21.existsSync(".cursorrules") ? chalk6.yellow("~") : chalk6.green("+");
5905
5406
  const desc = getDescription(".cursorrules");
5906
- console.log(` ${icon} ${chalk7.bold(".cursorrules")}`);
5907
- if (desc) console.log(chalk7.dim(` ${desc}`));
5407
+ console.log(` ${icon} ${chalk6.bold(".cursorrules")}`);
5408
+ if (desc) console.log(chalk6.dim(` ${desc}`));
5908
5409
  console.log("");
5909
5410
  }
5910
5411
  const cursorSkills = cursor.skills;
5911
5412
  if (Array.isArray(cursorSkills) && cursorSkills.length > 0) {
5912
5413
  for (const skill of cursorSkills) {
5913
5414
  const skillPath = `.cursor/skills/${skill.name}/SKILL.md`;
5914
- const icon = fs22.existsSync(skillPath) ? chalk7.yellow("~") : chalk7.green("+");
5415
+ const icon = fs21.existsSync(skillPath) ? chalk6.yellow("~") : chalk6.green("+");
5915
5416
  const desc = getDescription(skillPath);
5916
- console.log(` ${icon} ${chalk7.bold(skillPath)}`);
5917
- console.log(chalk7.dim(` ${desc || skill.description || skill.name}`));
5417
+ console.log(` ${icon} ${chalk6.bold(skillPath)}`);
5418
+ console.log(chalk6.dim(` ${desc || skill.description || skill.name}`));
5918
5419
  console.log("");
5919
5420
  }
5920
5421
  }
@@ -5922,40 +5423,40 @@ function printSetupSummary(setup) {
5922
5423
  if (Array.isArray(rules) && rules.length > 0) {
5923
5424
  for (const rule of rules) {
5924
5425
  const rulePath = `.cursor/rules/${rule.filename}`;
5925
- const icon = fs22.existsSync(rulePath) ? chalk7.yellow("~") : chalk7.green("+");
5426
+ const icon = fs21.existsSync(rulePath) ? chalk6.yellow("~") : chalk6.green("+");
5926
5427
  const desc = getDescription(rulePath);
5927
- console.log(` ${icon} ${chalk7.bold(rulePath)}`);
5428
+ console.log(` ${icon} ${chalk6.bold(rulePath)}`);
5928
5429
  if (desc) {
5929
- console.log(chalk7.dim(` ${desc}`));
5430
+ console.log(chalk6.dim(` ${desc}`));
5930
5431
  } else {
5931
5432
  const firstLine = rule.content.split("\n").filter((l) => l.trim() && !l.trim().startsWith("#"))[0];
5932
- if (firstLine) console.log(chalk7.dim(` ${firstLine.trim().slice(0, 80)}`));
5433
+ if (firstLine) console.log(chalk6.dim(` ${firstLine.trim().slice(0, 80)}`));
5933
5434
  }
5934
5435
  console.log("");
5935
5436
  }
5936
5437
  }
5937
5438
  }
5938
- if (!codex && !fs22.existsSync("AGENTS.md")) {
5939
- console.log(` ${chalk7.green("+")} ${chalk7.bold("AGENTS.md")}`);
5940
- console.log(chalk7.dim(" Cross-agent coordination file"));
5439
+ if (!codex && !fs21.existsSync("AGENTS.md")) {
5440
+ console.log(` ${chalk6.green("+")} ${chalk6.bold("AGENTS.md")}`);
5441
+ console.log(chalk6.dim(" Cross-agent coordination file"));
5941
5442
  console.log("");
5942
5443
  }
5943
5444
  if (Array.isArray(deletions) && deletions.length > 0) {
5944
5445
  for (const del of deletions) {
5945
- console.log(` ${chalk7.red("-")} ${chalk7.bold(del.filePath)}`);
5946
- console.log(chalk7.dim(` ${del.reason}`));
5446
+ console.log(` ${chalk6.red("-")} ${chalk6.bold(del.filePath)}`);
5447
+ console.log(chalk6.dim(` ${del.reason}`));
5947
5448
  console.log("");
5948
5449
  }
5949
5450
  }
5950
- console.log(` ${chalk7.green("+")} ${chalk7.dim("new")} ${chalk7.yellow("~")} ${chalk7.dim("modified")} ${chalk7.red("-")} ${chalk7.dim("removed")}`);
5451
+ console.log(` ${chalk6.green("+")} ${chalk6.dim("new")} ${chalk6.yellow("~")} ${chalk6.dim("modified")} ${chalk6.red("-")} ${chalk6.dim("removed")}`);
5951
5452
  console.log("");
5952
5453
  }
5953
5454
  function ensurePermissions() {
5954
5455
  const settingsPath = ".claude/settings.json";
5955
5456
  let settings = {};
5956
5457
  try {
5957
- if (fs22.existsSync(settingsPath)) {
5958
- settings = JSON.parse(fs22.readFileSync(settingsPath, "utf-8"));
5458
+ if (fs21.existsSync(settingsPath)) {
5459
+ settings = JSON.parse(fs21.readFileSync(settingsPath, "utf-8"));
5959
5460
  }
5960
5461
  } catch {
5961
5462
  }
@@ -5969,15 +5470,15 @@ function ensurePermissions() {
5969
5470
  "Bash(git *)"
5970
5471
  ];
5971
5472
  settings.permissions = permissions;
5972
- if (!fs22.existsSync(".claude")) fs22.mkdirSync(".claude", { recursive: true });
5973
- fs22.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
5473
+ if (!fs21.existsSync(".claude")) fs21.mkdirSync(".claude", { recursive: true });
5474
+ fs21.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
5974
5475
  }
5975
5476
 
5976
5477
  // src/commands/undo.ts
5977
- import chalk8 from "chalk";
5978
- import ora4 from "ora";
5478
+ import chalk7 from "chalk";
5479
+ import ora3 from "ora";
5979
5480
  function undoCommand() {
5980
- const spinner = ora4("Reverting setup...").start();
5481
+ const spinner = ora3("Reverting setup...").start();
5981
5482
  try {
5982
5483
  const { restored, removed } = undoSetup();
5983
5484
  if (restored.length === 0 && removed.length === 0) {
@@ -5986,27 +5487,27 @@ function undoCommand() {
5986
5487
  }
5987
5488
  spinner.succeed("Setup reverted successfully.\n");
5988
5489
  if (restored.length > 0) {
5989
- console.log(chalk8.cyan(" Restored from backup:"));
5490
+ console.log(chalk7.cyan(" Restored from backup:"));
5990
5491
  for (const file of restored) {
5991
- console.log(` ${chalk8.green("\u21A9")} ${file}`);
5492
+ console.log(` ${chalk7.green("\u21A9")} ${file}`);
5992
5493
  }
5993
5494
  }
5994
5495
  if (removed.length > 0) {
5995
- console.log(chalk8.cyan(" Removed:"));
5496
+ console.log(chalk7.cyan(" Removed:"));
5996
5497
  for (const file of removed) {
5997
- console.log(` ${chalk8.red("\u2717")} ${file}`);
5498
+ console.log(` ${chalk7.red("\u2717")} ${file}`);
5998
5499
  }
5999
5500
  }
6000
5501
  console.log("");
6001
5502
  } catch (err) {
6002
- spinner.fail(chalk8.red(err instanceof Error ? err.message : "Undo failed"));
5503
+ spinner.fail(chalk7.red(err instanceof Error ? err.message : "Undo failed"));
6003
5504
  throw new Error("__exit__");
6004
5505
  }
6005
5506
  }
6006
5507
 
6007
5508
  // src/commands/status.ts
6008
- import chalk9 from "chalk";
6009
- import fs23 from "fs";
5509
+ import chalk8 from "chalk";
5510
+ import fs22 from "fs";
6010
5511
  async function statusCommand(options) {
6011
5512
  const config = loadConfig();
6012
5513
  const manifest = readManifest();
@@ -6019,52 +5520,52 @@ async function statusCommand(options) {
6019
5520
  }, null, 2));
6020
5521
  return;
6021
5522
  }
6022
- console.log(chalk9.bold("\nCaliber Status\n"));
5523
+ console.log(chalk8.bold("\nCaliber Status\n"));
6023
5524
  if (config) {
6024
- console.log(` LLM: ${chalk9.green(config.provider)} (${config.model})`);
5525
+ console.log(` LLM: ${chalk8.green(config.provider)} (${config.model})`);
6025
5526
  } else {
6026
- console.log(` LLM: ${chalk9.yellow("Not configured")} \u2014 run ${chalk9.hex("#83D1EB")("caliber config")}`);
5527
+ console.log(` LLM: ${chalk8.yellow("Not configured")} \u2014 run ${chalk8.hex("#83D1EB")("caliber config")}`);
6027
5528
  }
6028
5529
  if (!manifest) {
6029
- console.log(` Setup: ${chalk9.dim("No setup applied")}`);
6030
- console.log(chalk9.dim("\n Run ") + chalk9.hex("#83D1EB")("caliber onboard") + chalk9.dim(" to get started.\n"));
5530
+ console.log(` Setup: ${chalk8.dim("No setup applied")}`);
5531
+ console.log(chalk8.dim("\n Run ") + chalk8.hex("#83D1EB")("caliber onboard") + chalk8.dim(" to get started.\n"));
6031
5532
  return;
6032
5533
  }
6033
- console.log(` Files managed: ${chalk9.cyan(manifest.entries.length.toString())}`);
5534
+ console.log(` Files managed: ${chalk8.cyan(manifest.entries.length.toString())}`);
6034
5535
  for (const entry of manifest.entries) {
6035
- const exists = fs23.existsSync(entry.path);
6036
- const icon = exists ? chalk9.green("\u2713") : chalk9.red("\u2717");
5536
+ const exists = fs22.existsSync(entry.path);
5537
+ const icon = exists ? chalk8.green("\u2713") : chalk8.red("\u2717");
6037
5538
  console.log(` ${icon} ${entry.path} (${entry.action})`);
6038
5539
  }
6039
5540
  console.log("");
6040
5541
  }
6041
5542
 
6042
5543
  // src/commands/regenerate.ts
6043
- import chalk10 from "chalk";
6044
- import ora5 from "ora";
5544
+ import chalk9 from "chalk";
5545
+ import ora4 from "ora";
6045
5546
  import select5 from "@inquirer/select";
6046
5547
  async function regenerateCommand(options) {
6047
5548
  const config = loadConfig();
6048
5549
  if (!config) {
6049
- console.log(chalk10.red("No LLM provider configured. Run ") + chalk10.hex("#83D1EB")("caliber config") + chalk10.red(" first."));
5550
+ console.log(chalk9.red("No LLM provider configured. Run ") + chalk9.hex("#83D1EB")("caliber config") + chalk9.red(" first."));
6050
5551
  throw new Error("__exit__");
6051
5552
  }
6052
5553
  const manifest = readManifest();
6053
5554
  if (!manifest) {
6054
- console.log(chalk10.yellow("No existing setup found. Run ") + chalk10.hex("#83D1EB")("caliber onboard") + chalk10.yellow(" first."));
5555
+ console.log(chalk9.yellow("No existing setup found. Run ") + chalk9.hex("#83D1EB")("caliber onboard") + chalk9.yellow(" first."));
6055
5556
  throw new Error("__exit__");
6056
5557
  }
6057
5558
  const targetAgent = readState()?.targetAgent ?? ["claude", "cursor"];
6058
- const spinner = ora5("Analyzing project...").start();
5559
+ const spinner = ora4("Analyzing project...").start();
6059
5560
  const fingerprint = await collectFingerprint(process.cwd());
6060
5561
  spinner.succeed("Project analyzed");
6061
5562
  const baselineScore = computeLocalScore(process.cwd(), targetAgent);
6062
5563
  displayScoreSummary(baselineScore);
6063
5564
  if (baselineScore.score === 100) {
6064
- console.log(chalk10.green(" Your setup is already at 100/100 \u2014 nothing to regenerate.\n"));
5565
+ console.log(chalk9.green(" Your setup is already at 100/100 \u2014 nothing to regenerate.\n"));
6065
5566
  return;
6066
5567
  }
6067
- const genSpinner = ora5("Regenerating setup...").start();
5568
+ const genSpinner = ora4("Regenerating setup...").start();
6068
5569
  const genMessages = new SpinnerMessages(genSpinner, GENERATION_MESSAGES, { showElapsedTime: true });
6069
5570
  genMessages.start();
6070
5571
  let generatedSetup = null;
@@ -6102,18 +5603,18 @@ async function regenerateCommand(options) {
6102
5603
  const setupFiles = collectSetupFiles(generatedSetup);
6103
5604
  const staged = stageFiles(setupFiles, process.cwd());
6104
5605
  const totalChanges = staged.newFiles + staged.modifiedFiles;
6105
- console.log(chalk10.dim(`
6106
- ${chalk10.green(`${staged.newFiles} new`)} / ${chalk10.yellow(`${staged.modifiedFiles} modified`)} file${totalChanges !== 1 ? "s" : ""}
5606
+ console.log(chalk9.dim(`
5607
+ ${chalk9.green(`${staged.newFiles} new`)} / ${chalk9.yellow(`${staged.modifiedFiles} modified`)} file${totalChanges !== 1 ? "s" : ""}
6107
5608
  `));
6108
5609
  if (totalChanges === 0) {
6109
- console.log(chalk10.dim(" No changes needed \u2014 your configs are already up to date.\n"));
5610
+ console.log(chalk9.dim(" No changes needed \u2014 your configs are already up to date.\n"));
6110
5611
  cleanupStaging();
6111
5612
  return;
6112
5613
  }
6113
5614
  if (options.dryRun) {
6114
- console.log(chalk10.yellow("[Dry run] Would write:"));
5615
+ console.log(chalk9.yellow("[Dry run] Would write:"));
6115
5616
  for (const f of staged.stagedFiles) {
6116
- console.log(` ${f.isNew ? chalk10.green("+") : chalk10.yellow("~")} ${f.relativePath}`);
5617
+ console.log(` ${f.isNew ? chalk9.green("+") : chalk9.yellow("~")} ${f.relativePath}`);
6117
5618
  }
6118
5619
  cleanupStaging();
6119
5620
  return;
@@ -6132,28 +5633,28 @@ async function regenerateCommand(options) {
6132
5633
  });
6133
5634
  cleanupStaging();
6134
5635
  if (action === "decline") {
6135
- console.log(chalk10.dim("Regeneration cancelled. No files were modified."));
5636
+ console.log(chalk9.dim("Regeneration cancelled. No files were modified."));
6136
5637
  return;
6137
5638
  }
6138
- const writeSpinner = ora5("Writing config files...").start();
5639
+ const writeSpinner = ora4("Writing config files...").start();
6139
5640
  try {
6140
5641
  const result = writeSetup(generatedSetup);
6141
5642
  writeSpinner.succeed("Config files written");
6142
5643
  for (const file of result.written) {
6143
- console.log(` ${chalk10.green("\u2713")} ${file}`);
5644
+ console.log(` ${chalk9.green("\u2713")} ${file}`);
6144
5645
  }
6145
5646
  if (result.deleted.length > 0) {
6146
5647
  for (const file of result.deleted) {
6147
- console.log(` ${chalk10.red("\u2717")} ${file}`);
5648
+ console.log(` ${chalk9.red("\u2717")} ${file}`);
6148
5649
  }
6149
5650
  }
6150
5651
  if (result.backupDir) {
6151
- console.log(chalk10.dim(`
5652
+ console.log(chalk9.dim(`
6152
5653
  Backups saved to ${result.backupDir}`));
6153
5654
  }
6154
5655
  } catch (err) {
6155
5656
  writeSpinner.fail("Failed to write files");
6156
- console.error(chalk10.red(err instanceof Error ? err.message : "Unknown error"));
5657
+ console.error(chalk9.red(err instanceof Error ? err.message : "Unknown error"));
6157
5658
  throw new Error("__exit__");
6158
5659
  }
6159
5660
  const sha = getCurrentHeadSha();
@@ -6165,24 +5666,24 @@ async function regenerateCommand(options) {
6165
5666
  const afterScore = computeLocalScore(process.cwd(), targetAgent);
6166
5667
  if (afterScore.score < baselineScore.score) {
6167
5668
  console.log("");
6168
- console.log(chalk10.yellow(` Score would drop from ${baselineScore.score} to ${afterScore.score} \u2014 reverting changes.`));
5669
+ console.log(chalk9.yellow(` Score would drop from ${baselineScore.score} to ${afterScore.score} \u2014 reverting changes.`));
6169
5670
  try {
6170
5671
  const { restored, removed } = undoSetup();
6171
5672
  if (restored.length > 0 || removed.length > 0) {
6172
- console.log(chalk10.dim(` Reverted ${restored.length + removed.length} file${restored.length + removed.length === 1 ? "" : "s"} from backup.`));
5673
+ console.log(chalk9.dim(` Reverted ${restored.length + removed.length} file${restored.length + removed.length === 1 ? "" : "s"} from backup.`));
6173
5674
  }
6174
5675
  } catch {
6175
5676
  }
6176
- console.log(chalk10.dim(" Run ") + chalk10.hex("#83D1EB")("caliber onboard --force") + chalk10.dim(" to override.\n"));
5677
+ console.log(chalk9.dim(" Run ") + chalk9.hex("#83D1EB")("caliber onboard --force") + chalk9.dim(" to override.\n"));
6177
5678
  return;
6178
5679
  }
6179
5680
  displayScoreDelta(baselineScore, afterScore);
6180
- console.log(chalk10.bold.green(" Regeneration complete!"));
6181
- console.log(chalk10.dim(" Run ") + chalk10.hex("#83D1EB")("caliber undo") + chalk10.dim(" to revert changes.\n"));
5681
+ console.log(chalk9.bold.green(" Regeneration complete!"));
5682
+ console.log(chalk9.dim(" Run ") + chalk9.hex("#83D1EB")("caliber undo") + chalk9.dim(" to revert changes.\n"));
6182
5683
  }
6183
5684
 
6184
5685
  // src/commands/score.ts
6185
- import chalk11 from "chalk";
5686
+ import chalk10 from "chalk";
6186
5687
  async function scoreCommand(options) {
6187
5688
  const dir = process.cwd();
6188
5689
  const target = options.agent ?? readState()?.targetAgent;
@@ -6196,23 +5697,23 @@ async function scoreCommand(options) {
6196
5697
  return;
6197
5698
  }
6198
5699
  displayScore(result);
6199
- const separator = chalk11.gray(" " + "\u2500".repeat(53));
5700
+ const separator = chalk10.gray(" " + "\u2500".repeat(53));
6200
5701
  console.log(separator);
6201
5702
  if (result.score < 40) {
6202
- console.log(chalk11.gray(" Run ") + chalk11.hex("#83D1EB")("caliber onboard") + chalk11.gray(" to generate a complete, optimized setup."));
5703
+ console.log(chalk10.gray(" Run ") + chalk10.hex("#83D1EB")("caliber onboard") + chalk10.gray(" to generate a complete, optimized setup."));
6203
5704
  } else if (result.score < 70) {
6204
- console.log(chalk11.gray(" Run ") + chalk11.hex("#83D1EB")("caliber onboard") + chalk11.gray(" to improve your setup."));
5705
+ console.log(chalk10.gray(" Run ") + chalk10.hex("#83D1EB")("caliber onboard") + chalk10.gray(" to improve your setup."));
6205
5706
  } else {
6206
- console.log(chalk11.green(" Looking good!") + chalk11.gray(" Run ") + chalk11.hex("#83D1EB")("caliber regenerate") + chalk11.gray(" to rebuild from scratch."));
5707
+ console.log(chalk10.green(" Looking good!") + chalk10.gray(" Run ") + chalk10.hex("#83D1EB")("caliber regenerate") + chalk10.gray(" to rebuild from scratch."));
6207
5708
  }
6208
5709
  console.log("");
6209
5710
  }
6210
5711
 
6211
5712
  // src/commands/refresh.ts
6212
- import fs25 from "fs";
6213
- import path19 from "path";
6214
- import chalk12 from "chalk";
6215
- import ora6 from "ora";
5713
+ import fs24 from "fs";
5714
+ import path18 from "path";
5715
+ import chalk11 from "chalk";
5716
+ import ora5 from "ora";
6216
5717
 
6217
5718
  // src/lib/git-diff.ts
6218
5719
  import { execSync as execSync8 } from "child_process";
@@ -6287,37 +5788,37 @@ function collectDiff(lastSha) {
6287
5788
  }
6288
5789
 
6289
5790
  // src/writers/refresh.ts
6290
- import fs24 from "fs";
6291
- import path18 from "path";
5791
+ import fs23 from "fs";
5792
+ import path17 from "path";
6292
5793
  function writeRefreshDocs(docs) {
6293
5794
  const written = [];
6294
5795
  if (docs.claudeMd) {
6295
- fs24.writeFileSync("CLAUDE.md", docs.claudeMd);
5796
+ fs23.writeFileSync("CLAUDE.md", docs.claudeMd);
6296
5797
  written.push("CLAUDE.md");
6297
5798
  }
6298
5799
  if (docs.readmeMd) {
6299
- fs24.writeFileSync("README.md", docs.readmeMd);
5800
+ fs23.writeFileSync("README.md", docs.readmeMd);
6300
5801
  written.push("README.md");
6301
5802
  }
6302
5803
  if (docs.cursorrules) {
6303
- fs24.writeFileSync(".cursorrules", docs.cursorrules);
5804
+ fs23.writeFileSync(".cursorrules", docs.cursorrules);
6304
5805
  written.push(".cursorrules");
6305
5806
  }
6306
5807
  if (docs.cursorRules) {
6307
- const rulesDir = path18.join(".cursor", "rules");
6308
- if (!fs24.existsSync(rulesDir)) fs24.mkdirSync(rulesDir, { recursive: true });
5808
+ const rulesDir = path17.join(".cursor", "rules");
5809
+ if (!fs23.existsSync(rulesDir)) fs23.mkdirSync(rulesDir, { recursive: true });
6309
5810
  for (const rule of docs.cursorRules) {
6310
- const filePath = path18.join(rulesDir, rule.filename);
6311
- fs24.writeFileSync(filePath, rule.content);
5811
+ const filePath = path17.join(rulesDir, rule.filename);
5812
+ fs23.writeFileSync(filePath, rule.content);
6312
5813
  written.push(filePath);
6313
5814
  }
6314
5815
  }
6315
5816
  if (docs.claudeSkills) {
6316
- const skillsDir = path18.join(".claude", "skills");
6317
- if (!fs24.existsSync(skillsDir)) fs24.mkdirSync(skillsDir, { recursive: true });
5817
+ const skillsDir = path17.join(".claude", "skills");
5818
+ if (!fs23.existsSync(skillsDir)) fs23.mkdirSync(skillsDir, { recursive: true });
6318
5819
  for (const skill of docs.claudeSkills) {
6319
- const filePath = path18.join(skillsDir, skill.filename);
6320
- fs24.writeFileSync(filePath, skill.content);
5820
+ const filePath = path17.join(skillsDir, skill.filename);
5821
+ fs23.writeFileSync(filePath, skill.content);
6321
5822
  written.push(filePath);
6322
5823
  }
6323
5824
  }
@@ -6394,11 +5895,11 @@ function log(quiet, ...args) {
6394
5895
  function discoverGitRepos(parentDir) {
6395
5896
  const repos = [];
6396
5897
  try {
6397
- const entries = fs25.readdirSync(parentDir, { withFileTypes: true });
5898
+ const entries = fs24.readdirSync(parentDir, { withFileTypes: true });
6398
5899
  for (const entry of entries) {
6399
5900
  if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
6400
- const childPath = path19.join(parentDir, entry.name);
6401
- if (fs25.existsSync(path19.join(childPath, ".git"))) {
5901
+ const childPath = path18.join(parentDir, entry.name);
5902
+ if (fs24.existsSync(path18.join(childPath, ".git"))) {
6402
5903
  repos.push(childPath);
6403
5904
  }
6404
5905
  }
@@ -6408,7 +5909,7 @@ function discoverGitRepos(parentDir) {
6408
5909
  }
6409
5910
  async function refreshSingleRepo(repoDir, options) {
6410
5911
  const quiet = !!options.quiet;
6411
- const prefix = options.label ? `${chalk12.bold(options.label)} ` : "";
5912
+ const prefix = options.label ? `${chalk11.bold(options.label)} ` : "";
6412
5913
  const state = readState();
6413
5914
  const lastSha = state?.lastRefreshSha ?? null;
6414
5915
  const diff = collectDiff(lastSha);
@@ -6417,10 +5918,10 @@ async function refreshSingleRepo(repoDir, options) {
6417
5918
  if (currentSha) {
6418
5919
  writeState({ lastRefreshSha: currentSha, lastRefreshTimestamp: (/* @__PURE__ */ new Date()).toISOString() });
6419
5920
  }
6420
- log(quiet, chalk12.dim(`${prefix}No changes since last refresh.`));
5921
+ log(quiet, chalk11.dim(`${prefix}No changes since last refresh.`));
6421
5922
  return;
6422
5923
  }
6423
- const spinner = quiet ? null : ora6(`${prefix}Analyzing changes...`).start();
5924
+ const spinner = quiet ? null : ora5(`${prefix}Analyzing changes...`).start();
6424
5925
  const existingDocs = readExistingConfigs(repoDir);
6425
5926
  const fingerprint = await collectFingerprint(repoDir);
6426
5927
  const projectContext = {
@@ -6449,10 +5950,10 @@ async function refreshSingleRepo(repoDir, options) {
6449
5950
  if (options.dryRun) {
6450
5951
  spinner?.info(`${prefix}Dry run \u2014 would update:`);
6451
5952
  for (const doc of response.docsUpdated) {
6452
- console.log(` ${chalk12.yellow("~")} ${doc}`);
5953
+ console.log(` ${chalk11.yellow("~")} ${doc}`);
6453
5954
  }
6454
5955
  if (response.changesSummary) {
6455
- console.log(chalk12.dim(`
5956
+ console.log(chalk11.dim(`
6456
5957
  ${response.changesSummary}`));
6457
5958
  }
6458
5959
  return;
@@ -6460,10 +5961,10 @@ async function refreshSingleRepo(repoDir, options) {
6460
5961
  const written = writeRefreshDocs(response.updatedDocs);
6461
5962
  spinner?.succeed(`${prefix}Updated ${written.length} doc${written.length === 1 ? "" : "s"}`);
6462
5963
  for (const file of written) {
6463
- log(quiet, ` ${chalk12.green("\u2713")} ${file}`);
5964
+ log(quiet, ` ${chalk11.green("\u2713")} ${file}`);
6464
5965
  }
6465
5966
  if (response.changesSummary) {
6466
- log(quiet, chalk12.dim(`
5967
+ log(quiet, chalk11.dim(`
6467
5968
  ${response.changesSummary}`));
6468
5969
  }
6469
5970
  if (currentSha) {
@@ -6476,7 +5977,7 @@ async function refreshCommand(options) {
6476
5977
  const config = loadConfig();
6477
5978
  if (!config) {
6478
5979
  if (quiet) return;
6479
- console.log(chalk12.red("No LLM provider configured. Run ") + chalk12.hex("#83D1EB")("caliber config") + chalk12.red(" (e.g. choose Cursor) or set an API key."));
5980
+ console.log(chalk11.red("No LLM provider configured. Run ") + chalk11.hex("#83D1EB")("caliber config") + chalk11.red(" (e.g. choose Cursor) or set an API key."));
6480
5981
  throw new Error("__exit__");
6481
5982
  }
6482
5983
  if (isGitRepo()) {
@@ -6486,20 +5987,20 @@ async function refreshCommand(options) {
6486
5987
  const repos = discoverGitRepos(process.cwd());
6487
5988
  if (repos.length === 0) {
6488
5989
  if (quiet) return;
6489
- console.log(chalk12.red("Not inside a git repository and no git repos found in child directories."));
5990
+ console.log(chalk11.red("Not inside a git repository and no git repos found in child directories."));
6490
5991
  throw new Error("__exit__");
6491
5992
  }
6492
- log(quiet, chalk12.dim(`Found ${repos.length} git repo${repos.length === 1 ? "" : "s"}
5993
+ log(quiet, chalk11.dim(`Found ${repos.length} git repo${repos.length === 1 ? "" : "s"}
6493
5994
  `));
6494
5995
  const originalDir = process.cwd();
6495
5996
  for (const repo of repos) {
6496
- const repoName = path19.basename(repo);
5997
+ const repoName = path18.basename(repo);
6497
5998
  try {
6498
5999
  process.chdir(repo);
6499
6000
  await refreshSingleRepo(repo, { ...options, label: repoName });
6500
6001
  } catch (err) {
6501
6002
  if (err instanceof Error && err.message === "__exit__") continue;
6502
- log(quiet, chalk12.yellow(`${repoName}: refresh failed \u2014 ${err instanceof Error ? err.message : "unknown error"}`));
6003
+ log(quiet, chalk11.yellow(`${repoName}: refresh failed \u2014 ${err instanceof Error ? err.message : "unknown error"}`));
6503
6004
  }
6504
6005
  }
6505
6006
  process.chdir(originalDir);
@@ -6507,13 +6008,13 @@ async function refreshCommand(options) {
6507
6008
  if (err instanceof Error && err.message === "__exit__") throw err;
6508
6009
  if (quiet) return;
6509
6010
  const msg = err instanceof Error ? err.message : "Unknown error";
6510
- console.log(chalk12.red(`Refresh failed: ${msg}`));
6011
+ console.log(chalk11.red(`Refresh failed: ${msg}`));
6511
6012
  throw new Error("__exit__");
6512
6013
  }
6513
6014
  }
6514
6015
 
6515
6016
  // src/commands/hooks.ts
6516
- import chalk13 from "chalk";
6017
+ import chalk12 from "chalk";
6517
6018
  var HOOKS = [
6518
6019
  {
6519
6020
  id: "session-end",
@@ -6533,13 +6034,13 @@ var HOOKS = [
6533
6034
  }
6534
6035
  ];
6535
6036
  function printStatus() {
6536
- console.log(chalk13.bold("\n Hooks\n"));
6037
+ console.log(chalk12.bold("\n Hooks\n"));
6537
6038
  for (const hook of HOOKS) {
6538
6039
  const installed = hook.isInstalled();
6539
- const icon = installed ? chalk13.green("\u2713") : chalk13.dim("\u2717");
6540
- const state = installed ? chalk13.green("enabled") : chalk13.dim("disabled");
6040
+ const icon = installed ? chalk12.green("\u2713") : chalk12.dim("\u2717");
6041
+ const state = installed ? chalk12.green("enabled") : chalk12.dim("disabled");
6541
6042
  console.log(` ${icon} ${hook.label.padEnd(26)} ${state}`);
6542
- console.log(chalk13.dim(` ${hook.description}`));
6043
+ console.log(chalk12.dim(` ${hook.description}`));
6543
6044
  }
6544
6045
  console.log("");
6545
6046
  }
@@ -6548,9 +6049,9 @@ async function hooksCommand(options) {
6548
6049
  for (const hook of HOOKS) {
6549
6050
  const result = hook.install();
6550
6051
  if (result.alreadyInstalled) {
6551
- console.log(chalk13.dim(` ${hook.label} already enabled.`));
6052
+ console.log(chalk12.dim(` ${hook.label} already enabled.`));
6552
6053
  } else {
6553
- console.log(chalk13.green(" \u2713") + ` ${hook.label} enabled`);
6054
+ console.log(chalk12.green(" \u2713") + ` ${hook.label} enabled`);
6554
6055
  }
6555
6056
  }
6556
6057
  return;
@@ -6559,9 +6060,9 @@ async function hooksCommand(options) {
6559
6060
  for (const hook of HOOKS) {
6560
6061
  const result = hook.remove();
6561
6062
  if (result.notFound) {
6562
- console.log(chalk13.dim(` ${hook.label} already disabled.`));
6063
+ console.log(chalk12.dim(` ${hook.label} already disabled.`));
6563
6064
  } else {
6564
- console.log(chalk13.green(" \u2713") + ` ${hook.label} removed`);
6065
+ console.log(chalk12.green(" \u2713") + ` ${hook.label} removed`);
6565
6066
  }
6566
6067
  }
6567
6068
  return;
@@ -6576,18 +6077,18 @@ async function hooksCommand(options) {
6576
6077
  const states = HOOKS.map((h) => h.isInstalled());
6577
6078
  function render() {
6578
6079
  const lines = [];
6579
- lines.push(chalk13.bold(" Hooks"));
6080
+ lines.push(chalk12.bold(" Hooks"));
6580
6081
  lines.push("");
6581
6082
  for (let i = 0; i < HOOKS.length; i++) {
6582
6083
  const hook = HOOKS[i];
6583
6084
  const enabled = states[i];
6584
- const toggle = enabled ? chalk13.green("[on] ") : chalk13.dim("[off]");
6585
- const ptr = i === cursor ? chalk13.cyan(">") : " ";
6085
+ const toggle = enabled ? chalk12.green("[on] ") : chalk12.dim("[off]");
6086
+ const ptr = i === cursor ? chalk12.cyan(">") : " ";
6586
6087
  lines.push(` ${ptr} ${toggle} ${hook.label}`);
6587
- lines.push(chalk13.dim(` ${hook.description}`));
6088
+ lines.push(chalk12.dim(` ${hook.description}`));
6588
6089
  }
6589
6090
  lines.push("");
6590
- lines.push(chalk13.dim(" \u2191\u2193 navigate \u23B5 toggle a all on n all off \u23CE apply q cancel"));
6091
+ lines.push(chalk12.dim(" \u2191\u2193 navigate \u23B5 toggle a all on n all off \u23CE apply q cancel"));
6591
6092
  return lines.join("\n");
6592
6093
  }
6593
6094
  function draw(initial) {
@@ -6618,16 +6119,16 @@ async function hooksCommand(options) {
6618
6119
  const wantEnabled = states[i];
6619
6120
  if (wantEnabled && !wasInstalled) {
6620
6121
  hook.install();
6621
- console.log(chalk13.green(" \u2713") + ` ${hook.label} enabled`);
6122
+ console.log(chalk12.green(" \u2713") + ` ${hook.label} enabled`);
6622
6123
  changed++;
6623
6124
  } else if (!wantEnabled && wasInstalled) {
6624
6125
  hook.remove();
6625
- console.log(chalk13.green(" \u2713") + ` ${hook.label} disabled`);
6126
+ console.log(chalk12.green(" \u2713") + ` ${hook.label} disabled`);
6626
6127
  changed++;
6627
6128
  }
6628
6129
  }
6629
6130
  if (changed === 0) {
6630
- console.log(chalk13.dim(" No changes."));
6131
+ console.log(chalk12.dim(" No changes."));
6631
6132
  }
6632
6133
  console.log("");
6633
6134
  }
@@ -6663,7 +6164,7 @@ async function hooksCommand(options) {
6663
6164
  case "\x1B":
6664
6165
  case "":
6665
6166
  cleanup();
6666
- console.log(chalk13.dim("\n Cancelled.\n"));
6167
+ console.log(chalk12.dim("\n Cancelled.\n"));
6667
6168
  resolve2();
6668
6169
  break;
6669
6170
  }
@@ -6673,48 +6174,48 @@ async function hooksCommand(options) {
6673
6174
  }
6674
6175
 
6675
6176
  // src/commands/config.ts
6676
- import chalk14 from "chalk";
6177
+ import chalk13 from "chalk";
6677
6178
  async function configCommand() {
6678
6179
  const existing = loadConfig();
6679
6180
  if (existing) {
6680
6181
  const displayModel = existing.model === "default" && existing.provider === "claude-cli" ? process.env.ANTHROPIC_MODEL || "default (inherited from Claude Code)" : existing.model;
6681
6182
  const fastModel = getFastModel();
6682
- console.log(chalk14.bold("\nCurrent Configuration\n"));
6683
- console.log(` Provider: ${chalk14.cyan(existing.provider)}`);
6684
- console.log(` Model: ${chalk14.cyan(displayModel)}`);
6183
+ console.log(chalk13.bold("\nCurrent Configuration\n"));
6184
+ console.log(` Provider: ${chalk13.cyan(existing.provider)}`);
6185
+ console.log(` Model: ${chalk13.cyan(displayModel)}`);
6685
6186
  if (fastModel) {
6686
- console.log(` Scan: ${chalk14.cyan(fastModel)}`);
6187
+ console.log(` Scan: ${chalk13.cyan(fastModel)}`);
6687
6188
  }
6688
6189
  if (existing.apiKey) {
6689
6190
  const masked = existing.apiKey.slice(0, 8) + "..." + existing.apiKey.slice(-4);
6690
- console.log(` API Key: ${chalk14.dim(masked)}`);
6191
+ console.log(` API Key: ${chalk13.dim(masked)}`);
6691
6192
  }
6692
6193
  if (existing.provider === "cursor") {
6693
- console.log(` Seat: ${chalk14.dim("Cursor (agent acp)")}`);
6194
+ console.log(` Seat: ${chalk13.dim("Cursor (agent acp)")}`);
6694
6195
  }
6695
6196
  if (existing.provider === "claude-cli") {
6696
- console.log(` Seat: ${chalk14.dim("Claude Code (claude -p)")}`);
6197
+ console.log(` Seat: ${chalk13.dim("Claude Code (claude -p)")}`);
6697
6198
  }
6698
6199
  if (existing.baseUrl) {
6699
- console.log(` Base URL: ${chalk14.dim(existing.baseUrl)}`);
6200
+ console.log(` Base URL: ${chalk13.dim(existing.baseUrl)}`);
6700
6201
  }
6701
6202
  if (existing.vertexProjectId) {
6702
- console.log(` Vertex Project: ${chalk14.dim(existing.vertexProjectId)}`);
6703
- console.log(` Vertex Region: ${chalk14.dim(existing.vertexRegion || "us-east5")}`);
6203
+ console.log(` Vertex Project: ${chalk13.dim(existing.vertexProjectId)}`);
6204
+ console.log(` Vertex Region: ${chalk13.dim(existing.vertexRegion || "us-east5")}`);
6704
6205
  }
6705
- console.log(` Source: ${chalk14.dim(process.env.ANTHROPIC_API_KEY || process.env.OPENAI_API_KEY || process.env.VERTEX_PROJECT_ID || process.env.CALIBER_USE_CURSOR_SEAT || process.env.CALIBER_USE_CLAUDE_CLI ? "environment variables" : getConfigFilePath())}`);
6206
+ console.log(` Source: ${chalk13.dim(process.env.ANTHROPIC_API_KEY || process.env.OPENAI_API_KEY || process.env.VERTEX_PROJECT_ID || process.env.CALIBER_USE_CURSOR_SEAT || process.env.CALIBER_USE_CLAUDE_CLI ? "environment variables" : getConfigFilePath())}`);
6706
6207
  console.log("");
6707
6208
  }
6708
6209
  await runInteractiveProviderSetup();
6709
- console.log(chalk14.green("\n\u2713 Configuration saved"));
6710
- console.log(chalk14.dim(` ${getConfigFilePath()}
6210
+ console.log(chalk13.green("\n\u2713 Configuration saved"));
6211
+ console.log(chalk13.dim(` ${getConfigFilePath()}
6711
6212
  `));
6712
- console.log(chalk14.dim(" You can also set environment variables instead:"));
6713
- console.log(chalk14.dim(" ANTHROPIC_API_KEY, OPENAI_API_KEY, VERTEX_PROJECT_ID, CALIBER_USE_CURSOR_SEAT=1, or CALIBER_USE_CLAUDE_CLI=1\n"));
6213
+ console.log(chalk13.dim(" You can also set environment variables instead:"));
6214
+ console.log(chalk13.dim(" ANTHROPIC_API_KEY, OPENAI_API_KEY, VERTEX_PROJECT_ID, CALIBER_USE_CURSOR_SEAT=1, or CALIBER_USE_CLAUDE_CLI=1\n"));
6714
6215
  }
6715
6216
 
6716
6217
  // src/commands/learn.ts
6717
- import chalk15 from "chalk";
6218
+ import chalk14 from "chalk";
6718
6219
 
6719
6220
  // src/learner/stdin.ts
6720
6221
  var STDIN_TIMEOUT_MS = 5e3;
@@ -6745,8 +6246,8 @@ function readStdin() {
6745
6246
 
6746
6247
  // src/learner/storage.ts
6747
6248
  init_constants();
6748
- import fs26 from "fs";
6749
- import path20 from "path";
6249
+ import fs25 from "fs";
6250
+ import path19 from "path";
6750
6251
  var MAX_RESPONSE_LENGTH = 2e3;
6751
6252
  var DEFAULT_STATE = {
6752
6253
  sessionId: null,
@@ -6754,15 +6255,15 @@ var DEFAULT_STATE = {
6754
6255
  lastAnalysisTimestamp: null
6755
6256
  };
6756
6257
  function ensureLearningDir() {
6757
- if (!fs26.existsSync(LEARNING_DIR)) {
6758
- fs26.mkdirSync(LEARNING_DIR, { recursive: true });
6258
+ if (!fs25.existsSync(LEARNING_DIR)) {
6259
+ fs25.mkdirSync(LEARNING_DIR, { recursive: true });
6759
6260
  }
6760
6261
  }
6761
6262
  function sessionFilePath() {
6762
- return path20.join(LEARNING_DIR, LEARNING_SESSION_FILE);
6263
+ return path19.join(LEARNING_DIR, LEARNING_SESSION_FILE);
6763
6264
  }
6764
6265
  function stateFilePath() {
6765
- return path20.join(LEARNING_DIR, LEARNING_STATE_FILE);
6266
+ return path19.join(LEARNING_DIR, LEARNING_STATE_FILE);
6766
6267
  }
6767
6268
  function truncateResponse(response) {
6768
6269
  const str = JSON.stringify(response);
@@ -6773,50 +6274,50 @@ function appendEvent(event) {
6773
6274
  ensureLearningDir();
6774
6275
  const truncated = { ...event, tool_response: truncateResponse(event.tool_response) };
6775
6276
  const filePath = sessionFilePath();
6776
- fs26.appendFileSync(filePath, JSON.stringify(truncated) + "\n");
6277
+ fs25.appendFileSync(filePath, JSON.stringify(truncated) + "\n");
6777
6278
  const count = getEventCount();
6778
6279
  if (count > LEARNING_MAX_EVENTS) {
6779
- const lines = fs26.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
6280
+ const lines = fs25.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
6780
6281
  const kept = lines.slice(lines.length - LEARNING_MAX_EVENTS);
6781
- fs26.writeFileSync(filePath, kept.join("\n") + "\n");
6282
+ fs25.writeFileSync(filePath, kept.join("\n") + "\n");
6782
6283
  }
6783
6284
  }
6784
6285
  function readAllEvents() {
6785
6286
  const filePath = sessionFilePath();
6786
- if (!fs26.existsSync(filePath)) return [];
6787
- const lines = fs26.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
6287
+ if (!fs25.existsSync(filePath)) return [];
6288
+ const lines = fs25.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
6788
6289
  return lines.map((line) => JSON.parse(line));
6789
6290
  }
6790
6291
  function getEventCount() {
6791
6292
  const filePath = sessionFilePath();
6792
- if (!fs26.existsSync(filePath)) return 0;
6793
- const content = fs26.readFileSync(filePath, "utf-8");
6293
+ if (!fs25.existsSync(filePath)) return 0;
6294
+ const content = fs25.readFileSync(filePath, "utf-8");
6794
6295
  return content.split("\n").filter(Boolean).length;
6795
6296
  }
6796
6297
  function clearSession() {
6797
6298
  const filePath = sessionFilePath();
6798
- if (fs26.existsSync(filePath)) fs26.unlinkSync(filePath);
6299
+ if (fs25.existsSync(filePath)) fs25.unlinkSync(filePath);
6799
6300
  }
6800
6301
  function readState2() {
6801
6302
  const filePath = stateFilePath();
6802
- if (!fs26.existsSync(filePath)) return { ...DEFAULT_STATE };
6303
+ if (!fs25.existsSync(filePath)) return { ...DEFAULT_STATE };
6803
6304
  try {
6804
- return JSON.parse(fs26.readFileSync(filePath, "utf-8"));
6305
+ return JSON.parse(fs25.readFileSync(filePath, "utf-8"));
6805
6306
  } catch {
6806
6307
  return { ...DEFAULT_STATE };
6807
6308
  }
6808
6309
  }
6809
6310
  function writeState2(state) {
6810
6311
  ensureLearningDir();
6811
- fs26.writeFileSync(stateFilePath(), JSON.stringify(state, null, 2));
6312
+ fs25.writeFileSync(stateFilePath(), JSON.stringify(state, null, 2));
6812
6313
  }
6813
6314
  function resetState() {
6814
6315
  writeState2({ ...DEFAULT_STATE });
6815
6316
  }
6816
6317
 
6817
6318
  // src/learner/writer.ts
6818
- import fs27 from "fs";
6819
- import path21 from "path";
6319
+ import fs26 from "fs";
6320
+ import path20 from "path";
6820
6321
  var LEARNED_START = "<!-- caliber:learned -->";
6821
6322
  var LEARNED_END = "<!-- /caliber:learned -->";
6822
6323
  function writeLearnedContent(update) {
@@ -6836,8 +6337,8 @@ function writeLearnedContent(update) {
6836
6337
  function writeLearnedSection(content) {
6837
6338
  const claudeMdPath = "CLAUDE.md";
6838
6339
  let existing = "";
6839
- if (fs27.existsSync(claudeMdPath)) {
6840
- existing = fs27.readFileSync(claudeMdPath, "utf-8");
6340
+ if (fs26.existsSync(claudeMdPath)) {
6341
+ existing = fs26.readFileSync(claudeMdPath, "utf-8");
6841
6342
  }
6842
6343
  const section = `${LEARNED_START}
6843
6344
  ${content}
@@ -6851,15 +6352,15 @@ ${LEARNED_END}`;
6851
6352
  const separator = existing.endsWith("\n") || existing === "" ? "" : "\n";
6852
6353
  updated = existing + separator + "\n" + section + "\n";
6853
6354
  }
6854
- fs27.writeFileSync(claudeMdPath, updated);
6355
+ fs26.writeFileSync(claudeMdPath, updated);
6855
6356
  }
6856
6357
  function writeLearnedSkill(skill) {
6857
- const skillDir = path21.join(".claude", "skills", skill.name);
6858
- if (!fs27.existsSync(skillDir)) fs27.mkdirSync(skillDir, { recursive: true });
6859
- const skillPath = path21.join(skillDir, "SKILL.md");
6860
- if (!skill.isNew && fs27.existsSync(skillPath)) {
6861
- const existing = fs27.readFileSync(skillPath, "utf-8");
6862
- fs27.writeFileSync(skillPath, existing.trimEnd() + "\n\n" + skill.content);
6358
+ const skillDir = path20.join(".claude", "skills", skill.name);
6359
+ if (!fs26.existsSync(skillDir)) fs26.mkdirSync(skillDir, { recursive: true });
6360
+ const skillPath = path20.join(skillDir, "SKILL.md");
6361
+ if (!skill.isNew && fs26.existsSync(skillPath)) {
6362
+ const existing = fs26.readFileSync(skillPath, "utf-8");
6363
+ fs26.writeFileSync(skillPath, existing.trimEnd() + "\n\n" + skill.content);
6863
6364
  } else {
6864
6365
  const frontmatter = [
6865
6366
  "---",
@@ -6868,14 +6369,14 @@ function writeLearnedSkill(skill) {
6868
6369
  "---",
6869
6370
  ""
6870
6371
  ].join("\n");
6871
- fs27.writeFileSync(skillPath, frontmatter + skill.content);
6372
+ fs26.writeFileSync(skillPath, frontmatter + skill.content);
6872
6373
  }
6873
6374
  return skillPath;
6874
6375
  }
6875
6376
  function readLearnedSection() {
6876
6377
  const claudeMdPath = "CLAUDE.md";
6877
- if (!fs27.existsSync(claudeMdPath)) return null;
6878
- const content = fs27.readFileSync(claudeMdPath, "utf-8");
6378
+ if (!fs26.existsSync(claudeMdPath)) return null;
6379
+ const content = fs26.readFileSync(claudeMdPath, "utf-8");
6879
6380
  const startIdx = content.indexOf(LEARNED_START);
6880
6381
  const endIdx = content.indexOf(LEARNED_END);
6881
6382
  if (startIdx === -1 || endIdx === -1) return null;
@@ -6945,10 +6446,12 @@ ${skillsSummary}`);
6945
6446
  const prompt = `${contextParts.length ? contextParts.join("\n\n---\n\n") + "\n\n---\n\n" : ""}## Tool Events from Session (${fittedEvents.length} events)
6946
6447
 
6947
6448
  ${eventsText}`;
6449
+ const fastModel = getFastModel();
6948
6450
  const raw = await llmCall({
6949
6451
  system: LEARN_SYSTEM_PROMPT,
6950
6452
  prompt,
6951
- maxTokens: 4096
6453
+ maxTokens: 4096,
6454
+ ...fastModel ? { model: fastModel } : {}
6952
6455
  });
6953
6456
  return parseAnalysisResponse(raw);
6954
6457
  }
@@ -7015,53 +6518,53 @@ async function learnFinalizeCommand() {
7015
6518
  async function learnInstallCommand() {
7016
6519
  const result = installLearningHooks();
7017
6520
  if (result.alreadyInstalled) {
7018
- console.log(chalk15.dim("Learning hooks already installed."));
6521
+ console.log(chalk14.dim("Learning hooks already installed."));
7019
6522
  return;
7020
6523
  }
7021
- console.log(chalk15.green("\u2713") + " Learning hooks installed in .claude/settings.json");
7022
- console.log(chalk15.dim(" PostToolUse, PostToolUseFailure, and SessionEnd hooks active."));
7023
- console.log(chalk15.dim(" Session learnings will be written to CLAUDE.md and skills."));
6524
+ console.log(chalk14.green("\u2713") + " Learning hooks installed in .claude/settings.json");
6525
+ console.log(chalk14.dim(" PostToolUse, PostToolUseFailure, and SessionEnd hooks active."));
6526
+ console.log(chalk14.dim(" Session learnings will be written to CLAUDE.md and skills."));
7024
6527
  }
7025
6528
  async function learnRemoveCommand() {
7026
6529
  const result = removeLearningHooks();
7027
6530
  if (result.notFound) {
7028
- console.log(chalk15.dim("Learning hooks not found."));
6531
+ console.log(chalk14.dim("Learning hooks not found."));
7029
6532
  return;
7030
6533
  }
7031
- console.log(chalk15.green("\u2713") + " Learning hooks removed from .claude/settings.json");
6534
+ console.log(chalk14.green("\u2713") + " Learning hooks removed from .claude/settings.json");
7032
6535
  }
7033
6536
  async function learnStatusCommand() {
7034
6537
  const installed = areLearningHooksInstalled();
7035
6538
  const state = readState2();
7036
6539
  const eventCount = getEventCount();
7037
- console.log(chalk15.bold("Session Learning Status"));
6540
+ console.log(chalk14.bold("Session Learning Status"));
7038
6541
  console.log();
7039
6542
  if (installed) {
7040
- console.log(chalk15.green("\u2713") + " Learning hooks are " + chalk15.green("installed"));
6543
+ console.log(chalk14.green("\u2713") + " Learning hooks are " + chalk14.green("installed"));
7041
6544
  } else {
7042
- console.log(chalk15.dim("\u2717") + " Learning hooks are " + chalk15.yellow("not installed"));
7043
- console.log(chalk15.dim(" Run `caliber learn install` to enable session learning."));
6545
+ console.log(chalk14.dim("\u2717") + " Learning hooks are " + chalk14.yellow("not installed"));
6546
+ console.log(chalk14.dim(" Run `caliber learn install` to enable session learning."));
7044
6547
  }
7045
6548
  console.log();
7046
- console.log(`Events recorded: ${chalk15.cyan(String(eventCount))}`);
7047
- console.log(`Total this session: ${chalk15.cyan(String(state.eventCount))}`);
6549
+ console.log(`Events recorded: ${chalk14.cyan(String(eventCount))}`);
6550
+ console.log(`Total this session: ${chalk14.cyan(String(state.eventCount))}`);
7048
6551
  if (state.lastAnalysisTimestamp) {
7049
- console.log(`Last analysis: ${chalk15.cyan(state.lastAnalysisTimestamp)}`);
6552
+ console.log(`Last analysis: ${chalk14.cyan(state.lastAnalysisTimestamp)}`);
7050
6553
  } else {
7051
- console.log(`Last analysis: ${chalk15.dim("none")}`);
6554
+ console.log(`Last analysis: ${chalk14.dim("none")}`);
7052
6555
  }
7053
6556
  const learnedSection = readLearnedSection();
7054
6557
  if (learnedSection) {
7055
6558
  const lineCount = learnedSection.split("\n").filter(Boolean).length;
7056
6559
  console.log(`
7057
- Learned items in CLAUDE.md: ${chalk15.cyan(String(lineCount))}`);
6560
+ Learned items in CLAUDE.md: ${chalk14.cyan(String(lineCount))}`);
7058
6561
  }
7059
6562
  }
7060
6563
 
7061
6564
  // src/cli.ts
7062
- var __dirname = path22.dirname(fileURLToPath(import.meta.url));
6565
+ var __dirname = path21.dirname(fileURLToPath(import.meta.url));
7063
6566
  var pkg = JSON.parse(
7064
- fs28.readFileSync(path22.resolve(__dirname, "..", "package.json"), "utf-8")
6567
+ fs27.readFileSync(path21.resolve(__dirname, "..", "package.json"), "utf-8")
7065
6568
  );
7066
6569
  var program = new Command();
7067
6570
  var displayVersion = process.env.CALIBER_LOCAL ? `${pkg.version}-local` : pkg.version;
@@ -7094,22 +6597,22 @@ learn.command("remove").description("Remove learning hooks from .claude/settings
7094
6597
  learn.command("status").description("Show learning system status").action(learnStatusCommand);
7095
6598
 
7096
6599
  // src/utils/version-check.ts
7097
- import fs29 from "fs";
7098
- import path23 from "path";
6600
+ import fs28 from "fs";
6601
+ import path22 from "path";
7099
6602
  import { fileURLToPath as fileURLToPath2 } from "url";
7100
6603
  import { execSync as execSync9 } from "child_process";
7101
- import chalk16 from "chalk";
7102
- import ora7 from "ora";
6604
+ import chalk15 from "chalk";
6605
+ import ora6 from "ora";
7103
6606
  import confirm from "@inquirer/confirm";
7104
- var __dirname_vc = path23.dirname(fileURLToPath2(import.meta.url));
6607
+ var __dirname_vc = path22.dirname(fileURLToPath2(import.meta.url));
7105
6608
  var pkg2 = JSON.parse(
7106
- fs29.readFileSync(path23.resolve(__dirname_vc, "..", "package.json"), "utf-8")
6609
+ fs28.readFileSync(path22.resolve(__dirname_vc, "..", "package.json"), "utf-8")
7107
6610
  );
7108
6611
  function getInstalledVersion() {
7109
6612
  try {
7110
6613
  const globalRoot = execSync9("npm root -g", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
7111
- const pkgPath = path23.join(globalRoot, "@rely-ai", "caliber", "package.json");
7112
- return JSON.parse(fs29.readFileSync(pkgPath, "utf-8")).version;
6614
+ const pkgPath = path22.join(globalRoot, "@rely-ai", "caliber", "package.json");
6615
+ return JSON.parse(fs28.readFileSync(pkgPath, "utf-8")).version;
7113
6616
  } catch {
7114
6617
  return null;
7115
6618
  }
@@ -7132,17 +6635,17 @@ async function checkForUpdates() {
7132
6635
  const isInteractive = process.stdin.isTTY === true;
7133
6636
  if (!isInteractive) {
7134
6637
  console.log(
7135
- chalk16.yellow(
6638
+ chalk15.yellow(
7136
6639
  `
7137
6640
  Update available: ${current} -> ${latest}
7138
- Run ${chalk16.bold("npm install -g @rely-ai/caliber")} to upgrade.
6641
+ Run ${chalk15.bold("npm install -g @rely-ai/caliber")} to upgrade.
7139
6642
  `
7140
6643
  )
7141
6644
  );
7142
6645
  return;
7143
6646
  }
7144
6647
  console.log(
7145
- chalk16.yellow(`
6648
+ chalk15.yellow(`
7146
6649
  Update available: ${current} -> ${latest}`)
7147
6650
  );
7148
6651
  const shouldUpdate = await confirm({ message: "Would you like to update now? (Y/n)", default: true });
@@ -7150,7 +6653,7 @@ Update available: ${current} -> ${latest}`)
7150
6653
  console.log();
7151
6654
  return;
7152
6655
  }
7153
- const spinner = ora7("Updating caliber...").start();
6656
+ const spinner = ora6("Updating caliber...").start();
7154
6657
  try {
7155
6658
  execSync9(`npm install -g @rely-ai/caliber@${latest}`, {
7156
6659
  stdio: "pipe",
@@ -7160,13 +6663,13 @@ Update available: ${current} -> ${latest}`)
7160
6663
  const installed = getInstalledVersion();
7161
6664
  if (installed !== latest) {
7162
6665
  spinner.fail(`Update incomplete \u2014 got ${installed ?? "unknown"}, expected ${latest}`);
7163
- console.log(chalk16.yellow(`Run ${chalk16.bold(`npm install -g @rely-ai/caliber@${latest}`)} manually.
6666
+ console.log(chalk15.yellow(`Run ${chalk15.bold(`npm install -g @rely-ai/caliber@${latest}`)} manually.
7164
6667
  `));
7165
6668
  return;
7166
6669
  }
7167
- spinner.succeed(chalk16.green(`Updated to ${latest}`));
6670
+ spinner.succeed(chalk15.green(`Updated to ${latest}`));
7168
6671
  const args = process.argv.slice(2);
7169
- console.log(chalk16.dim(`
6672
+ console.log(chalk15.dim(`
7170
6673
  Restarting: caliber ${args.join(" ")}
7171
6674
  `));
7172
6675
  execSync9(`caliber ${args.map((a) => JSON.stringify(a)).join(" ")}`, {
@@ -7179,11 +6682,11 @@ Restarting: caliber ${args.join(" ")}
7179
6682
  if (err instanceof Error) {
7180
6683
  const stderr = err.stderr;
7181
6684
  const errMsg = stderr ? String(stderr).trim().split("\n").pop() : err.message.split("\n")[0];
7182
- if (errMsg && !errMsg.includes("SIGTERM")) console.log(chalk16.dim(` ${errMsg}`));
6685
+ if (errMsg && !errMsg.includes("SIGTERM")) console.log(chalk15.dim(` ${errMsg}`));
7183
6686
  }
7184
6687
  console.log(
7185
- chalk16.yellow(
7186
- `Run ${chalk16.bold(`npm install -g @rely-ai/caliber@${latest}`)} manually to upgrade.
6688
+ chalk15.yellow(
6689
+ `Run ${chalk15.bold(`npm install -g @rely-ai/caliber@${latest}`)} manually to upgrade.
7187
6690
  `
7188
6691
  )
7189
6692
  );