@rely-ai/caliber 1.31.0-dev.1774743306 → 1.31.0-dev.1774815271
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 +429 -187
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -71,6 +71,7 @@ __export(builtin_skills_exports, {
|
|
|
71
71
|
BUILTIN_SKILLS: () => BUILTIN_SKILLS,
|
|
72
72
|
BUILTIN_SKILL_NAMES: () => BUILTIN_SKILL_NAMES,
|
|
73
73
|
FIND_SKILLS_SKILL: () => FIND_SKILLS_SKILL,
|
|
74
|
+
PLATFORM_CONFIGS: () => PLATFORM_CONFIGS,
|
|
74
75
|
SAVE_LEARNING_SKILL: () => SAVE_LEARNING_SKILL,
|
|
75
76
|
SETUP_CALIBER_SKILL: () => SETUP_CALIBER_SKILL,
|
|
76
77
|
buildSkillContent: () => buildSkillContent,
|
|
@@ -217,18 +218,19 @@ then only act if something is missing.
|
|
|
217
218
|
command -v caliber >/dev/null 2>&1 && caliber --version || echo "NOT_INSTALLED"
|
|
218
219
|
\`\`\`
|
|
219
220
|
|
|
220
|
-
- If a version prints \u2192 Caliber is installed.
|
|
221
|
-
- If NOT_INSTALLED \u2192
|
|
222
|
-
Then run:
|
|
221
|
+
- If a version prints \u2192 Caliber is installed globally. Set \`CALIBER="caliber"\` and move to Step 2.
|
|
222
|
+
- If NOT_INSTALLED \u2192 Install it globally (faster for daily use since the pre-commit hook runs on every commit):
|
|
223
223
|
\`\`\`bash
|
|
224
224
|
npm install -g @rely-ai/caliber
|
|
225
225
|
\`\`\`
|
|
226
|
-
|
|
226
|
+
Set \`CALIBER="caliber"\`.
|
|
227
|
+
|
|
228
|
+
If npm fails (permissions, no sudo, etc.), fall back to npx:
|
|
227
229
|
\`\`\`bash
|
|
228
|
-
npx @rely-ai/caliber --version
|
|
230
|
+
npx @rely-ai/caliber --version 2>/dev/null || echo "NO_NODE"
|
|
229
231
|
\`\`\`
|
|
230
|
-
If npx works
|
|
231
|
-
If
|
|
232
|
+
- If npx works \u2192 Set \`CALIBER="npx @rely-ai/caliber"\`. This works but adds ~500ms per invocation.
|
|
233
|
+
- If NO_NODE \u2192 Tell the user: "Caliber requires Node.js >= 20. Install Node first, then run /setup-caliber again." Stop here.
|
|
232
234
|
|
|
233
235
|
### Step 2: Check if pre-commit hook is installed
|
|
234
236
|
|
|
@@ -239,7 +241,7 @@ grep -q "caliber" .git/hooks/pre-commit 2>/dev/null && echo "HOOK_ACTIVE" || ech
|
|
|
239
241
|
- If HOOK_ACTIVE \u2192 Tell the user: "Pre-commit hook is active \u2014 configs sync on every commit." Move to Step 3.
|
|
240
242
|
- If NO_HOOK \u2192 Tell the user: "I'll install the pre-commit hook so your agent configs sync automatically on every commit."
|
|
241
243
|
\`\`\`bash
|
|
242
|
-
|
|
244
|
+
$CALIBER hooks --install
|
|
243
245
|
\`\`\`
|
|
244
246
|
|
|
245
247
|
### Step 3: Detect agents and check if configs exist
|
|
@@ -269,22 +271,22 @@ echo "COPILOT=$([ -f .github/copilot-instructions.md ] && echo exists || echo mi
|
|
|
269
271
|
- If configs are missing \u2192 Tell the user: "No agent configs found. I'll generate them now."
|
|
270
272
|
Use the detected or user-selected agent list:
|
|
271
273
|
\`\`\`bash
|
|
272
|
-
|
|
274
|
+
$CALIBER init --auto-approve --agent <comma-separated-agents>
|
|
273
275
|
\`\`\`
|
|
274
|
-
For example:
|
|
276
|
+
For example: \`$CALIBER init --auto-approve --agent claude,cursor\`
|
|
275
277
|
This generates CLAUDE.md, Cursor rules, AGENTS.md, skills, and sync infrastructure for the specified agents.
|
|
276
278
|
|
|
277
279
|
### Step 4: Check if configs are fresh
|
|
278
280
|
|
|
279
281
|
\`\`\`bash
|
|
280
|
-
|
|
282
|
+
$CALIBER score --json --quiet 2>/dev/null | head -1
|
|
281
283
|
\`\`\`
|
|
282
284
|
|
|
283
285
|
- If score is 80+ \u2192 Tell the user: "Your configs are in good shape (score: X/100)."
|
|
284
286
|
- If score is below 80 \u2192 Tell the user: "Your configs could be improved (score: X/100). Want me to run a refresh?"
|
|
285
287
|
If yes:
|
|
286
288
|
\`\`\`bash
|
|
287
|
-
|
|
289
|
+
$CALIBER refresh
|
|
288
290
|
\`\`\`
|
|
289
291
|
|
|
290
292
|
### Step 5: Ask about team setup
|
|
@@ -295,20 +297,20 @@ Ask the user: "Are you setting up for yourself only, or for your team too?"
|
|
|
295
297
|
|
|
296
298
|
Check if session learning is enabled:
|
|
297
299
|
\`\`\`bash
|
|
298
|
-
|
|
300
|
+
$CALIBER learn status 2>/dev/null | head -3
|
|
299
301
|
\`\`\`
|
|
300
302
|
- If learning is already enabled \u2192 note it in the summary.
|
|
301
303
|
- If not enabled \u2192 ask the user: "Caliber can learn from your coding sessions \u2014 when you correct a mistake or fix a pattern, it remembers for next time. Enable session learning?"
|
|
302
304
|
If yes:
|
|
303
305
|
\`\`\`bash
|
|
304
|
-
|
|
306
|
+
$CALIBER learn install
|
|
305
307
|
\`\`\`
|
|
306
308
|
|
|
307
309
|
Then tell the user:
|
|
308
310
|
"You're all set! Here's what happens next:
|
|
309
311
|
- Every time you commit, Caliber syncs your agent configs automatically
|
|
310
312
|
- Your CLAUDE.md, Cursor rules, and AGENTS.md stay current with your code
|
|
311
|
-
- Run
|
|
313
|
+
- Run \`$CALIBER skills\` anytime to discover community skills for your stack"
|
|
312
314
|
|
|
313
315
|
Then show the summary (see below) and stop.
|
|
314
316
|
|
|
@@ -343,7 +345,7 @@ Ask the user: "Are you setting up for yourself only, or for your team too?"
|
|
|
343
345
|
\`\`\`
|
|
344
346
|
Now determine which LLM provider the team uses. Check the local Caliber config:
|
|
345
347
|
\`\`\`bash
|
|
346
|
-
|
|
348
|
+
$CALIBER config --show 2>/dev/null || echo "NO_CONFIG"
|
|
347
349
|
\`\`\`
|
|
348
350
|
|
|
349
351
|
Based on the provider, the GitHub Action needs the corresponding secret:
|
|
@@ -468,7 +470,8 @@ __export(pre_commit_block_exports, {
|
|
|
468
470
|
getCursorSyncRule: () => getCursorSyncRule,
|
|
469
471
|
hasLearningsBlock: () => hasLearningsBlock,
|
|
470
472
|
hasPreCommitBlock: () => hasPreCommitBlock,
|
|
471
|
-
hasSyncBlock: () => hasSyncBlock
|
|
473
|
+
hasSyncBlock: () => hasSyncBlock,
|
|
474
|
+
stripManagedBlocks: () => stripManagedBlocks
|
|
472
475
|
});
|
|
473
476
|
function getCaliberNotFoundFallback(platform, bin) {
|
|
474
477
|
switch (platform) {
|
|
@@ -477,7 +480,11 @@ function getCaliberNotFoundFallback(platform, bin) {
|
|
|
477
480
|
case "codex":
|
|
478
481
|
return `If \`${bin}\` is not found, read \`.agents/skills/setup-caliber/SKILL.md\` and follow its instructions to install Caliber.`;
|
|
479
482
|
case "copilot":
|
|
480
|
-
return `If \`${bin}\` is not found,
|
|
483
|
+
return `If \`${bin}\` is not found, tell the developer to set up Caliber by running \`/setup-caliber\` in Claude Code or Cursor. Alternatively, they can run these commands in their terminal:
|
|
484
|
+
\`\`\`
|
|
485
|
+
npx @rely-ai/caliber hooks --install
|
|
486
|
+
npx @rely-ai/caliber refresh
|
|
487
|
+
\`\`\``;
|
|
481
488
|
}
|
|
482
489
|
}
|
|
483
490
|
function getPreCommitBlock(platform = "claude") {
|
|
@@ -545,11 +552,10 @@ function getSyncSetupInstruction(platform, bin) {
|
|
|
545
552
|
case "codex":
|
|
546
553
|
return `If the pre-commit hook is not set up, read \`.agents/skills/setup-caliber/SKILL.md\` and follow the setup instructions.`;
|
|
547
554
|
case "copilot":
|
|
548
|
-
return `If the pre-commit hook is not set up,
|
|
555
|
+
return `If the pre-commit hook is not set up, the developer should run \`/setup-caliber\` in Claude Code or Cursor for automated setup. Alternatively, run in terminal:
|
|
549
556
|
\`\`\`bash
|
|
550
|
-
|
|
551
|
-
caliber
|
|
552
|
-
caliber refresh
|
|
557
|
+
npx @rely-ai/caliber hooks --install
|
|
558
|
+
npx @rely-ai/caliber refresh
|
|
553
559
|
git add ${MANAGED_DOC_PATHS} 2>/dev/null
|
|
554
560
|
\`\`\``;
|
|
555
561
|
}
|
|
@@ -608,7 +614,15 @@ If the user agrees, read \`.cursor/skills/setup-caliber/SKILL.md\` and follow it
|
|
|
608
614
|
function getCursorSetupRule() {
|
|
609
615
|
return { filename: CURSOR_SETUP_FILENAME, content: getCursorSetupContent() };
|
|
610
616
|
}
|
|
611
|
-
|
|
617
|
+
function stripManagedBlocks(content) {
|
|
618
|
+
let result = content;
|
|
619
|
+
for (const [start, end] of MANAGED_BLOCK_PAIRS) {
|
|
620
|
+
const regex = new RegExp(`\\n?${start.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}[\\s\\S]*?${end.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\n?`, "g");
|
|
621
|
+
result = result.replace(regex, "\n");
|
|
622
|
+
}
|
|
623
|
+
return result.replace(/\n{3,}/g, "\n\n").trim() + "\n";
|
|
624
|
+
}
|
|
625
|
+
var BLOCK_START, BLOCK_END, MANAGED_DOC_PATHS, CURSOR_RULE_FILENAME, LEARNINGS_BLOCK_START, LEARNINGS_BLOCK_END, LEARNINGS_BLOCK, CURSOR_LEARNINGS_FILENAME, CURSOR_LEARNINGS_CONTENT, SYNC_BLOCK_START, SYNC_BLOCK_END, CURSOR_SYNC_FILENAME, CURSOR_SETUP_FILENAME, MANAGED_BLOCK_PAIRS;
|
|
612
626
|
var init_pre_commit_block = __esm({
|
|
613
627
|
"src/writers/pre-commit-block.ts"() {
|
|
614
628
|
"use strict";
|
|
@@ -637,6 +651,11 @@ These are auto-extracted from real tool usage \u2014 treat them as project-speci
|
|
|
637
651
|
SYNC_BLOCK_END = "<!-- /caliber:managed:sync -->";
|
|
638
652
|
CURSOR_SYNC_FILENAME = "caliber-sync.mdc";
|
|
639
653
|
CURSOR_SETUP_FILENAME = "caliber-setup.mdc";
|
|
654
|
+
MANAGED_BLOCK_PAIRS = [
|
|
655
|
+
[BLOCK_START, BLOCK_END],
|
|
656
|
+
[LEARNINGS_BLOCK_START, LEARNINGS_BLOCK_END],
|
|
657
|
+
[SYNC_BLOCK_START, SYNC_BLOCK_END]
|
|
658
|
+
];
|
|
640
659
|
}
|
|
641
660
|
});
|
|
642
661
|
|
|
@@ -1120,8 +1139,8 @@ var init_lock = __esm({
|
|
|
1120
1139
|
|
|
1121
1140
|
// src/cli.ts
|
|
1122
1141
|
import { Command } from "commander";
|
|
1123
|
-
import
|
|
1124
|
-
import
|
|
1142
|
+
import fs49 from "fs";
|
|
1143
|
+
import path39 from "path";
|
|
1125
1144
|
import { fileURLToPath } from "url";
|
|
1126
1145
|
|
|
1127
1146
|
// src/commands/init.ts
|
|
@@ -4444,15 +4463,15 @@ init_config();
|
|
|
4444
4463
|
// src/utils/dependencies.ts
|
|
4445
4464
|
import { readFileSync as readFileSync2 } from "fs";
|
|
4446
4465
|
import { join as join2 } from "path";
|
|
4447
|
-
function readFileOrNull2(
|
|
4466
|
+
function readFileOrNull2(path41) {
|
|
4448
4467
|
try {
|
|
4449
|
-
return readFileSync2(
|
|
4468
|
+
return readFileSync2(path41, "utf-8");
|
|
4450
4469
|
} catch {
|
|
4451
4470
|
return null;
|
|
4452
4471
|
}
|
|
4453
4472
|
}
|
|
4454
|
-
function readJsonOrNull(
|
|
4455
|
-
const content = readFileOrNull2(
|
|
4473
|
+
function readJsonOrNull(path41) {
|
|
4474
|
+
const content = readFileOrNull2(path41);
|
|
4456
4475
|
if (!content) return null;
|
|
4457
4476
|
try {
|
|
4458
4477
|
return JSON.parse(content);
|
|
@@ -5773,6 +5792,9 @@ async function runInteractiveProviderSetup(options) {
|
|
|
5773
5792
|
return config;
|
|
5774
5793
|
}
|
|
5775
5794
|
|
|
5795
|
+
// src/commands/init.ts
|
|
5796
|
+
import confirm2 from "@inquirer/confirm";
|
|
5797
|
+
|
|
5776
5798
|
// src/scoring/index.ts
|
|
5777
5799
|
import { existsSync as existsSync7 } from "fs";
|
|
5778
5800
|
import { join as join9 } from "path";
|
|
@@ -6771,8 +6793,8 @@ function detectTargetAgent(dir) {
|
|
|
6771
6793
|
const agents = [];
|
|
6772
6794
|
if (existsSync7(join9(dir, "CLAUDE.md")) || existsSync7(join9(dir, ".claude", "skills"))) agents.push("claude");
|
|
6773
6795
|
if (existsSync7(join9(dir, ".cursorrules")) || existsSync7(join9(dir, ".cursor", "rules"))) agents.push("cursor");
|
|
6774
|
-
if (existsSync7(join9(dir, ".codex")) || existsSync7(join9(dir, ".agents", "skills"))) agents.push("codex");
|
|
6775
|
-
if (existsSync7(join9(dir, ".github", "copilot-instructions.md"))) agents.push("github-copilot");
|
|
6796
|
+
if (existsSync7(join9(dir, ".codex")) || existsSync7(join9(dir, ".agents", "skills")) || existsSync7(join9(dir, "AGENTS.md"))) agents.push("codex");
|
|
6797
|
+
if (existsSync7(join9(dir, ".github", "copilot-instructions.md")) || existsSync7(join9(dir, ".github", "instructions"))) agents.push("github-copilot");
|
|
6776
6798
|
return agents.length > 0 ? agents : ["claude"];
|
|
6777
6799
|
}
|
|
6778
6800
|
function computeLocalScore(dir, targetAgent) {
|
|
@@ -7026,11 +7048,57 @@ function getMachineId() {
|
|
|
7026
7048
|
return machineId;
|
|
7027
7049
|
}
|
|
7028
7050
|
var EMAIL_HASH_KEY = "caliber-telemetry-v1";
|
|
7029
|
-
|
|
7051
|
+
var PERSONAL_DOMAINS = /* @__PURE__ */ new Set([
|
|
7052
|
+
"gmail.com",
|
|
7053
|
+
"googlemail.com",
|
|
7054
|
+
"outlook.com",
|
|
7055
|
+
"hotmail.com",
|
|
7056
|
+
"live.com",
|
|
7057
|
+
"yahoo.com",
|
|
7058
|
+
"yahoo.co.uk",
|
|
7059
|
+
"icloud.com",
|
|
7060
|
+
"me.com",
|
|
7061
|
+
"mac.com",
|
|
7062
|
+
"aol.com",
|
|
7063
|
+
"protonmail.com",
|
|
7064
|
+
"proton.me",
|
|
7065
|
+
"pm.me",
|
|
7066
|
+
"mail.com",
|
|
7067
|
+
"zoho.com",
|
|
7068
|
+
"yandex.com",
|
|
7069
|
+
"gmx.com",
|
|
7070
|
+
"gmx.net",
|
|
7071
|
+
"fastmail.com",
|
|
7072
|
+
"tutanota.com",
|
|
7073
|
+
"tuta.io"
|
|
7074
|
+
]);
|
|
7075
|
+
function getGitEmail() {
|
|
7030
7076
|
try {
|
|
7031
7077
|
const email = execSync13("git config user.email", { encoding: "utf-8" }).trim();
|
|
7032
|
-
|
|
7033
|
-
|
|
7078
|
+
return email || void 0;
|
|
7079
|
+
} catch {
|
|
7080
|
+
return void 0;
|
|
7081
|
+
}
|
|
7082
|
+
}
|
|
7083
|
+
function getGitEmailInfo() {
|
|
7084
|
+
const email = getGitEmail();
|
|
7085
|
+
if (!email) return {};
|
|
7086
|
+
const hash = crypto4.createHmac("sha256", EMAIL_HASH_KEY).update(email).digest("hex");
|
|
7087
|
+
let domain;
|
|
7088
|
+
if (email.includes("@")) {
|
|
7089
|
+
const d = email.split("@")[1].toLowerCase();
|
|
7090
|
+
if (!PERSONAL_DOMAINS.has(d)) domain = d;
|
|
7091
|
+
}
|
|
7092
|
+
return { hash, domain };
|
|
7093
|
+
}
|
|
7094
|
+
function getRepoHash() {
|
|
7095
|
+
try {
|
|
7096
|
+
const remote = execSync13("git remote get-url origin || git rev-parse --show-toplevel", {
|
|
7097
|
+
encoding: "utf-8",
|
|
7098
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
7099
|
+
}).trim();
|
|
7100
|
+
if (!remote) return void 0;
|
|
7101
|
+
return crypto4.createHmac("sha256", EMAIL_HASH_KEY).update(remote).digest("hex").slice(0, 16);
|
|
7034
7102
|
} catch {
|
|
7035
7103
|
return void 0;
|
|
7036
7104
|
}
|
|
@@ -7055,6 +7123,7 @@ function markNoticeShown() {
|
|
|
7055
7123
|
var POSTHOG_KEY = "phc_XXrV0pSX4s2QVxVoOaeuyXDvtlRwPAjovt1ttMGVMPp";
|
|
7056
7124
|
var client = null;
|
|
7057
7125
|
var distinctId = null;
|
|
7126
|
+
var superProperties = {};
|
|
7058
7127
|
function initTelemetry() {
|
|
7059
7128
|
if (isTelemetryDisabled()) return;
|
|
7060
7129
|
const machineId = getMachineId();
|
|
@@ -7070,11 +7139,17 @@ function initTelemetry() {
|
|
|
7070
7139
|
);
|
|
7071
7140
|
markNoticeShown();
|
|
7072
7141
|
}
|
|
7073
|
-
const gitEmailHash =
|
|
7142
|
+
const { hash: gitEmailHash, domain: emailDomain } = getGitEmailInfo();
|
|
7143
|
+
const repoHash = getRepoHash();
|
|
7144
|
+
superProperties = {
|
|
7145
|
+
...repoHash ? { repo_hash: repoHash } : {},
|
|
7146
|
+
...emailDomain ? { email_domain: emailDomain } : {}
|
|
7147
|
+
};
|
|
7074
7148
|
client.identify({
|
|
7075
7149
|
distinctId: machineId,
|
|
7076
7150
|
properties: {
|
|
7077
|
-
...gitEmailHash ? { git_email_hash: gitEmailHash } : {}
|
|
7151
|
+
...gitEmailHash ? { git_email_hash: gitEmailHash } : {},
|
|
7152
|
+
...emailDomain ? { email_domain: emailDomain } : {}
|
|
7078
7153
|
}
|
|
7079
7154
|
});
|
|
7080
7155
|
}
|
|
@@ -7083,7 +7158,7 @@ function trackEvent(name, properties) {
|
|
|
7083
7158
|
client.capture({
|
|
7084
7159
|
distinctId,
|
|
7085
7160
|
event: name,
|
|
7086
|
-
properties: properties
|
|
7161
|
+
properties: { ...superProperties, ...properties }
|
|
7087
7162
|
});
|
|
7088
7163
|
}
|
|
7089
7164
|
async function flushTelemetry() {
|
|
@@ -7132,11 +7207,14 @@ function trackInitSkillsSearch(searched, installedCount) {
|
|
|
7132
7207
|
function trackInitScoreRegression(oldScore, newScore) {
|
|
7133
7208
|
trackEvent("init_score_regression", { old_score: oldScore, new_score: newScore });
|
|
7134
7209
|
}
|
|
7210
|
+
function trackInitCompleted(path41, score) {
|
|
7211
|
+
trackEvent("init_completed", { path: path41, score });
|
|
7212
|
+
}
|
|
7135
7213
|
function trackRegenerateCompleted(action, durationMs) {
|
|
7136
7214
|
trackEvent("regenerate_completed", { action, duration_ms: durationMs });
|
|
7137
7215
|
}
|
|
7138
|
-
function trackRefreshCompleted(changesCount, durationMs) {
|
|
7139
|
-
trackEvent("refresh_completed", { changes_count: changesCount, duration_ms: durationMs });
|
|
7216
|
+
function trackRefreshCompleted(changesCount, durationMs, trigger) {
|
|
7217
|
+
trackEvent("refresh_completed", { changes_count: changesCount, duration_ms: durationMs, trigger: trigger ?? "manual" });
|
|
7140
7218
|
}
|
|
7141
7219
|
function trackScoreComputed(score, agent) {
|
|
7142
7220
|
trackEvent("score_computed", { score, agent });
|
|
@@ -7150,6 +7228,9 @@ function trackSkillsInstalled(count) {
|
|
|
7150
7228
|
function trackUndoExecuted() {
|
|
7151
7229
|
trackEvent("undo_executed");
|
|
7152
7230
|
}
|
|
7231
|
+
function trackUninstallExecuted() {
|
|
7232
|
+
trackEvent("uninstall_executed");
|
|
7233
|
+
}
|
|
7153
7234
|
function trackInitLearnEnabled(enabled) {
|
|
7154
7235
|
trackEvent("init_learn_enabled", { enabled });
|
|
7155
7236
|
}
|
|
@@ -8084,11 +8165,11 @@ function countIssuePoints(issues) {
|
|
|
8084
8165
|
}
|
|
8085
8166
|
async function scoreAndRefine(setup, dir, sessionHistory, callbacks) {
|
|
8086
8167
|
const existsCache = /* @__PURE__ */ new Map();
|
|
8087
|
-
const cachedExists = (
|
|
8088
|
-
const cached = existsCache.get(
|
|
8168
|
+
const cachedExists = (path41) => {
|
|
8169
|
+
const cached = existsCache.get(path41);
|
|
8089
8170
|
if (cached !== void 0) return cached;
|
|
8090
|
-
const result = existsSync9(
|
|
8091
|
-
existsCache.set(
|
|
8171
|
+
const result = existsSync9(path41);
|
|
8172
|
+
existsCache.set(path41, result);
|
|
8092
8173
|
return result;
|
|
8093
8174
|
};
|
|
8094
8175
|
const projectStructure = collectProjectStructure(dir);
|
|
@@ -8868,25 +8949,6 @@ async function promptAgent(detected) {
|
|
|
8868
8949
|
});
|
|
8869
8950
|
return selected;
|
|
8870
8951
|
}
|
|
8871
|
-
async function promptLearnInstall(targetAgent) {
|
|
8872
|
-
const hasClaude = targetAgent.includes("claude");
|
|
8873
|
-
const hasCursor = targetAgent.includes("cursor");
|
|
8874
|
-
const agentName = hasClaude && hasCursor ? "Claude and Cursor" : hasClaude ? "Claude" : "Cursor";
|
|
8875
|
-
console.log(chalk11.bold(`
|
|
8876
|
-
Session Learning
|
|
8877
|
-
`));
|
|
8878
|
-
console.log(chalk11.dim(` Caliber can learn from your ${agentName} sessions \u2014 when a tool fails`));
|
|
8879
|
-
console.log(chalk11.dim(` or you correct a mistake, it captures the lesson so it won't`));
|
|
8880
|
-
console.log(chalk11.dim(` happen again. Runs once at session end using the fast model.
|
|
8881
|
-
`));
|
|
8882
|
-
return select5({
|
|
8883
|
-
message: "Enable session learning?",
|
|
8884
|
-
choices: [
|
|
8885
|
-
{ name: "Enable session learning (recommended)", value: true },
|
|
8886
|
-
{ name: "Skip for now", value: false }
|
|
8887
|
-
]
|
|
8888
|
-
});
|
|
8889
|
-
}
|
|
8890
8952
|
async function promptReviewAction(hasSkillResults, hasChanges, staged) {
|
|
8891
8953
|
if (!hasChanges && !hasSkillResults) return "accept";
|
|
8892
8954
|
const choices = [];
|
|
@@ -9345,10 +9407,9 @@ async function initCommand(options) {
|
|
|
9345
9407
|
console.log(chalk14.dim(" Keep your AI agent configs in sync \u2014 automatically."));
|
|
9346
9408
|
console.log(chalk14.dim(" Works across Claude Code, Cursor, Codex, and GitHub Copilot.\n"));
|
|
9347
9409
|
console.log(title.bold(" How it works:\n"));
|
|
9348
|
-
console.log(chalk14.dim(" 1. Connect
|
|
9349
|
-
console.log(chalk14.dim(" 2.
|
|
9350
|
-
console.log(chalk14.dim(" 3.
|
|
9351
|
-
console.log(chalk14.dim(" 4. Finalize Review changes and score your setup\n"));
|
|
9410
|
+
console.log(chalk14.dim(" 1. Connect Auto-detect your LLM provider and agents"));
|
|
9411
|
+
console.log(chalk14.dim(" 2. Build Install sync, scan your project, generate configs"));
|
|
9412
|
+
console.log(chalk14.dim(" 3. Done Review score and start syncing\n"));
|
|
9352
9413
|
} else {
|
|
9353
9414
|
console.log(brand.bold("\n CALIBER") + chalk14.dim(" \u2014 setting up continuous sync\n"));
|
|
9354
9415
|
}
|
|
@@ -9358,19 +9419,50 @@ async function initCommand(options) {
|
|
|
9358
9419
|
console.log(chalk14.yellow(" Caliber will still generate config files, but they won't be auto-installed.\n"));
|
|
9359
9420
|
}
|
|
9360
9421
|
const report = options.debugReport ? new DebugReport() : null;
|
|
9361
|
-
console.log(title.bold(" Step 1/
|
|
9422
|
+
console.log(title.bold(" Step 1/3 \u2014 Connect\n"));
|
|
9362
9423
|
let config = loadConfig();
|
|
9424
|
+
if (!config && !options.autoApprove) {
|
|
9425
|
+
if (isClaudeCliAvailable()) {
|
|
9426
|
+
console.log(chalk14.dim(" Detected: Claude Code CLI (uses your Pro/Max/Team subscription)\n"));
|
|
9427
|
+
const useIt = await confirm2({ message: "Use Claude Code as your LLM provider?" });
|
|
9428
|
+
if (useIt) {
|
|
9429
|
+
const autoConfig = { provider: "claude-cli", model: "default" };
|
|
9430
|
+
writeConfigFile(autoConfig);
|
|
9431
|
+
config = autoConfig;
|
|
9432
|
+
}
|
|
9433
|
+
} else if (isCursorAgentAvailable() && isCursorLoggedIn()) {
|
|
9434
|
+
console.log(chalk14.dim(" Detected: Cursor (uses your existing subscription)\n"));
|
|
9435
|
+
const useIt = await confirm2({ message: "Use Cursor as your LLM provider?" });
|
|
9436
|
+
if (useIt) {
|
|
9437
|
+
const autoConfig = { provider: "cursor", model: "sonnet-4.6" };
|
|
9438
|
+
writeConfigFile(autoConfig);
|
|
9439
|
+
config = autoConfig;
|
|
9440
|
+
}
|
|
9441
|
+
}
|
|
9442
|
+
}
|
|
9363
9443
|
if (!config) {
|
|
9364
|
-
|
|
9365
|
-
|
|
9366
|
-
|
|
9367
|
-
|
|
9368
|
-
|
|
9444
|
+
if (options.autoApprove) {
|
|
9445
|
+
if (isClaudeCliAvailable()) {
|
|
9446
|
+
const autoConfig = { provider: "claude-cli", model: "default" };
|
|
9447
|
+
writeConfigFile(autoConfig);
|
|
9448
|
+
config = autoConfig;
|
|
9449
|
+
} else if (isCursorAgentAvailable() && isCursorLoggedIn()) {
|
|
9450
|
+
const autoConfig = { provider: "cursor", model: "sonnet-4.6" };
|
|
9451
|
+
writeConfigFile(autoConfig);
|
|
9452
|
+
config = autoConfig;
|
|
9453
|
+
}
|
|
9454
|
+
}
|
|
9369
9455
|
if (!config) {
|
|
9370
|
-
console.log(chalk14.
|
|
9371
|
-
|
|
9456
|
+
console.log(chalk14.dim(" No LLM provider detected.\n"));
|
|
9457
|
+
await runInteractiveProviderSetup({
|
|
9458
|
+
selectMessage: "How do you want to use Caliber? (choose LLM provider)"
|
|
9459
|
+
});
|
|
9460
|
+
config = loadConfig();
|
|
9461
|
+
if (!config) {
|
|
9462
|
+
console.log(chalk14.red(" Configuration cancelled or failed.\n"));
|
|
9463
|
+
throw new Error("__exit__");
|
|
9464
|
+
}
|
|
9372
9465
|
}
|
|
9373
|
-
console.log(chalk14.green(" \u2713 Provider saved\n"));
|
|
9374
9466
|
}
|
|
9375
9467
|
trackInitProviderSelected(config.provider, config.model, firstRun);
|
|
9376
9468
|
const displayModel = getDisplayModel(config);
|
|
@@ -9388,22 +9480,28 @@ async function initCommand(options) {
|
|
|
9388
9480
|
const agentAutoDetected = !options.agent;
|
|
9389
9481
|
if (options.agent) {
|
|
9390
9482
|
targetAgent = options.agent;
|
|
9391
|
-
} else if (options.autoApprove) {
|
|
9392
|
-
const detected = detectAgents(process.cwd());
|
|
9393
|
-
targetAgent = detected.length > 0 ? detected : ["claude"];
|
|
9394
|
-
log(options.verbose, `Auto-approve: using ${targetAgent.join(", ")}`);
|
|
9395
9483
|
} else {
|
|
9396
9484
|
const detected = detectAgents(process.cwd());
|
|
9397
|
-
|
|
9485
|
+
if (detected.length > 0 && (options.autoApprove || firstRun)) {
|
|
9486
|
+
targetAgent = detected;
|
|
9487
|
+
console.log(chalk14.dim(` Detected agents: ${detected.join(", ")}
|
|
9488
|
+
`));
|
|
9489
|
+
} else if (detected.length > 0) {
|
|
9490
|
+
console.log(chalk14.dim(` Detected agents: ${detected.join(", ")}
|
|
9491
|
+
`));
|
|
9492
|
+
const useDetected = await confirm2({ message: "Use detected agents?" });
|
|
9493
|
+
targetAgent = useDetected ? detected : await promptAgent();
|
|
9494
|
+
} else {
|
|
9495
|
+
targetAgent = options.autoApprove ? ["claude"] : await promptAgent();
|
|
9496
|
+
}
|
|
9398
9497
|
}
|
|
9399
9498
|
console.log(chalk14.dim(` Target: ${targetAgent.join(", ")}
|
|
9400
9499
|
`));
|
|
9401
9500
|
trackInitAgentSelected(targetAgent, agentAutoDetected);
|
|
9402
|
-
console.log(title.bold(" Step 2/
|
|
9403
|
-
console.log(chalk14.dim(" Installing sync infrastructure...\n"));
|
|
9501
|
+
console.log(title.bold(" Step 2/3 \u2014 Build\n"));
|
|
9404
9502
|
const hookResult = installPreCommitHook();
|
|
9405
9503
|
if (hookResult.installed) {
|
|
9406
|
-
console.log(` ${chalk14.green("\u2713")} Pre-commit hook installed
|
|
9504
|
+
console.log(` ${chalk14.green("\u2713")} Pre-commit hook installed`);
|
|
9407
9505
|
} else if (hookResult.alreadyInstalled) {
|
|
9408
9506
|
console.log(` ${chalk14.green("\u2713")} Pre-commit hook \u2014 active`);
|
|
9409
9507
|
}
|
|
@@ -9415,21 +9513,18 @@ async function initCommand(options) {
|
|
|
9415
9513
|
}
|
|
9416
9514
|
const skillsWritten = ensureBuiltinSkills2();
|
|
9417
9515
|
if (skillsWritten.length > 0) {
|
|
9418
|
-
console.log(` ${chalk14.green("\u2713")} Agent skills installed
|
|
9419
|
-
}
|
|
9420
|
-
|
|
9516
|
+
console.log(` ${chalk14.green("\u2713")} Agent skills installed`);
|
|
9517
|
+
}
|
|
9518
|
+
const hasLearnableAgent = targetAgent.includes("claude") || targetAgent.includes("cursor");
|
|
9519
|
+
if (hasLearnableAgent) {
|
|
9520
|
+
if (targetAgent.includes("claude")) installLearningHooks();
|
|
9521
|
+
if (targetAgent.includes("cursor")) installCursorLearningHooks();
|
|
9522
|
+
console.log(` ${chalk14.green("\u2713")} Session learning enabled`);
|
|
9523
|
+
trackInitLearnEnabled(true);
|
|
9421
9524
|
}
|
|
9422
9525
|
console.log("");
|
|
9423
|
-
console.log(chalk14.dim(" New team members can run /setup-caliber inside their coding agent"));
|
|
9424
|
-
console.log(chalk14.dim(" (Claude Code or Cursor) to get set up automatically.\n"));
|
|
9425
9526
|
let baselineScore = computeLocalScore(process.cwd(), targetAgent);
|
|
9426
|
-
|
|
9427
|
-
displayScoreSummary(baselineScore);
|
|
9428
|
-
if (options.verbose) {
|
|
9429
|
-
for (const c of baselineScore.checks) {
|
|
9430
|
-
log(options.verbose, ` ${c.passed ? "\u2713" : "\u2717"} ${c.name}: ${c.earnedPoints}/${c.maxPoints}${c.suggestion ? ` \u2014 ${c.suggestion}` : ""}`);
|
|
9431
|
-
}
|
|
9432
|
-
}
|
|
9527
|
+
log(options.verbose, `Baseline score: ${baselineScore.score}/100`);
|
|
9433
9528
|
if (report) {
|
|
9434
9529
|
report.markStep("Baseline scoring");
|
|
9435
9530
|
report.addSection("Scoring: Baseline", `**Score**: ${baselineScore.score}/100
|
|
@@ -9450,25 +9545,15 @@ async function initCommand(options) {
|
|
|
9450
9545
|
]);
|
|
9451
9546
|
const passingCount = baselineScore.checks.filter((c) => c.passed).length;
|
|
9452
9547
|
const failingCount = baselineScore.checks.filter((c) => !c.passed).length;
|
|
9548
|
+
trackInitScoreComputed(baselineScore.score, passingCount, failingCount, false);
|
|
9453
9549
|
let skipGeneration = false;
|
|
9454
|
-
if (hasExistingConfig && baselineScore.score === 100) {
|
|
9455
|
-
|
|
9456
|
-
console.log(chalk14.bold.green("\n Your config is already optimal.\n"));
|
|
9457
|
-
skipGeneration = !options.force;
|
|
9550
|
+
if (hasExistingConfig && baselineScore.score === 100 && !options.force) {
|
|
9551
|
+
skipGeneration = true;
|
|
9458
9552
|
} else if (hasExistingConfig && !options.force && !options.autoApprove) {
|
|
9459
|
-
|
|
9460
|
-
|
|
9461
|
-
|
|
9462
|
-
|
|
9463
|
-
skipGeneration = auditAnswer.toLowerCase() === "n";
|
|
9464
|
-
} else if (!hasExistingConfig && !options.force && !options.autoApprove) {
|
|
9465
|
-
trackInitScoreComputed(baselineScore.score, passingCount, failingCount, false);
|
|
9466
|
-
console.log(chalk14.dim("\n Sync infrastructure is ready. Caliber can also generate tailored"));
|
|
9467
|
-
console.log(chalk14.dim(" CLAUDE.md, Cursor rules, and Codex configs for your project.\n"));
|
|
9468
|
-
const generateAnswer = await promptInput(" Generate agent configs? (Y/n) ");
|
|
9469
|
-
skipGeneration = generateAnswer.toLowerCase() === "n";
|
|
9470
|
-
} else {
|
|
9471
|
-
trackInitScoreComputed(baselineScore.score, passingCount, failingCount, false);
|
|
9553
|
+
console.log(chalk14.dim(` Config score: ${baselineScore.score}/100 \u2014 Caliber can improve this.
|
|
9554
|
+
`));
|
|
9555
|
+
const improveAnswer = await confirm2({ message: "Improve your existing configs?" });
|
|
9556
|
+
skipGeneration = !improveAnswer;
|
|
9472
9557
|
}
|
|
9473
9558
|
if (skipGeneration) {
|
|
9474
9559
|
const {
|
|
@@ -9525,6 +9610,7 @@ async function initCommand(options) {
|
|
|
9525
9610
|
lastRefreshTimestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9526
9611
|
targetAgent
|
|
9527
9612
|
});
|
|
9613
|
+
trackInitCompleted("sync-only", baselineScore.score);
|
|
9528
9614
|
console.log(chalk14.bold.green("\n Caliber sync is set up!\n"));
|
|
9529
9615
|
console.log(chalk14.dim(" Your agent configs will sync automatically on every commit."));
|
|
9530
9616
|
console.log(chalk14.dim(" Run ") + title(`${bin} init --force`) + chalk14.dim(" anytime to generate or improve configs.\n"));
|
|
@@ -9532,7 +9618,6 @@ async function initCommand(options) {
|
|
|
9532
9618
|
}
|
|
9533
9619
|
const allFailingChecks = baselineScore.checks.filter((c) => !c.passed && c.maxPoints > 0);
|
|
9534
9620
|
const llmFixableChecks = allFailingChecks.filter((c) => !NON_LLM_CHECKS.has(c.id));
|
|
9535
|
-
console.log(title.bold("\n Step 3/4 \u2014 Generate\n"));
|
|
9536
9621
|
const genModelInfo = fastModel ? ` Using ${displayModel} for docs, ${fastModel} for skills` : ` Using ${displayModel}`;
|
|
9537
9622
|
console.log(chalk14.dim(genModelInfo + "\n"));
|
|
9538
9623
|
if (report) report.markStep("Generation");
|
|
@@ -9731,7 +9816,7 @@ async function initCommand(options) {
|
|
|
9731
9816
|
report.addJson("Generation: Parsed Config", generatedSetup);
|
|
9732
9817
|
}
|
|
9733
9818
|
log(options.verbose, `Generation completed: ${elapsedMs}ms, stopReason: ${genStopReason || "end_turn"}`);
|
|
9734
|
-
console.log(title.bold(" Step
|
|
9819
|
+
console.log(title.bold(" Step 3/3 \u2014 Done\n"));
|
|
9735
9820
|
const setupFiles = collectSetupFiles(generatedSetup, targetAgent);
|
|
9736
9821
|
const staged = stageFiles(setupFiles, process.cwd());
|
|
9737
9822
|
const totalChanges = staged.newFiles + staged.modifiedFiles;
|
|
@@ -9875,6 +9960,7 @@ ${agentRefs.join(" ")}
|
|
|
9875
9960
|
` + afterScore.checks.map((c) => `| ${c.name} | ${c.passed ? "Yes" : "No"} | ${c.earnedPoints} | ${c.maxPoints} |`).join("\n"));
|
|
9876
9961
|
}
|
|
9877
9962
|
recordScore(afterScore, "init");
|
|
9963
|
+
trackInitCompleted("full-generation", afterScore.score);
|
|
9878
9964
|
displayScoreDelta(baselineScore, afterScore);
|
|
9879
9965
|
if (options.verbose) {
|
|
9880
9966
|
log(options.verbose, `Final score: ${afterScore.score}/100`);
|
|
@@ -9892,64 +9978,26 @@ ${agentRefs.join(" ")}
|
|
|
9892
9978
|
communitySkillsInstalled = selected.length;
|
|
9893
9979
|
}
|
|
9894
9980
|
}
|
|
9895
|
-
console.log("");
|
|
9896
|
-
console.log(` ${chalk14.green("\u2713")} Docs auto-refresh ${chalk14.dim(`agents run ${resolveCaliber()} refresh before commits`)}`);
|
|
9897
9981
|
trackInitHookSelected("config-instructions");
|
|
9898
|
-
const hasLearnableAgent = targetAgent.includes("claude") || targetAgent.includes("cursor");
|
|
9899
|
-
let enableLearn = false;
|
|
9900
|
-
if (hasLearnableAgent) {
|
|
9901
|
-
if (!options.autoApprove) {
|
|
9902
|
-
enableLearn = await promptLearnInstall(targetAgent);
|
|
9903
|
-
trackInitLearnEnabled(enableLearn);
|
|
9904
|
-
if (enableLearn) {
|
|
9905
|
-
if (targetAgent.includes("claude")) {
|
|
9906
|
-
const r = installLearningHooks();
|
|
9907
|
-
if (r.installed) console.log(` ${chalk14.green("\u2713")} Learning hooks installed for Claude Code`);
|
|
9908
|
-
else if (r.alreadyInstalled) console.log(chalk14.dim(" Claude Code learning hooks already installed"));
|
|
9909
|
-
}
|
|
9910
|
-
if (targetAgent.includes("cursor")) {
|
|
9911
|
-
const r = installCursorLearningHooks();
|
|
9912
|
-
if (r.installed) console.log(` ${chalk14.green("\u2713")} Learning hooks installed for Cursor`);
|
|
9913
|
-
else if (r.alreadyInstalled) console.log(chalk14.dim(" Cursor learning hooks already installed"));
|
|
9914
|
-
}
|
|
9915
|
-
console.log(chalk14.dim(" Run ") + chalk14.hex("#83D1EB")(`${bin} learn status`) + chalk14.dim(" to see insights"));
|
|
9916
|
-
} else {
|
|
9917
|
-
console.log(chalk14.dim(" Skipped. Run ") + chalk14.hex("#83D1EB")(`${bin} learn install`) + chalk14.dim(" later to enable."));
|
|
9918
|
-
}
|
|
9919
|
-
} else {
|
|
9920
|
-
enableLearn = true;
|
|
9921
|
-
if (targetAgent.includes("claude")) installLearningHooks();
|
|
9922
|
-
if (targetAgent.includes("cursor")) installCursorLearningHooks();
|
|
9923
|
-
}
|
|
9924
|
-
}
|
|
9925
|
-
console.log(chalk14.bold.green("\n Caliber is set up!"));
|
|
9926
|
-
console.log(chalk14.dim(" Your AI agent configs will now stay in sync with your codebase automatically."));
|
|
9927
|
-
console.log(chalk14.dim(" Every commit refreshes configs for all your agents. All changes are backed up.\n"));
|
|
9928
9982
|
const done = chalk14.green("\u2713");
|
|
9929
|
-
|
|
9930
|
-
console.log(chalk14.bold(" What
|
|
9931
|
-
console.log(` ${done} Continuous sync
|
|
9932
|
-
console.log(` ${done} Config generated
|
|
9933
|
-
console.log(` ${done} Agent skills
|
|
9983
|
+
console.log(chalk14.bold.green("\n Caliber is set up!\n"));
|
|
9984
|
+
console.log(chalk14.bold(" What's configured:\n"));
|
|
9985
|
+
console.log(` ${done} Continuous sync ${chalk14.dim("pre-commit hook keeps all agent configs in sync")}`);
|
|
9986
|
+
console.log(` ${done} Config generated ${chalk14.dim(`score: ${afterScore.score}/100`)}`);
|
|
9987
|
+
console.log(` ${done} Agent skills ${chalk14.dim("/setup-caliber for new team members")}`);
|
|
9934
9988
|
if (hasLearnableAgent) {
|
|
9935
|
-
|
|
9936
|
-
console.log(` ${done} Session learning ${chalk14.dim("agent learns from your feedback")}`);
|
|
9937
|
-
} else {
|
|
9938
|
-
console.log(` ${skip} Session learning ${title(`${bin} learn install`)} ${chalk14.dim("to enable later")}`);
|
|
9939
|
-
}
|
|
9989
|
+
console.log(` ${done} Session learning ${chalk14.dim("learns from your corrections")}`);
|
|
9940
9990
|
}
|
|
9941
9991
|
if (communitySkillsInstalled > 0) {
|
|
9942
|
-
console.log(` ${done} Community skills
|
|
9943
|
-
} else if (skillSearchResult.results.length > 0) {
|
|
9944
|
-
console.log(` ${skip} Community skills ${chalk14.dim("available but skipped")}`);
|
|
9992
|
+
console.log(` ${done} Community skills ${chalk14.dim(`${communitySkillsInstalled} installed for your stack`)}`);
|
|
9945
9993
|
}
|
|
9946
9994
|
console.log(chalk14.bold("\n What happens next:\n"));
|
|
9947
|
-
console.log(chalk14.dim(" Every commit
|
|
9948
|
-
console.log(chalk14.dim(" New team members
|
|
9949
|
-
console.log(
|
|
9950
|
-
console.log(` ${title(`${bin}
|
|
9951
|
-
console.log(` ${title(`${bin}
|
|
9952
|
-
console.log(` ${title(`${bin}
|
|
9995
|
+
console.log(chalk14.dim(" Every commit syncs your agent configs automatically."));
|
|
9996
|
+
console.log(chalk14.dim(" New team members run /setup-caliber to get set up instantly.\n"));
|
|
9997
|
+
console.log(` ${title(`${bin} score`)} Full scoring breakdown`);
|
|
9998
|
+
console.log(` ${title(`${bin} skills`)} Find community skills`);
|
|
9999
|
+
console.log(` ${title(`${bin} undo`)} Revert changes`);
|
|
10000
|
+
console.log(` ${title(`${bin} uninstall`)} Remove Caliber completely`);
|
|
9953
10001
|
console.log("");
|
|
9954
10002
|
if (options.showTokens) {
|
|
9955
10003
|
displayTokenUsage();
|
|
@@ -10835,7 +10883,8 @@ async function refreshSingleRepo(repoDir, options) {
|
|
|
10835
10883
|
}
|
|
10836
10884
|
}
|
|
10837
10885
|
const written = writeRefreshDocs(response.updatedDocs);
|
|
10838
|
-
|
|
10886
|
+
const trigger = quiet ? "hook" : "manual";
|
|
10887
|
+
trackRefreshCompleted(written.length, Date.now(), trigger);
|
|
10839
10888
|
const postScore = computeLocalScore(repoDir, targetAgent);
|
|
10840
10889
|
if (postScore.score < preScore.score) {
|
|
10841
10890
|
for (const [filePath, content] of preRefreshContents) {
|
|
@@ -12539,10 +12588,199 @@ async function publishCommand() {
|
|
|
12539
12588
|
}
|
|
12540
12589
|
}
|
|
12541
12590
|
|
|
12591
|
+
// src/commands/bootstrap.ts
|
|
12592
|
+
init_builtin_skills();
|
|
12593
|
+
import fs47 from "fs";
|
|
12594
|
+
import chalk27 from "chalk";
|
|
12595
|
+
var PLATFORM_SKILL_DIRS = {
|
|
12596
|
+
claude: ".claude/skills",
|
|
12597
|
+
cursor: ".cursor/skills",
|
|
12598
|
+
codex: ".agents/skills"
|
|
12599
|
+
};
|
|
12600
|
+
async function bootstrapCommand() {
|
|
12601
|
+
const platforms = detectPlatforms();
|
|
12602
|
+
const detected = [];
|
|
12603
|
+
if (platforms.claude) detected.push("claude");
|
|
12604
|
+
if (platforms.cursor) detected.push("cursor");
|
|
12605
|
+
if (platforms.codex) detected.push("codex");
|
|
12606
|
+
if (detected.length === 0) detected.push("claude");
|
|
12607
|
+
const written = [];
|
|
12608
|
+
for (const platform of detected) {
|
|
12609
|
+
const skillsDir = PLATFORM_SKILL_DIRS[platform];
|
|
12610
|
+
if (!skillsDir) continue;
|
|
12611
|
+
for (const skill of BUILTIN_SKILLS) {
|
|
12612
|
+
const skillDir = `${skillsDir}/${skill.name}`;
|
|
12613
|
+
const skillPath = `${skillDir}/SKILL.md`;
|
|
12614
|
+
fs47.mkdirSync(skillDir, { recursive: true });
|
|
12615
|
+
fs47.writeFileSync(skillPath, buildSkillContent(skill));
|
|
12616
|
+
written.push(skillPath);
|
|
12617
|
+
}
|
|
12618
|
+
}
|
|
12619
|
+
if (written.length === 0) {
|
|
12620
|
+
console.log(chalk27.yellow("No skills were written."));
|
|
12621
|
+
return;
|
|
12622
|
+
}
|
|
12623
|
+
console.log(chalk27.bold.green("\n Caliber skills installed!\n"));
|
|
12624
|
+
for (const file of written) {
|
|
12625
|
+
console.log(` ${chalk27.green("\u2713")} ${file}`);
|
|
12626
|
+
}
|
|
12627
|
+
console.log(chalk27.dim("\n Your agent can now run /setup-caliber to complete the setup."));
|
|
12628
|
+
console.log(chalk27.dim(' Just tell your agent: "Run /setup-caliber"\n'));
|
|
12629
|
+
}
|
|
12630
|
+
|
|
12631
|
+
// src/commands/uninstall.ts
|
|
12632
|
+
import fs48 from "fs";
|
|
12633
|
+
import path38 from "path";
|
|
12634
|
+
import chalk28 from "chalk";
|
|
12635
|
+
import confirm3 from "@inquirer/confirm";
|
|
12636
|
+
init_pre_commit_block();
|
|
12637
|
+
init_builtin_skills();
|
|
12638
|
+
init_config();
|
|
12639
|
+
var MANAGED_DOC_FILES = [
|
|
12640
|
+
"CLAUDE.md",
|
|
12641
|
+
path38.join(".github", "copilot-instructions.md"),
|
|
12642
|
+
"AGENTS.md"
|
|
12643
|
+
];
|
|
12644
|
+
var SKILL_DIRS = PLATFORM_CONFIGS.map((c) => c.skillsDir);
|
|
12645
|
+
var CURSOR_RULES_DIR = path38.join(".cursor", "rules");
|
|
12646
|
+
function removeCaliberCursorRules() {
|
|
12647
|
+
const removed = [];
|
|
12648
|
+
if (!fs48.existsSync(CURSOR_RULES_DIR)) return removed;
|
|
12649
|
+
for (const file of fs48.readdirSync(CURSOR_RULES_DIR)) {
|
|
12650
|
+
if (file.startsWith("caliber-") && file.endsWith(".mdc")) {
|
|
12651
|
+
const fullPath = path38.join(CURSOR_RULES_DIR, file);
|
|
12652
|
+
fs48.unlinkSync(fullPath);
|
|
12653
|
+
removed.push(fullPath);
|
|
12654
|
+
}
|
|
12655
|
+
}
|
|
12656
|
+
return removed;
|
|
12657
|
+
}
|
|
12658
|
+
function removeBuiltinSkills() {
|
|
12659
|
+
const removed = [];
|
|
12660
|
+
for (const skillsDir of SKILL_DIRS) {
|
|
12661
|
+
if (!fs48.existsSync(skillsDir)) continue;
|
|
12662
|
+
for (const name of BUILTIN_SKILL_NAMES) {
|
|
12663
|
+
const skillDir = path38.join(skillsDir, name);
|
|
12664
|
+
if (fs48.existsSync(skillDir)) {
|
|
12665
|
+
fs48.rmSync(skillDir, { recursive: true });
|
|
12666
|
+
removed.push(skillDir);
|
|
12667
|
+
}
|
|
12668
|
+
}
|
|
12669
|
+
}
|
|
12670
|
+
return removed;
|
|
12671
|
+
}
|
|
12672
|
+
function stripManagedBlocksFromFiles() {
|
|
12673
|
+
const modified = [];
|
|
12674
|
+
for (const filePath of MANAGED_DOC_FILES) {
|
|
12675
|
+
if (!fs48.existsSync(filePath)) continue;
|
|
12676
|
+
const original = fs48.readFileSync(filePath, "utf-8");
|
|
12677
|
+
const stripped = stripManagedBlocks(original);
|
|
12678
|
+
if (stripped !== original) {
|
|
12679
|
+
const trimmed = stripped.trim();
|
|
12680
|
+
if (!trimmed || /^#\s*\S*$/.test(trimmed)) {
|
|
12681
|
+
fs48.unlinkSync(filePath);
|
|
12682
|
+
} else {
|
|
12683
|
+
fs48.writeFileSync(filePath, stripped);
|
|
12684
|
+
}
|
|
12685
|
+
modified.push(filePath);
|
|
12686
|
+
}
|
|
12687
|
+
}
|
|
12688
|
+
return modified;
|
|
12689
|
+
}
|
|
12690
|
+
function removeDirectory(dir) {
|
|
12691
|
+
if (!fs48.existsSync(dir)) return false;
|
|
12692
|
+
fs48.rmSync(dir, { recursive: true });
|
|
12693
|
+
return true;
|
|
12694
|
+
}
|
|
12695
|
+
async function uninstallCommand(options) {
|
|
12696
|
+
console.log(chalk28.bold("\n Caliber Uninstall\n"));
|
|
12697
|
+
console.log(chalk28.dim(" This will remove all Caliber resources from this project:\n"));
|
|
12698
|
+
console.log(chalk28.dim(" \u2022 Pre-commit hook"));
|
|
12699
|
+
console.log(chalk28.dim(" \u2022 Session learning hooks"));
|
|
12700
|
+
console.log(chalk28.dim(" \u2022 Managed blocks in CLAUDE.md, AGENTS.md, copilot-instructions.md"));
|
|
12701
|
+
console.log(chalk28.dim(" \u2022 Cursor rules (caliber-*.mdc)"));
|
|
12702
|
+
console.log(chalk28.dim(" \u2022 Built-in skills (setup-caliber, find-skills, save-learning)"));
|
|
12703
|
+
console.log(chalk28.dim(" \u2022 CALIBER_LEARNINGS.md"));
|
|
12704
|
+
console.log(chalk28.dim(" \u2022 .caliber/ directory (backups, cache, state)\n"));
|
|
12705
|
+
if (!options.force) {
|
|
12706
|
+
const proceed = await confirm3({ message: "Continue with uninstall?" });
|
|
12707
|
+
if (!proceed) {
|
|
12708
|
+
console.log(chalk28.dim("\n Cancelled.\n"));
|
|
12709
|
+
return;
|
|
12710
|
+
}
|
|
12711
|
+
}
|
|
12712
|
+
console.log("");
|
|
12713
|
+
const actions = [];
|
|
12714
|
+
const hookResult = removePreCommitHook();
|
|
12715
|
+
if (hookResult.removed) {
|
|
12716
|
+
console.log(` ${chalk28.red("\u2717")} Pre-commit hook removed`);
|
|
12717
|
+
actions.push("pre-commit hook");
|
|
12718
|
+
}
|
|
12719
|
+
const learnResult = removeLearningHooks();
|
|
12720
|
+
if (learnResult.removed) {
|
|
12721
|
+
console.log(` ${chalk28.red("\u2717")} Claude Code learning hooks removed`);
|
|
12722
|
+
actions.push("claude learning hooks");
|
|
12723
|
+
}
|
|
12724
|
+
const cursorLearnResult = removeCursorLearningHooks();
|
|
12725
|
+
if (cursorLearnResult.removed) {
|
|
12726
|
+
console.log(` ${chalk28.red("\u2717")} Cursor learning hooks removed`);
|
|
12727
|
+
actions.push("cursor learning hooks");
|
|
12728
|
+
}
|
|
12729
|
+
const strippedFiles = stripManagedBlocksFromFiles();
|
|
12730
|
+
for (const file of strippedFiles) {
|
|
12731
|
+
console.log(` ${chalk28.yellow("~")} ${file} \u2014 managed blocks removed`);
|
|
12732
|
+
actions.push(file);
|
|
12733
|
+
}
|
|
12734
|
+
const removedRules = removeCaliberCursorRules();
|
|
12735
|
+
for (const rule of removedRules) {
|
|
12736
|
+
console.log(` ${chalk28.red("\u2717")} ${rule}`);
|
|
12737
|
+
}
|
|
12738
|
+
if (removedRules.length > 0) actions.push("cursor rules");
|
|
12739
|
+
const removedSkills = removeBuiltinSkills();
|
|
12740
|
+
for (const skill of removedSkills) {
|
|
12741
|
+
console.log(` ${chalk28.red("\u2717")} ${skill}/`);
|
|
12742
|
+
}
|
|
12743
|
+
if (removedSkills.length > 0) actions.push("builtin skills");
|
|
12744
|
+
if (fs48.existsSync("CALIBER_LEARNINGS.md")) {
|
|
12745
|
+
fs48.unlinkSync("CALIBER_LEARNINGS.md");
|
|
12746
|
+
console.log(` ${chalk28.red("\u2717")} CALIBER_LEARNINGS.md`);
|
|
12747
|
+
actions.push("learnings file");
|
|
12748
|
+
}
|
|
12749
|
+
if (removeDirectory(CALIBER_DIR)) {
|
|
12750
|
+
console.log(` ${chalk28.red("\u2717")} .caliber/ directory`);
|
|
12751
|
+
actions.push(".caliber directory");
|
|
12752
|
+
}
|
|
12753
|
+
if (actions.length === 0) {
|
|
12754
|
+
console.log(chalk28.dim(" Nothing to remove \u2014 Caliber is not installed in this project.\n"));
|
|
12755
|
+
return;
|
|
12756
|
+
}
|
|
12757
|
+
trackUninstallExecuted();
|
|
12758
|
+
const configPath = getConfigFilePath();
|
|
12759
|
+
if (fs48.existsSync(configPath)) {
|
|
12760
|
+
console.log("");
|
|
12761
|
+
const removeConfig = options.force || await confirm3({
|
|
12762
|
+
message: `Remove global config (~/.caliber/config.json)? This affects all projects.`
|
|
12763
|
+
});
|
|
12764
|
+
if (removeConfig) {
|
|
12765
|
+
fs48.unlinkSync(configPath);
|
|
12766
|
+
console.log(` ${chalk28.red("\u2717")} ${configPath}`);
|
|
12767
|
+
const configDir = path38.dirname(configPath);
|
|
12768
|
+
try {
|
|
12769
|
+
const remaining = fs48.readdirSync(configDir);
|
|
12770
|
+
if (remaining.length === 0) fs48.rmdirSync(configDir);
|
|
12771
|
+
} catch {
|
|
12772
|
+
}
|
|
12773
|
+
}
|
|
12774
|
+
}
|
|
12775
|
+
console.log(chalk28.bold.green(`
|
|
12776
|
+
Caliber has been removed from this project.`));
|
|
12777
|
+
console.log(chalk28.dim(" Your code is untouched \u2014 only Caliber config files were removed.\n"));
|
|
12778
|
+
}
|
|
12779
|
+
|
|
12542
12780
|
// src/cli.ts
|
|
12543
|
-
var __dirname =
|
|
12781
|
+
var __dirname = path39.dirname(fileURLToPath(import.meta.url));
|
|
12544
12782
|
var pkg = JSON.parse(
|
|
12545
|
-
|
|
12783
|
+
fs49.readFileSync(path39.resolve(__dirname, "..", "package.json"), "utf-8")
|
|
12546
12784
|
);
|
|
12547
12785
|
var program = new Command();
|
|
12548
12786
|
var displayVersion = process.env.CALIBER_LOCAL ? `${pkg.version}-local` : pkg.version;
|
|
@@ -12550,9 +12788,11 @@ program.name(process.env.CALIBER_LOCAL ? "caloc" : "caliber").description("AI co
|
|
|
12550
12788
|
function tracked(commandName, handler) {
|
|
12551
12789
|
const wrapper = async (...args) => {
|
|
12552
12790
|
const start = Date.now();
|
|
12791
|
+
const isCI = !!(process.env.CI || process.env.GITHUB_ACTIONS);
|
|
12553
12792
|
trackEvent("command_started", {
|
|
12554
12793
|
command: commandName,
|
|
12555
|
-
cli_version: pkg.version
|
|
12794
|
+
cli_version: pkg.version,
|
|
12795
|
+
is_ci: isCI
|
|
12556
12796
|
});
|
|
12557
12797
|
try {
|
|
12558
12798
|
await handler(...args);
|
|
@@ -12604,7 +12844,9 @@ function parseAgentOption(value) {
|
|
|
12604
12844
|
return agents;
|
|
12605
12845
|
}
|
|
12606
12846
|
program.command("init").description("Initialize your project for AI-assisted development").option("--agent <type>", "Target agents (comma-separated): claude, cursor, codex, github-copilot", parseAgentOption).option("--source <paths...>", "Related source paths to include as context").option("--dry-run", "Preview changes without writing files").option("--force", "Overwrite existing config without prompting").option("--debug-report", void 0, false).option("--show-tokens", "Show token usage summary at the end").option("--auto-approve", "Run without interactive prompts (auto-accept all)").option("--verbose", "Show detailed logs of each step").action(tracked("init", initCommand));
|
|
12847
|
+
program.command("bootstrap").description("Install agent skills (/setup-caliber, /find-skills, /save-learning) without running init").action(tracked("bootstrap", bootstrapCommand));
|
|
12607
12848
|
program.command("undo").description("Revert all config changes made by Caliber").action(tracked("undo", undoCommand));
|
|
12849
|
+
program.command("uninstall").description("Remove all Caliber resources from this project").option("--force", "Skip confirmation prompt").action(tracked("uninstall", (options) => uninstallCommand(options)));
|
|
12608
12850
|
program.command("status").description("Show current Caliber config status").option("--json", "Output as JSON").action(tracked("status", statusCommand));
|
|
12609
12851
|
program.command("regenerate").alias("regen").alias("re").description("Re-analyze project and regenerate config").option("--dry-run", "Preview changes without writing files").action(tracked("regenerate", regenerateCommand));
|
|
12610
12852
|
program.command("config").description("Configure LLM provider, API key, and model").action(tracked("config", configCommand));
|
|
@@ -12629,16 +12871,16 @@ learn.command("delete <index>").description("Delete a learning by its index numb
|
|
|
12629
12871
|
learn.command("add <content>").description("Add a learning directly (used by agent skills)").option("--personal", "Save as a personal learning instead of project-level").action(tracked("learn:add", learnAddCommand));
|
|
12630
12872
|
|
|
12631
12873
|
// src/utils/version-check.ts
|
|
12632
|
-
import
|
|
12633
|
-
import
|
|
12874
|
+
import fs50 from "fs";
|
|
12875
|
+
import path40 from "path";
|
|
12634
12876
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
12635
12877
|
import { execSync as execSync16, execFileSync as execFileSync3 } from "child_process";
|
|
12636
|
-
import
|
|
12878
|
+
import chalk29 from "chalk";
|
|
12637
12879
|
import ora8 from "ora";
|
|
12638
|
-
import
|
|
12639
|
-
var __dirname_vc =
|
|
12880
|
+
import confirm4 from "@inquirer/confirm";
|
|
12881
|
+
var __dirname_vc = path40.dirname(fileURLToPath2(import.meta.url));
|
|
12640
12882
|
var pkg2 = JSON.parse(
|
|
12641
|
-
|
|
12883
|
+
fs50.readFileSync(path40.resolve(__dirname_vc, "..", "package.json"), "utf-8")
|
|
12642
12884
|
);
|
|
12643
12885
|
function getChannel(version) {
|
|
12644
12886
|
const match = version.match(/-(dev|next)\./);
|
|
@@ -12663,8 +12905,8 @@ function isNewer(registry, current) {
|
|
|
12663
12905
|
function getInstalledVersion() {
|
|
12664
12906
|
try {
|
|
12665
12907
|
const globalRoot = execSync16("npm root -g", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
12666
|
-
const pkgPath =
|
|
12667
|
-
return JSON.parse(
|
|
12908
|
+
const pkgPath = path40.join(globalRoot, "@rely-ai", "caliber", "package.json");
|
|
12909
|
+
return JSON.parse(fs50.readFileSync(pkgPath, "utf-8")).version;
|
|
12668
12910
|
} catch {
|
|
12669
12911
|
return null;
|
|
12670
12912
|
}
|
|
@@ -12689,20 +12931,20 @@ async function checkForUpdates() {
|
|
|
12689
12931
|
if (!isInteractive) {
|
|
12690
12932
|
const installTag = channel === "latest" ? "" : `@${channel}`;
|
|
12691
12933
|
console.log(
|
|
12692
|
-
|
|
12934
|
+
chalk29.yellow(
|
|
12693
12935
|
`
|
|
12694
12936
|
Update available: ${current} -> ${latest}
|
|
12695
|
-
Run ${
|
|
12937
|
+
Run ${chalk29.bold(`npm install -g @rely-ai/caliber${installTag}`)} to upgrade.
|
|
12696
12938
|
`
|
|
12697
12939
|
)
|
|
12698
12940
|
);
|
|
12699
12941
|
return;
|
|
12700
12942
|
}
|
|
12701
12943
|
console.log(
|
|
12702
|
-
|
|
12944
|
+
chalk29.yellow(`
|
|
12703
12945
|
Update available: ${current} -> ${latest}`)
|
|
12704
12946
|
);
|
|
12705
|
-
const shouldUpdate = await
|
|
12947
|
+
const shouldUpdate = await confirm4({ message: "Would you like to update now? (Y/n)", default: true });
|
|
12706
12948
|
if (!shouldUpdate) {
|
|
12707
12949
|
console.log();
|
|
12708
12950
|
return;
|
|
@@ -12719,13 +12961,13 @@ Update available: ${current} -> ${latest}`)
|
|
|
12719
12961
|
const installed = getInstalledVersion();
|
|
12720
12962
|
if (installed !== latest) {
|
|
12721
12963
|
spinner.fail(`Update incomplete \u2014 got ${installed ?? "unknown"}, expected ${latest}`);
|
|
12722
|
-
console.log(
|
|
12964
|
+
console.log(chalk29.yellow(`Run ${chalk29.bold(`npm install -g @rely-ai/caliber@${tag}`)} manually.
|
|
12723
12965
|
`));
|
|
12724
12966
|
return;
|
|
12725
12967
|
}
|
|
12726
|
-
spinner.succeed(
|
|
12968
|
+
spinner.succeed(chalk29.green(`Updated to ${latest}`));
|
|
12727
12969
|
const args = process.argv.slice(2);
|
|
12728
|
-
console.log(
|
|
12970
|
+
console.log(chalk29.dim(`
|
|
12729
12971
|
Restarting: caliber ${args.join(" ")}
|
|
12730
12972
|
`));
|
|
12731
12973
|
execFileSync3("caliber", args, {
|
|
@@ -12738,11 +12980,11 @@ Restarting: caliber ${args.join(" ")}
|
|
|
12738
12980
|
if (err instanceof Error) {
|
|
12739
12981
|
const stderr = err.stderr;
|
|
12740
12982
|
const errMsg = stderr ? String(stderr).trim().split("\n").pop() : err.message.split("\n")[0];
|
|
12741
|
-
if (errMsg && !errMsg.includes("SIGTERM")) console.log(
|
|
12983
|
+
if (errMsg && !errMsg.includes("SIGTERM")) console.log(chalk29.dim(` ${errMsg}`));
|
|
12742
12984
|
}
|
|
12743
12985
|
console.log(
|
|
12744
|
-
|
|
12745
|
-
`Run ${
|
|
12986
|
+
chalk29.yellow(
|
|
12987
|
+
`Run ${chalk29.bold(`npm install -g @rely-ai/caliber@${tag}`)} manually to upgrade.
|
|
12746
12988
|
`
|
|
12747
12989
|
)
|
|
12748
12990
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rely-ai/caliber",
|
|
3
|
-
"version": "1.31.0-dev.
|
|
3
|
+
"version": "1.31.0-dev.1774815271",
|
|
4
4
|
"description": "AI context infrastructure for coding agents — keeps CLAUDE.md, Cursor rules, and skills in sync as your codebase evolves",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|