@rely-ai/caliber 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +67 -45
- package/package.json +2 -1
package/dist/bin.js
CHANGED
|
@@ -60,6 +60,7 @@ import chalk5 from "chalk";
|
|
|
60
60
|
import ora2 from "ora";
|
|
61
61
|
import readline4 from "readline";
|
|
62
62
|
import select2 from "@inquirer/select";
|
|
63
|
+
import checkbox from "@inquirer/checkbox";
|
|
63
64
|
import fs19 from "fs";
|
|
64
65
|
|
|
65
66
|
// src/fingerprint/index.ts
|
|
@@ -1218,7 +1219,7 @@ Omit empty categories. Keep each reason punchy and specific. End with a blank li
|
|
|
1218
1219
|
|
|
1219
1220
|
AgentSetup schema:
|
|
1220
1221
|
{
|
|
1221
|
-
"targetAgent": "claude"
|
|
1222
|
+
"targetAgent": ["claude", "cursor", "codex"] (array of selected agents),
|
|
1222
1223
|
"fileDescriptions": {
|
|
1223
1224
|
"<file-path>": "reason for this change (max 80 chars)"
|
|
1224
1225
|
},
|
|
@@ -1302,7 +1303,7 @@ Apply the requested changes to the setup and return the complete updated AgentSe
|
|
|
1302
1303
|
|
|
1303
1304
|
AgentSetup schema:
|
|
1304
1305
|
{
|
|
1305
|
-
"targetAgent": "claude"
|
|
1306
|
+
"targetAgent": ["claude", "cursor", "codex"] (array of selected agents),
|
|
1306
1307
|
"fileDescriptions": {
|
|
1307
1308
|
"<file-path>": "reason for this change (max 80 chars)"
|
|
1308
1309
|
},
|
|
@@ -2019,13 +2020,13 @@ function writeSetup(setup) {
|
|
|
2019
2020
|
];
|
|
2020
2021
|
const backupDir = existingFiles.length > 0 ? createBackup(existingFiles) : void 0;
|
|
2021
2022
|
const written = [];
|
|
2022
|
-
if (
|
|
2023
|
+
if (setup.targetAgent.includes("claude") && setup.claude) {
|
|
2023
2024
|
written.push(...writeClaudeConfig(setup.claude));
|
|
2024
2025
|
}
|
|
2025
|
-
if (
|
|
2026
|
+
if (setup.targetAgent.includes("cursor") && setup.cursor) {
|
|
2026
2027
|
written.push(...writeCursorConfig(setup.cursor));
|
|
2027
2028
|
}
|
|
2028
|
-
if (setup.targetAgent
|
|
2029
|
+
if (setup.targetAgent.includes("codex") && setup.codex) {
|
|
2029
2030
|
written.push(...writeCodexConfig(setup.codex));
|
|
2030
2031
|
}
|
|
2031
2032
|
const deleted = [];
|
|
@@ -2078,7 +2079,7 @@ function undoSetup() {
|
|
|
2078
2079
|
}
|
|
2079
2080
|
function getFilesToWrite(setup) {
|
|
2080
2081
|
const files = [];
|
|
2081
|
-
if (
|
|
2082
|
+
if (setup.targetAgent.includes("claude") && setup.claude) {
|
|
2082
2083
|
files.push("CLAUDE.md");
|
|
2083
2084
|
if (setup.claude.mcpServers) files.push(".mcp.json");
|
|
2084
2085
|
if (setup.claude.skills) {
|
|
@@ -2087,7 +2088,7 @@ function getFilesToWrite(setup) {
|
|
|
2087
2088
|
}
|
|
2088
2089
|
}
|
|
2089
2090
|
}
|
|
2090
|
-
if (
|
|
2091
|
+
if (setup.targetAgent.includes("cursor") && setup.cursor) {
|
|
2091
2092
|
if (setup.cursor.cursorrules) files.push(".cursorrules");
|
|
2092
2093
|
if (setup.cursor.rules) {
|
|
2093
2094
|
for (const r of setup.cursor.rules) files.push(`.cursor/rules/${r.filename}`);
|
|
@@ -2097,7 +2098,7 @@ function getFilesToWrite(setup) {
|
|
|
2097
2098
|
}
|
|
2098
2099
|
if (setup.cursor.mcpServers) files.push(".cursor/mcp.json");
|
|
2099
2100
|
}
|
|
2100
|
-
if (setup.targetAgent
|
|
2101
|
+
if (setup.targetAgent.includes("codex") && setup.codex) {
|
|
2101
2102
|
files.push("AGENTS.md");
|
|
2102
2103
|
if (setup.codex.skills) {
|
|
2103
2104
|
for (const s of setup.codex.skills) files.push(`.agents/skills/${s.name}/SKILL.md`);
|
|
@@ -2426,10 +2427,20 @@ import fs16 from "fs";
|
|
|
2426
2427
|
import path14 from "path";
|
|
2427
2428
|
import { execSync as execSync6 } from "child_process";
|
|
2428
2429
|
var STATE_FILE = path14.join(CALIBER_DIR, ".caliber-state.json");
|
|
2430
|
+
function normalizeTargetAgent(value) {
|
|
2431
|
+
if (Array.isArray(value)) return value;
|
|
2432
|
+
if (typeof value === "string") {
|
|
2433
|
+
if (value === "both") return ["claude", "cursor"];
|
|
2434
|
+
if (["claude", "cursor", "codex"].includes(value)) return [value];
|
|
2435
|
+
}
|
|
2436
|
+
return void 0;
|
|
2437
|
+
}
|
|
2429
2438
|
function readState() {
|
|
2430
2439
|
try {
|
|
2431
2440
|
if (!fs16.existsSync(STATE_FILE)) return null;
|
|
2432
|
-
|
|
2441
|
+
const raw = JSON.parse(fs16.readFileSync(STATE_FILE, "utf-8"));
|
|
2442
|
+
if (raw.targetAgent) raw.targetAgent = normalizeTargetAgent(raw.targetAgent);
|
|
2443
|
+
return raw;
|
|
2433
2444
|
} catch {
|
|
2434
2445
|
return null;
|
|
2435
2446
|
}
|
|
@@ -3690,26 +3701,19 @@ function sumCategory(checks, category) {
|
|
|
3690
3701
|
}
|
|
3691
3702
|
function filterChecksForTarget(checks, target) {
|
|
3692
3703
|
return checks.filter((c) => {
|
|
3693
|
-
if (
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
if (target
|
|
3697
|
-
return !CLAUDE_ONLY_CHECKS.has(c.id) && !CODEX_ONLY_CHECKS.has(c.id) && !BOTH_ONLY_CHECKS.has(c.id);
|
|
3698
|
-
}
|
|
3699
|
-
if (target === "codex") {
|
|
3700
|
-
return !CLAUDE_ONLY_CHECKS.has(c.id) && !CURSOR_ONLY_CHECKS.has(c.id) && !BOTH_ONLY_CHECKS.has(c.id);
|
|
3701
|
-
}
|
|
3704
|
+
if (CLAUDE_ONLY_CHECKS.has(c.id)) return target.includes("claude");
|
|
3705
|
+
if (CURSOR_ONLY_CHECKS.has(c.id)) return target.includes("cursor");
|
|
3706
|
+
if (CODEX_ONLY_CHECKS.has(c.id)) return target.includes("codex");
|
|
3707
|
+
if (BOTH_ONLY_CHECKS.has(c.id)) return target.includes("claude") && target.includes("cursor");
|
|
3702
3708
|
return true;
|
|
3703
3709
|
});
|
|
3704
3710
|
}
|
|
3705
3711
|
function detectTargetAgent(dir) {
|
|
3706
|
-
const
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
if (
|
|
3710
|
-
|
|
3711
|
-
if (hasCursor) return "cursor";
|
|
3712
|
-
return "claude";
|
|
3712
|
+
const agents = [];
|
|
3713
|
+
if (existsSync8(join7(dir, "CLAUDE.md")) || existsSync8(join7(dir, ".claude", "skills"))) agents.push("claude");
|
|
3714
|
+
if (existsSync8(join7(dir, ".cursorrules")) || existsSync8(join7(dir, ".cursor", "rules"))) agents.push("cursor");
|
|
3715
|
+
if (existsSync8(join7(dir, ".codex")) || existsSync8(join7(dir, ".agents", "skills"))) agents.push("codex");
|
|
3716
|
+
return agents.length > 0 ? agents : ["claude"];
|
|
3713
3717
|
}
|
|
3714
3718
|
function computeLocalScore(dir, targetAgent) {
|
|
3715
3719
|
const target = targetAgent ?? detectTargetAgent(dir);
|
|
@@ -3746,6 +3750,11 @@ function computeLocalScore(dir, targetAgent) {
|
|
|
3746
3750
|
|
|
3747
3751
|
// src/scoring/display.ts
|
|
3748
3752
|
import chalk3 from "chalk";
|
|
3753
|
+
var AGENT_DISPLAY_NAMES = {
|
|
3754
|
+
claude: "Claude Code",
|
|
3755
|
+
cursor: "Cursor",
|
|
3756
|
+
codex: "Codex"
|
|
3757
|
+
};
|
|
3749
3758
|
var CATEGORY_LABELS = {
|
|
3750
3759
|
existence: "FILES & SETUP",
|
|
3751
3760
|
quality: "QUALITY",
|
|
@@ -3788,7 +3797,7 @@ function formatCheck(check) {
|
|
|
3788
3797
|
}
|
|
3789
3798
|
function displayScore(result) {
|
|
3790
3799
|
const gc = gradeColor(result.grade);
|
|
3791
|
-
const agentLabel = result.targetAgent
|
|
3800
|
+
const agentLabel = result.targetAgent.map((a) => AGENT_DISPLAY_NAMES[a] || a).join(" + ");
|
|
3792
3801
|
console.log("");
|
|
3793
3802
|
console.log(chalk3.gray(" \u256D\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E"));
|
|
3794
3803
|
console.log(chalk3.gray(" \u2502") + " " + chalk3.gray("\u2502"));
|
|
@@ -3814,7 +3823,7 @@ function displayScore(result) {
|
|
|
3814
3823
|
}
|
|
3815
3824
|
function displayScoreSummary(result) {
|
|
3816
3825
|
const gc = gradeColor(result.grade);
|
|
3817
|
-
const agentLabel = result.targetAgent
|
|
3826
|
+
const agentLabel = result.targetAgent.map((a) => AGENT_DISPLAY_NAMES[a] || a).join(" + ");
|
|
3818
3827
|
console.log("");
|
|
3819
3828
|
console.log(
|
|
3820
3829
|
chalk3.gray(" ") + gc(`${result.score}/${result.maxScore}`) + chalk3.gray(` (Grade ${result.grade})`) + chalk3.gray(` \xB7 ${agentLabel}`) + chalk3.gray(` \xB7 ${progressBar(result.score, result.maxScore, 20)}`)
|
|
@@ -4228,17 +4237,14 @@ async function discoverAndInstallMcps(targetAgent, fingerprint, dir) {
|
|
|
4228
4237
|
if (installedNames.length === 0) {
|
|
4229
4238
|
return { installed: 0, names: [] };
|
|
4230
4239
|
}
|
|
4231
|
-
if (targetAgent
|
|
4240
|
+
if (targetAgent.includes("claude") || targetAgent.includes("codex")) {
|
|
4232
4241
|
writeMcpJson(path16.join(dir, ".mcp.json"), mcpServers);
|
|
4233
4242
|
}
|
|
4234
|
-
if (targetAgent
|
|
4243
|
+
if (targetAgent.includes("cursor")) {
|
|
4235
4244
|
const cursorDir = path16.join(dir, ".cursor");
|
|
4236
4245
|
if (!fs18.existsSync(cursorDir)) fs18.mkdirSync(cursorDir, { recursive: true });
|
|
4237
4246
|
writeMcpJson(path16.join(cursorDir, "mcp.json"), mcpServers);
|
|
4238
4247
|
}
|
|
4239
|
-
if (targetAgent === "codex") {
|
|
4240
|
-
writeMcpJson(path16.join(dir, ".mcp.json"), mcpServers);
|
|
4241
|
-
}
|
|
4242
4248
|
return { installed: installedNames.length, names: installedNames };
|
|
4243
4249
|
}
|
|
4244
4250
|
function writeMcpJson(filePath, mcpServers) {
|
|
@@ -4255,12 +4261,12 @@ function writeMcpJson(filePath, mcpServers) {
|
|
|
4255
4261
|
}
|
|
4256
4262
|
function getExistingMcpNames(fingerprint, targetAgent) {
|
|
4257
4263
|
const names = [];
|
|
4258
|
-
if (targetAgent
|
|
4264
|
+
if (targetAgent.includes("claude")) {
|
|
4259
4265
|
if (fingerprint.existingConfigs.claudeMcpServers) {
|
|
4260
4266
|
names.push(...Object.keys(fingerprint.existingConfigs.claudeMcpServers).map((k) => k.toLowerCase()));
|
|
4261
4267
|
}
|
|
4262
4268
|
}
|
|
4263
|
-
if (targetAgent
|
|
4269
|
+
if (targetAgent.includes("cursor")) {
|
|
4264
4270
|
if (fingerprint.existingConfigs.cursorMcpServers) {
|
|
4265
4271
|
names.push(...Object.keys(fingerprint.existingConfigs.cursorMcpServers).map((k) => k.toLowerCase()));
|
|
4266
4272
|
}
|
|
@@ -4643,7 +4649,7 @@ async function initCommand(options) {
|
|
|
4643
4649
|
console.log("");
|
|
4644
4650
|
console.log(title.bold(" Keep your configs fresh\n"));
|
|
4645
4651
|
console.log(chalk5.dim(" Caliber can automatically update your agent configs when your code changes.\n"));
|
|
4646
|
-
const hookChoice =
|
|
4652
|
+
const hookChoice = await promptHookType(targetAgent);
|
|
4647
4653
|
if (hookChoice === "claude" || hookChoice === "both") {
|
|
4648
4654
|
const hookResult = installHook();
|
|
4649
4655
|
if (hookResult.installed) {
|
|
@@ -4801,23 +4807,28 @@ function promptInput3(question) {
|
|
|
4801
4807
|
});
|
|
4802
4808
|
}
|
|
4803
4809
|
async function promptAgent() {
|
|
4804
|
-
|
|
4805
|
-
message: "Which coding
|
|
4810
|
+
const selected = await checkbox({
|
|
4811
|
+
message: "Which coding agents do you use? (toggle with space)",
|
|
4806
4812
|
choices: [
|
|
4807
4813
|
{ name: "Claude Code", value: "claude" },
|
|
4808
4814
|
{ name: "Cursor", value: "cursor" },
|
|
4809
|
-
{ name: "Codex (OpenAI)", value: "codex" }
|
|
4810
|
-
|
|
4811
|
-
|
|
4815
|
+
{ name: "Codex (OpenAI)", value: "codex" }
|
|
4816
|
+
],
|
|
4817
|
+
validate: (items) => {
|
|
4818
|
+
if (items.length === 0) return "At least one agent must be selected";
|
|
4819
|
+
return true;
|
|
4820
|
+
}
|
|
4812
4821
|
});
|
|
4822
|
+
return selected;
|
|
4813
4823
|
}
|
|
4814
4824
|
async function promptHookType(targetAgent) {
|
|
4815
4825
|
const choices = [];
|
|
4816
|
-
|
|
4826
|
+
const hasClaude = targetAgent.includes("claude");
|
|
4827
|
+
if (hasClaude) {
|
|
4817
4828
|
choices.push({ name: "Claude Code hook (auto-refresh on session end)", value: "claude" });
|
|
4818
4829
|
}
|
|
4819
4830
|
choices.push({ name: "Git pre-commit hook (refresh before each commit)", value: "precommit" });
|
|
4820
|
-
if (
|
|
4831
|
+
if (hasClaude) {
|
|
4821
4832
|
choices.push({ name: "Both (Claude Code + pre-commit)", value: "both" });
|
|
4822
4833
|
}
|
|
4823
4834
|
choices.push({ name: "Skip for now", value: "skip" });
|
|
@@ -5312,7 +5323,7 @@ async function regenerateCommand(options) {
|
|
|
5312
5323
|
genMessages.start();
|
|
5313
5324
|
let generatedSetup = null;
|
|
5314
5325
|
try {
|
|
5315
|
-
const targetAgent = readState()?.targetAgent ?? "
|
|
5326
|
+
const targetAgent = readState()?.targetAgent ?? ["claude", "cursor"];
|
|
5316
5327
|
const result2 = await generateSetup(
|
|
5317
5328
|
fingerprint,
|
|
5318
5329
|
targetAgent,
|
|
@@ -6936,13 +6947,24 @@ var pkg = JSON.parse(
|
|
|
6936
6947
|
var program = new Command();
|
|
6937
6948
|
var displayVersion = process.env.CALIBER_LOCAL ? `${pkg.version}-local` : pkg.version;
|
|
6938
6949
|
program.name(process.env.CALIBER_LOCAL ? "caloc" : "caliber").description("Configure your coding agent environment").version(displayVersion);
|
|
6939
|
-
|
|
6950
|
+
function parseAgentOption(value) {
|
|
6951
|
+
if (value === "both") return ["claude", "cursor"];
|
|
6952
|
+
if (value === "all") return ["claude", "cursor", "codex"];
|
|
6953
|
+
const valid = ["claude", "cursor", "codex"];
|
|
6954
|
+
const agents = [...new Set(value.split(",").map((s) => s.trim().toLowerCase()).filter((a) => valid.includes(a)))];
|
|
6955
|
+
if (agents.length === 0) {
|
|
6956
|
+
console.error(`Invalid agent "${value}". Choose from: claude, cursor, codex (comma-separated for multiple)`);
|
|
6957
|
+
process.exit(1);
|
|
6958
|
+
}
|
|
6959
|
+
return agents;
|
|
6960
|
+
}
|
|
6961
|
+
program.command("onboard").alias("init").description("Onboard your project for AI-assisted development").option("--agent <type>", "Target agents (comma-separated): claude, cursor, codex", parseAgentOption).option("--dry-run", "Preview changes without writing files").option("--force", "Overwrite existing setup without prompting").action(initCommand);
|
|
6940
6962
|
program.command("undo").description("Revert all config changes made by Caliber").action(undoCommand);
|
|
6941
6963
|
program.command("status").description("Show current Caliber setup status").option("--json", "Output as JSON").action(statusCommand);
|
|
6942
6964
|
program.command("regenerate").alias("regen").alias("re").alias("update").description("Re-analyze project and regenerate setup").option("--dry-run", "Preview changes without writing files").action(regenerateCommand);
|
|
6943
6965
|
program.command("config").description("Configure LLM provider, API key, and model").action(configCommand);
|
|
6944
6966
|
program.command("recommend").description("Discover and install skill recommendations").option("--generate", "Force fresh recommendation search").action(recommendCommand);
|
|
6945
|
-
program.command("score").description("Score your current agent config setup (deterministic, no network)").option("--json", "Output as JSON").option("--quiet", "One-line output for scripts/hooks").option("--agent <type>", "Target
|
|
6967
|
+
program.command("score").description("Score your current agent config setup (deterministic, no network)").option("--json", "Output as JSON").option("--quiet", "One-line output for scripts/hooks").option("--agent <type>", "Target agents (comma-separated): claude, cursor, codex", parseAgentOption).action(scoreCommand);
|
|
6946
6968
|
program.command("refresh").description("Update docs based on recent code changes").option("--quiet", "Suppress output (for use in hooks)").option("--dry-run", "Preview changes without writing files").action(refreshCommand);
|
|
6947
6969
|
program.command("hooks").description("Manage auto-refresh hooks (toggle interactively)").option("--install", "Enable all hooks non-interactively").option("--remove", "Disable all hooks non-interactively").action(hooksCommand);
|
|
6948
6970
|
var learn = program.command("learn").description("Session learning \u2014 observe tool usage and extract reusable instructions");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rely-ai/caliber",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Analyze your codebase and generate optimized AI agent configs (CLAUDE.md, .cursorrules, skills) — no API key needed",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@anthropic-ai/sdk": "^0.39.0",
|
|
18
18
|
"@anthropic-ai/vertex-sdk": "^0.7.0",
|
|
19
|
+
"@inquirer/checkbox": "^5.1.0",
|
|
19
20
|
"@inquirer/confirm": "^6.0.8",
|
|
20
21
|
"@inquirer/select": "^5.1.0",
|
|
21
22
|
"chalk": "^5.4.0",
|