@cleocode/caamp 2026.4.0 → 2026.4.3

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/cli.js CHANGED
@@ -3,27 +3,18 @@ import {
3
3
  CANONICAL_SKILLS_DIR,
4
4
  MarketplaceClient,
5
5
  RECOMMENDATION_ERROR_CODES,
6
- applyMcpInstallWithPolicy,
7
- buildCleoProfile,
8
- buildServerConfig,
9
- checkCommandReachability,
10
6
  checkSkillUpdate,
11
- configureProviderGlobalAndProject,
12
7
  detectAllProviders,
13
- detectMcpConfigConflicts,
14
8
  detectProjectProviders,
15
9
  discoverSkill,
16
10
  discoverSkillsMulti,
17
- extractVersionTag,
18
11
  formatNetworkError,
19
12
  formatSkillRecommendations,
20
13
  getInstalledProviders,
21
14
  getSkill,
22
15
  getSkillDir,
23
- getTrackedMcpServers,
24
16
  getTrackedSkills,
25
17
  installBatchWithRollback,
26
- installMcpServerToAll,
27
18
  installSkill,
28
19
  isCatalogAvailable,
29
20
  isHuman,
@@ -31,25 +22,15 @@ import {
31
22
  isQuiet,
32
23
  isVerbose,
33
24
  listCanonicalSkills,
34
- listMcpServers,
35
25
  listProfiles,
36
26
  listSkills,
37
- normalizeCleoChannel,
38
- parseEnvAssignments,
39
27
  parseSource,
40
28
  readConfig,
41
29
  readLockFile,
42
30
  recommendSkills,
43
- reconcileCleoLock,
44
- recordMcpInstall,
45
31
  recordSkillInstall,
46
- removeMcpFromLock,
47
- removeMcpServer,
48
32
  removeSkill,
49
33
  removeSkillFromLock,
50
- resolveChannelFromServerName,
51
- resolveCleoServerName,
52
- resolveConfigPath,
53
34
  resolveProfile,
54
35
  scanDirectory,
55
36
  scanFile,
@@ -61,7 +42,7 @@ import {
61
42
  tokenizeCriteriaValue,
62
43
  updateInstructionsSingleOperation,
63
44
  validateSkill
64
- } from "./chunk-3WKBFXLE.js";
45
+ } from "./chunk-6NBM4CAF.js";
65
46
  import {
66
47
  buildSkillsMap,
67
48
  checkAllInjections,
@@ -74,7 +55,7 @@ import {
74
55
  groupByInstructFile,
75
56
  injectAll,
76
57
  providerSupports
77
- } from "./chunk-5UUABVWS.js";
58
+ } from "./chunk-CRU25LRL.js";
78
59
  import {
79
60
  CANONICAL_HOOK_EVENTS,
80
61
  buildHookMatrix,
@@ -83,13 +64,12 @@ import {
83
64
  getHookSupport,
84
65
  getProviderSummary,
85
66
  translateToAll
86
- } from "./chunk-OH6Z2N3G.js";
67
+ } from "./chunk-FLBRAXDW.js";
87
68
  import {
88
69
  buildSkillSubPathCandidates,
89
- resolvePreferredConfigScope,
90
70
  resolveProviderConfigPath,
91
71
  resolveProviderSkillsDir
92
- } from "./chunk-3IEKCREL.js";
72
+ } from "./chunk-XWQ5WPHC.js";
93
73
 
94
74
  // src/cli.ts
95
75
  import { Command } from "commander";
@@ -265,57 +245,6 @@ async function readJsonFile(path) {
265
245
  );
266
246
  }
267
247
  }
268
- async function readMcpOperations(path) {
269
- const value = await readJsonFile(path);
270
- if (!Array.isArray(value)) {
271
- throw new LAFSCommandError(
272
- "E_ADVANCED_VALIDATION_MCP_ARRAY",
273
- `MCP operations file must be a JSON array: ${path}`,
274
- "Provide an array of objects with serverName and config fields."
275
- );
276
- }
277
- const operations = [];
278
- for (const [index, item] of value.entries()) {
279
- if (!item || typeof item !== "object") {
280
- throw new LAFSCommandError(
281
- "E_ADVANCED_VALIDATION_MCP_ITEM",
282
- `Invalid MCP operation at index ${index}`,
283
- "Each operation must be an object with serverName and config."
284
- );
285
- }
286
- const obj = item;
287
- const serverName = obj.serverName;
288
- const config = obj.config;
289
- const scope = obj.scope;
290
- if (typeof serverName !== "string" || serverName.length === 0) {
291
- throw new LAFSCommandError(
292
- "E_ADVANCED_VALIDATION_MCP_NAME",
293
- `Invalid serverName at index ${index}`,
294
- "Set serverName to a non-empty string."
295
- );
296
- }
297
- if (!config || typeof config !== "object" || Array.isArray(config)) {
298
- throw new LAFSCommandError(
299
- "E_ADVANCED_VALIDATION_MCP_CONFIG",
300
- `Invalid config at index ${index}`,
301
- "Set config to an object matching McpServerConfig."
302
- );
303
- }
304
- if (scope !== void 0 && scope !== "project" && scope !== "global") {
305
- throw new LAFSCommandError(
306
- "E_ADVANCED_VALIDATION_SCOPE",
307
- `Invalid scope at index ${index}: ${String(scope)}`,
308
- "Use scope value 'project' or 'global'."
309
- );
310
- }
311
- operations.push({
312
- serverName,
313
- config,
314
- ...scope ? { scope } : {}
315
- });
316
- }
317
- return operations;
318
- }
319
248
  async function readSkillOperations(path) {
320
249
  const value = await readJsonFile(path);
321
250
  if (!Array.isArray(value)) {
@@ -390,104 +319,24 @@ async function readTextInput(inlineContent, filePath) {
390
319
  }
391
320
  }
392
321
 
393
- // src/commands/advanced/apply.ts
394
- var VALID_POLICIES = /* @__PURE__ */ new Set(["fail", "skip", "overwrite"]);
395
- function parsePolicy(value) {
396
- if (!VALID_POLICIES.has(value)) {
397
- throw new LAFSCommandError(
398
- "E_ADVANCED_VALIDATION_POLICY",
399
- `Invalid policy: ${value}`,
400
- "Use one of: fail, skip, overwrite."
401
- );
402
- }
403
- return value;
404
- }
405
- function registerAdvancedApply(parent) {
406
- parent.command("apply").description("Apply MCP operations with configurable conflict policy").requiredOption("--mcp-file <path>", "JSON file containing McpBatchOperation[]").option("--policy <policy>", "Conflict policy: fail|skip|overwrite", "fail").option(
407
- "-a, --agent <name>",
408
- "Target specific provider(s)",
409
- (v, prev) => [...prev, v],
410
- []
411
- ).option("--all", "Use all registry providers (not only detected)").option("--min-tier <tier>", "Minimum priority tier: high|medium|low", "low").option("--project-dir <path>", "Project directory to resolve project-scope paths").option("--details", "Include detailed apply result").action(
412
- async (opts) => runLafsCommand("advanced.apply", opts.details ? "full" : "standard", async () => {
413
- const baseProviders = resolveProviders({ all: opts.all, agent: opts.agent });
414
- const minimumPriority = parsePriority(opts.minTier);
415
- const providers = selectProvidersByMinimumPriority(baseProviders, minimumPriority);
416
- const operations = await readMcpOperations(opts.mcpFile);
417
- const policy = parsePolicy(opts.policy);
418
- if (providers.length === 0) {
419
- throw new LAFSCommandError(
420
- "E_ADVANCED_NO_TARGET_PROVIDERS",
421
- "No target providers resolved for apply operation.",
422
- "Use --all or pass provider IDs with --agent."
423
- );
424
- }
425
- const result = await applyMcpInstallWithPolicy(
426
- providers,
427
- operations,
428
- policy,
429
- opts.projectDir
430
- );
431
- if (policy === "fail" && result.conflicts.length > 0) {
432
- throw new LAFSCommandError(
433
- "E_ADVANCED_CONFLICTS_BLOCKING",
434
- "Conflicts detected and policy is set to fail.",
435
- "Run `caamp advanced conflicts` to inspect, or rerun with --policy skip/overwrite.",
436
- true,
437
- result
438
- );
439
- }
440
- const failedWrites = result.applied.filter((entry) => !entry.success);
441
- if (failedWrites.length > 0) {
442
- throw new LAFSCommandError(
443
- "E_ADVANCED_APPLY_WRITE_FAILED",
444
- "One or more MCP writes failed.",
445
- "Check result details, fix provider config issues, and retry.",
446
- true,
447
- result
448
- );
449
- }
450
- return {
451
- objective: "Apply MCP operations with policy-driven conflict handling",
452
- constraints: {
453
- policy,
454
- minimumPriority,
455
- providerCount: providers.length,
456
- operationCount: operations.length
457
- },
458
- acceptanceCriteria: {
459
- conflicts: result.conflicts.length,
460
- writesSucceeded: result.applied.length
461
- },
462
- data: opts.details ? result : {
463
- conflicts: result.conflicts.length,
464
- applied: result.applied.length,
465
- skipped: result.skipped.length
466
- }
467
- };
468
- })
469
- );
470
- }
471
-
472
322
  // src/commands/advanced/batch.ts
473
323
  function registerAdvancedBatch(parent) {
474
- parent.command("batch").description("Run rollback-capable batch install for MCP + skills").option(
324
+ parent.command("batch").description("Run rollback-capable batch install for skills").option(
475
325
  "-a, --agent <name>",
476
326
  "Target specific provider(s)",
477
327
  (v, prev) => [...prev, v],
478
328
  []
479
- ).option("--all", "Use all registry providers (not only detected)").option("--min-tier <tier>", "Minimum priority tier: high|medium|low", "low").option("--mcp-file <path>", "JSON file containing McpBatchOperation[]").option("--skills-file <path>", "JSON file containing SkillBatchOperation[]").option("--project-dir <path>", "Project directory to resolve project-scope paths").option("--details", "Include detailed operation result").action(
329
+ ).option("--all", "Use all registry providers (not only detected)").option("--min-tier <tier>", "Minimum priority tier: high|medium|low", "low").requiredOption("--skills-file <path>", "JSON file containing SkillBatchOperation[]").option("--project-dir <path>", "Project directory to resolve project-scope paths").option("--details", "Include detailed operation result").action(
480
330
  async (opts) => runLafsCommand("advanced.batch", opts.details ? "full" : "standard", async () => {
481
331
  const baseProviders = resolveProviders({ all: opts.all, agent: opts.agent });
482
332
  const minimumPriority = parsePriority(opts.minTier);
483
333
  const providers = selectProvidersByMinimumPriority(baseProviders, minimumPriority);
484
- const mcp = opts.mcpFile ? await readMcpOperations(opts.mcpFile) : [];
485
- const skills = opts.skillsFile ? await readSkillOperations(opts.skillsFile) : [];
486
- if (mcp.length === 0 && skills.length === 0) {
334
+ const skills = await readSkillOperations(opts.skillsFile);
335
+ if (skills.length === 0) {
487
336
  throw new LAFSCommandError(
488
337
  "E_ADVANCED_VALIDATION_NO_OPS",
489
338
  "No operations provided.",
490
- "Provide --mcp-file and/or --skills-file."
339
+ "Provide a --skills-file with at least one operation."
491
340
  );
492
341
  }
493
342
  if (providers.length === 0) {
@@ -500,7 +349,6 @@ function registerAdvancedBatch(parent) {
500
349
  const result = await installBatchWithRollback({
501
350
  providers,
502
351
  minimumPriority,
503
- mcp,
504
352
  skills,
505
353
  projectDir: opts.projectDir
506
354
  });
@@ -514,11 +362,10 @@ function registerAdvancedBatch(parent) {
514
362
  );
515
363
  }
516
364
  return {
517
- objective: "Install MCP and skills with rollback safety",
365
+ objective: "Install skills with rollback safety",
518
366
  constraints: {
519
367
  minimumPriority,
520
368
  providerCount: providers.length,
521
- mcpOps: mcp.length,
522
369
  skillOps: skills.length
523
370
  },
524
371
  acceptanceCriteria: {
@@ -527,7 +374,6 @@ function registerAdvancedBatch(parent) {
527
374
  },
528
375
  data: opts.details ? result : {
529
376
  providerCount: result.providerIds.length,
530
- mcpApplied: result.mcpApplied,
531
377
  skillsApplied: result.skillsApplied,
532
378
  rollbackPerformed: result.rollbackPerformed
533
379
  }
@@ -536,140 +382,6 @@ function registerAdvancedBatch(parent) {
536
382
  );
537
383
  }
538
384
 
539
- // src/commands/advanced/configure.ts
540
- function registerAdvancedConfigure(parent) {
541
- parent.command("configure").description("Configure global + project scope for one provider in one operation").requiredOption("-a, --agent <name>", "Target provider ID or alias").option("--global-mcp-file <path>", "JSON file for global MCP operations").option("--project-mcp-file <path>", "JSON file for project MCP operations").option("--instruction <text>", "Instruction content for both scopes").option("--instruction-file <path>", "Instruction content file for both scopes").option("--instruction-global <text>", "Instruction content for global scope").option("--instruction-global-file <path>", "Instruction content file for global scope").option("--instruction-project <text>", "Instruction content for project scope").option("--instruction-project-file <path>", "Instruction content file for project scope").option("--project-dir <path>", "Project directory to resolve project-scope paths").option("--details", "Include detailed write results").action(
542
- async (opts) => runLafsCommand("advanced.configure", opts.details ? "full" : "standard", async () => {
543
- const provider = getProvider(opts.agent);
544
- if (!provider) {
545
- throw new LAFSCommandError(
546
- "E_ADVANCED_PROVIDER_NOT_FOUND",
547
- `Unknown provider: ${opts.agent}`,
548
- "Check `caamp providers list` for valid provider IDs/aliases."
549
- );
550
- }
551
- const globalMcp = opts.globalMcpFile ? await readMcpOperations(opts.globalMcpFile) : [];
552
- const projectMcp = opts.projectMcpFile ? await readMcpOperations(opts.projectMcpFile) : [];
553
- const sharedInstruction = await readTextInput(opts.instruction, opts.instructionFile);
554
- const globalInstruction = await readTextInput(
555
- opts.instructionGlobal,
556
- opts.instructionGlobalFile
557
- );
558
- const projectInstruction = await readTextInput(
559
- opts.instructionProject,
560
- opts.instructionProjectFile
561
- );
562
- let instructionContent;
563
- if (globalInstruction || projectInstruction) {
564
- instructionContent = {
565
- ...globalInstruction ? { global: globalInstruction } : {},
566
- ...projectInstruction ? { project: projectInstruction } : {}
567
- };
568
- } else if (sharedInstruction) {
569
- instructionContent = sharedInstruction;
570
- }
571
- if (globalMcp.length === 0 && projectMcp.length === 0 && !instructionContent) {
572
- throw new LAFSCommandError(
573
- "E_ADVANCED_VALIDATION_NO_OPS",
574
- "No configuration operations were provided.",
575
- "Provide MCP files and/or instruction content."
576
- );
577
- }
578
- const result = await configureProviderGlobalAndProject(provider, {
579
- globalMcp: globalMcp.map((entry) => ({
580
- serverName: entry.serverName,
581
- config: entry.config
582
- })),
583
- projectMcp: projectMcp.map((entry) => ({
584
- serverName: entry.serverName,
585
- config: entry.config
586
- })),
587
- instructionContent,
588
- projectDir: opts.projectDir
589
- });
590
- const globalFailures = result.mcp.global.filter((entry) => !entry.success);
591
- const projectFailures = result.mcp.project.filter((entry) => !entry.success);
592
- if (globalFailures.length > 0 || projectFailures.length > 0) {
593
- throw new LAFSCommandError(
594
- "E_ADVANCED_CONFIGURE_FAILED",
595
- "One or more MCP writes failed during configure operation.",
596
- "Inspect the failed write entries and provider config paths, then retry.",
597
- true,
598
- result
599
- );
600
- }
601
- return {
602
- objective: "Configure global and project settings in one operation",
603
- constraints: {
604
- provider: provider.id,
605
- globalMcpOps: globalMcp.length,
606
- projectMcpOps: projectMcp.length,
607
- instructionMode: instructionContent ? typeof instructionContent === "string" ? "shared" : "scoped" : "none"
608
- },
609
- acceptanceCriteria: {
610
- globalWrites: result.mcp.global.length,
611
- projectWrites: result.mcp.project.length
612
- },
613
- data: opts.details ? result : {
614
- providerId: result.providerId,
615
- configPaths: result.configPaths,
616
- globalWrites: result.mcp.global.length,
617
- projectWrites: result.mcp.project.length,
618
- instructionUpdates: {
619
- global: result.instructions.global?.size ?? 0,
620
- project: result.instructions.project?.size ?? 0
621
- }
622
- }
623
- };
624
- })
625
- );
626
- }
627
-
628
- // src/commands/advanced/conflicts.ts
629
- function registerAdvancedConflicts(parent) {
630
- parent.command("conflicts").description("Preflight MCP conflict detection across providers").requiredOption("--mcp-file <path>", "JSON file containing McpBatchOperation[]").option(
631
- "-a, --agent <name>",
632
- "Target specific provider(s)",
633
- (v, prev) => [...prev, v],
634
- []
635
- ).option("--all", "Use all registry providers (not only detected)").option("--min-tier <tier>", "Minimum priority tier: high|medium|low", "low").option("--project-dir <path>", "Project directory to resolve project-scope paths").option("--details", "Include full conflict list").action(
636
- async (opts) => runLafsCommand("advanced.conflicts", opts.details ? "full" : "standard", async () => {
637
- const baseProviders = resolveProviders({ all: opts.all, agent: opts.agent });
638
- const minimumPriority = parsePriority(opts.minTier);
639
- const providers = selectProvidersByMinimumPriority(baseProviders, minimumPriority);
640
- const operations = await readMcpOperations(opts.mcpFile);
641
- if (providers.length === 0) {
642
- throw new LAFSCommandError(
643
- "E_ADVANCED_NO_TARGET_PROVIDERS",
644
- "No target providers resolved for conflict detection.",
645
- "Use --all or pass provider IDs with --agent."
646
- );
647
- }
648
- const conflicts = await detectMcpConfigConflicts(providers, operations, opts.projectDir);
649
- const countByCode = conflicts.reduce((acc, conflict) => {
650
- acc[conflict.code] = (acc[conflict.code] ?? 0) + 1;
651
- return acc;
652
- }, {});
653
- return {
654
- objective: "Detect MCP configuration conflicts before mutation",
655
- constraints: {
656
- minimumPriority,
657
- providerCount: providers.length,
658
- operationCount: operations.length
659
- },
660
- acceptanceCriteria: {
661
- conflictCount: conflicts.length
662
- },
663
- data: opts.details ? conflicts : {
664
- conflictCount: conflicts.length,
665
- countByCode,
666
- sample: conflicts.slice(0, 5)
667
- }
668
- };
669
- })
670
- );
671
- }
672
-
673
385
  // src/commands/advanced/instructions.ts
674
386
  function registerAdvancedInstructions(parent) {
675
387
  parent.command("instructions").description("Single-operation instruction update across providers").option(
@@ -771,10 +483,7 @@ function registerAdvancedCommands(program2) {
771
483
  const advanced = program2.command("advanced").description("LAFS-compliant wrappers for advanced orchestration APIs");
772
484
  registerAdvancedProviders(advanced);
773
485
  registerAdvancedBatch(advanced);
774
- registerAdvancedConflicts(advanced);
775
- registerAdvancedApply(advanced);
776
486
  registerAdvancedInstructions(advanced);
777
- registerAdvancedConfigure(advanced);
778
487
  }
779
488
 
780
489
  // src/commands/config.ts
@@ -1256,69 +965,6 @@ async function checkLockFile() {
1256
965
  }
1257
966
  return { name: "Lock File", checks };
1258
967
  }
1259
- async function checkMcpLockEntries() {
1260
- const checks = [];
1261
- try {
1262
- const lock = await readLockFile();
1263
- const lockNames = Object.keys(lock.mcpServers);
1264
- checks.push({ label: `${lockNames.length} MCP server entries in lock`, status: "pass" });
1265
- const results = detectAllProviders();
1266
- const installed = results.filter((r) => r.installed);
1267
- const liveCleoNames = /* @__PURE__ */ new Set();
1268
- let untrackedCount = 0;
1269
- for (const scope of ["project", "global"]) {
1270
- for (const r of installed) {
1271
- try {
1272
- const entries = await listMcpServers(r.provider, scope);
1273
- for (const entry of entries) {
1274
- const channel = resolveChannelFromServerName(entry.name);
1275
- if (!channel) continue;
1276
- liveCleoNames.add(entry.name);
1277
- if (!lock.mcpServers[entry.name]) {
1278
- untrackedCount++;
1279
- }
1280
- }
1281
- } catch {
1282
- }
1283
- }
1284
- }
1285
- if (untrackedCount === 0) {
1286
- checks.push({ label: "All CLEO servers tracked in lock", status: "pass" });
1287
- } else {
1288
- checks.push({
1289
- label: `${untrackedCount} untracked CLEO server${untrackedCount !== 1 ? "s" : ""} (in config, not in lock)`,
1290
- status: "warn",
1291
- detail: "Run `caamp cleo repair` to backfill lock entries"
1292
- });
1293
- }
1294
- let orphanedCount = 0;
1295
- const orphanedNames = [];
1296
- for (const serverName of lockNames) {
1297
- const channel = resolveChannelFromServerName(serverName);
1298
- if (!channel) continue;
1299
- if (!liveCleoNames.has(serverName)) {
1300
- orphanedCount++;
1301
- orphanedNames.push(serverName);
1302
- }
1303
- }
1304
- if (orphanedCount === 0) {
1305
- checks.push({ label: "No orphaned CLEO lock entries", status: "pass" });
1306
- } else {
1307
- checks.push({
1308
- label: `${orphanedCount} orphaned CLEO lock entr${orphanedCount !== 1 ? "ies" : "y"} (in lock, not in any config)`,
1309
- status: "warn",
1310
- detail: orphanedNames.join(", ") + " \u2014 Run `caamp cleo repair --prune` to clean up"
1311
- });
1312
- }
1313
- } catch (err) {
1314
- checks.push({
1315
- label: "Failed to check MCP lock entries",
1316
- status: "fail",
1317
- detail: err instanceof Error ? err.message : String(err)
1318
- });
1319
- }
1320
- return { name: "MCP Lock", checks };
1321
- }
1322
968
  async function checkConfigFiles() {
1323
969
  const checks = [];
1324
970
  const results = detectAllProviders();
@@ -1387,7 +1033,6 @@ function registerDoctorCommand(program2) {
1387
1033
  sections.push(checkInstalledProviders());
1388
1034
  sections.push(checkSkillSymlinks());
1389
1035
  sections.push(await checkLockFile());
1390
- sections.push(await checkMcpLockEntries());
1391
1036
  sections.push(await checkConfigFiles());
1392
1037
  let passed = 0;
1393
1038
  let warnings = 0;
@@ -1407,11 +1052,6 @@ function registerDoctorCommand(program2) {
1407
1052
  const detectionResults = detectAllProviders();
1408
1053
  const installedProviders = detectionResults.filter((r) => r.installed);
1409
1054
  const { canonicalCount, brokenCount, staleCount } = countSkillIssues();
1410
- const {
1411
- tracked: mcpTracked,
1412
- untracked: mcpUntracked,
1413
- orphaned: mcpOrphaned
1414
- } = countMcpLockIssues(sections);
1415
1055
  const result = {
1416
1056
  environment: {
1417
1057
  node: getNodeVersion(),
@@ -1433,11 +1073,6 @@ function registerDoctorCommand(program2) {
1433
1073
  brokenLinks: brokenCount,
1434
1074
  staleLinks: staleCount
1435
1075
  },
1436
- mcpServers: {
1437
- tracked: mcpTracked,
1438
- untracked: mcpUntracked,
1439
- orphaned: mcpOrphaned
1440
- },
1441
1076
  checks: sections.flatMap(
1442
1077
  (s) => s.checks.map((c) => ({
1443
1078
  label: `${s.name}: ${c.label}`,
@@ -1526,1278 +1161,32 @@ function countSkillIssues() {
1526
1161
  staleCount++;
1527
1162
  }
1528
1163
  }
1529
- } catch {
1530
- }
1531
- }
1532
- } catch {
1533
- }
1534
- }
1535
- return { canonicalCount, brokenCount, staleCount };
1536
- }
1537
- function countMcpLockIssues(sections) {
1538
- const mcpSection = sections.find((s) => s.name === "MCP Lock");
1539
- if (!mcpSection) return { tracked: 0, untracked: 0, orphaned: 0 };
1540
- let tracked = 0;
1541
- let untracked = 0;
1542
- let orphaned = 0;
1543
- for (const check of mcpSection.checks) {
1544
- const countMatch = check.label.match(/^(\d+)/);
1545
- if (!countMatch?.[1]) continue;
1546
- const count = Number.parseInt(countMatch[1], 10);
1547
- if (check.label.includes("MCP server entries in lock")) {
1548
- tracked = count;
1549
- } else if (check.label.includes("untracked")) {
1550
- untracked = count;
1551
- } else if (check.label.includes("orphaned")) {
1552
- orphaned = count;
1553
- }
1554
- }
1555
- return { tracked, untracked, orphaned };
1556
- }
1557
-
1558
- // src/commands/instructions/check.ts
1559
- import pc3 from "picocolors";
1560
- function registerInstructionsCheck(parent) {
1561
- parent.command("check").description("Check injection status across providers").option(
1562
- "-a, --agent <name>",
1563
- "Check specific agent(s)",
1564
- (v, prev) => [...prev, v],
1565
- []
1566
- ).option("-g, --global", "Check global instruction files").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").option("--all", "Check all known providers").action(
1567
- async (opts) => {
1568
- const operation = "instructions.check";
1569
- const mvi = "standard";
1570
- let format;
1571
- try {
1572
- format = resolveFormat({
1573
- jsonFlag: opts.json ?? false,
1574
- humanFlag: opts.human ?? false,
1575
- projectDefault: "json"
1576
- });
1577
- } catch (error) {
1578
- const message = error instanceof Error ? error.message : String(error);
1579
- emitJsonError(
1580
- operation,
1581
- mvi,
1582
- ErrorCodes.FORMAT_CONFLICT,
1583
- message,
1584
- ErrorCategories.VALIDATION
1585
- );
1586
- process.exit(1);
1587
- }
1588
- let providers;
1589
- if (opts.all) {
1590
- providers = getAllProviders();
1591
- } else if (opts.agent.length > 0) {
1592
- providers = opts.agent.map((a) => getProvider(a)).filter((p) => p !== void 0);
1593
- } else {
1594
- providers = getInstalledProviders();
1595
- }
1596
- const scope = opts.global ? "global" : "project";
1597
- const results = await checkAllInjections(providers, process.cwd(), scope);
1598
- const providerStatus = results.map((r) => ({
1599
- id: r.provider,
1600
- present: r.status === "current" || r.status === "outdated",
1601
- path: r.file
1602
- }));
1603
- const present = providerStatus.filter((p) => p.present).length;
1604
- const missing = providerStatus.filter((p) => !p.present).length;
1605
- if (format === "json") {
1606
- outputSuccess(operation, mvi, {
1607
- providers: providerStatus,
1608
- present,
1609
- missing
1610
- });
1611
- return;
1612
- }
1613
- console.log(pc3.bold(`
1614
- Instruction file status (${scope}):
1615
- `));
1616
- for (const r of results) {
1617
- let icon;
1618
- let label;
1619
- switch (r.status) {
1620
- case "current":
1621
- icon = pc3.green("\u2713");
1622
- label = "current";
1623
- break;
1624
- case "outdated":
1625
- icon = pc3.yellow("~");
1626
- label = "outdated";
1627
- break;
1628
- case "missing":
1629
- icon = pc3.red("\u2717");
1630
- label = "missing";
1631
- break;
1632
- case "none":
1633
- icon = pc3.dim("-");
1634
- label = "no injection";
1635
- break;
1636
- }
1637
- console.log(` ${icon} ${r.file.padEnd(40)} ${label}`);
1638
- }
1639
- console.log();
1640
- }
1641
- );
1642
- }
1643
-
1644
- // src/commands/instructions/inject.ts
1645
- import pc4 from "picocolors";
1646
- function registerInstructionsInject(parent) {
1647
- parent.command("inject").description("Inject instruction blocks into all provider files").option(
1648
- "-a, --agent <name>",
1649
- "Target specific agent(s)",
1650
- (v, prev) => [...prev, v],
1651
- []
1652
- ).option("-g, --global", "Inject into global instruction files").option("--content <text>", "Custom content to inject").option("--dry-run", "Preview without writing").option("--all", "Target all known providers").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(
1653
- async (opts) => {
1654
- const operation = "instructions.inject";
1655
- const mvi = "standard";
1656
- let format;
1657
- try {
1658
- format = resolveFormat({
1659
- jsonFlag: opts.json ?? false,
1660
- humanFlag: opts.human ?? false,
1661
- projectDefault: "json"
1662
- });
1663
- } catch (error) {
1664
- const message = error instanceof Error ? error.message : String(error);
1665
- emitJsonError(
1666
- operation,
1667
- mvi,
1668
- ErrorCodes.FORMAT_CONFLICT,
1669
- message,
1670
- ErrorCategories.VALIDATION
1671
- );
1672
- process.exit(1);
1673
- }
1674
- let providers;
1675
- if (opts.all) {
1676
- providers = getAllProviders();
1677
- } else if (opts.agent.length > 0) {
1678
- providers = opts.agent.map((a) => getProvider(a)).filter((p) => p !== void 0);
1679
- } else {
1680
- providers = getInstalledProviders();
1681
- }
1682
- if (providers.length === 0) {
1683
- const message = "No providers found.";
1684
- if (format === "json") {
1685
- emitJsonError(
1686
- operation,
1687
- mvi,
1688
- ErrorCodes.PROVIDER_NOT_FOUND,
1689
- message,
1690
- ErrorCategories.NOT_FOUND
1691
- );
1692
- } else {
1693
- console.error(pc4.red(message));
1694
- }
1695
- process.exit(1);
1696
- }
1697
- const content = opts.content ?? generateInjectionContent();
1698
- const scope = opts.global ? "global" : "project";
1699
- const groups = groupByInstructFile(providers);
1700
- if (opts.dryRun) {
1701
- if (format === "json") {
1702
- outputSuccess(operation, mvi, {
1703
- injected: [],
1704
- providers: providers.map((p) => p.id),
1705
- count: 0,
1706
- dryRun: true,
1707
- wouldInject: Array.from(groups.entries()).map(([file, group]) => ({
1708
- file,
1709
- providers: group.map((p) => p.id)
1710
- }))
1711
- });
1712
- } else {
1713
- console.log(pc4.bold("Dry run - would inject into:\n"));
1714
- for (const [file, group] of groups) {
1715
- console.log(` ${pc4.bold(file)}: ${group.map((p) => p.id).join(", ")}`);
1716
- }
1717
- console.log(pc4.dim(`
1718
- Scope: ${scope}`));
1719
- console.log(pc4.dim(` Content length: ${content.length} chars`));
1720
- }
1721
- return;
1722
- }
1723
- const results = await injectAll(providers, process.cwd(), scope, content);
1724
- const injected = [];
1725
- for (const [file] of results) {
1726
- injected.push(file);
1727
- }
1728
- if (format === "json") {
1729
- outputSuccess(operation, mvi, {
1730
- injected,
1731
- providers: providers.map((p) => p.id),
1732
- count: results.size
1733
- });
1734
- } else {
1735
- for (const [file, action] of results) {
1736
- const icon = action === "created" ? pc4.green("+") : action === "updated" ? pc4.yellow("~") : pc4.blue("^");
1737
- console.log(` ${icon} ${file} (${action})`);
1738
- }
1739
- console.log(pc4.bold(`
1740
- ${results.size} file(s) processed.`));
1741
- }
1742
- }
1743
- );
1744
- }
1745
-
1746
- // src/commands/instructions/update.ts
1747
- import pc5 from "picocolors";
1748
- function registerInstructionsUpdate(parent) {
1749
- parent.command("update").description("Update all instruction file injections").option("-g, --global", "Update global instruction files").option("-y, --yes", "Skip confirmation").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(async (opts) => {
1750
- const operation = "instructions.update";
1751
- const mvi = "standard";
1752
- let format;
1753
- try {
1754
- format = resolveFormat({
1755
- jsonFlag: opts.json ?? false,
1756
- humanFlag: opts.human ?? false,
1757
- projectDefault: "json"
1758
- });
1759
- } catch (error) {
1760
- const message = error instanceof Error ? error.message : String(error);
1761
- emitJsonError(
1762
- operation,
1763
- mvi,
1764
- ErrorCodes.FORMAT_CONFLICT,
1765
- message,
1766
- ErrorCategories.VALIDATION
1767
- );
1768
- process.exit(1);
1769
- }
1770
- const providers = getInstalledProviders();
1771
- const scope = opts.global ? "global" : "project";
1772
- const content = generateInjectionContent();
1773
- const checks = await checkAllInjections(providers, process.cwd(), scope, content);
1774
- const needsUpdate = checks.filter((c) => c.status !== "current");
1775
- if (needsUpdate.length === 0) {
1776
- if (format === "json") {
1777
- outputSuccess(operation, mvi, {
1778
- updated: [],
1779
- failed: [],
1780
- count: { updated: 0, failed: 0 }
1781
- });
1782
- } else {
1783
- console.log(pc5.green("All instruction files are up to date."));
1784
- }
1785
- return;
1786
- }
1787
- if (format === "human") {
1788
- console.log(pc5.bold(`${needsUpdate.length} file(s) need updating:
1789
- `));
1790
- for (const c of needsUpdate) {
1791
- console.log(` ${c.file} (${c.status})`);
1792
- }
1793
- }
1794
- const providerIds = new Set(needsUpdate.map((c) => c.provider));
1795
- const toUpdate = providers.filter((p) => providerIds.has(p.id));
1796
- const results = await injectAll(toUpdate, process.cwd(), scope, content);
1797
- const updated = [];
1798
- for (const [file] of results) {
1799
- updated.push(file);
1800
- }
1801
- if (format === "human") {
1802
- console.log();
1803
- for (const [file, action] of results) {
1804
- console.log(` ${pc5.green("\u2713")} ${file} (${action})`);
1805
- }
1806
- console.log(pc5.bold(`
1807
- ${results.size} file(s) updated.`));
1808
- }
1809
- if (format === "json") {
1810
- outputSuccess(operation, mvi, {
1811
- updated,
1812
- failed: [],
1813
- count: { updated: updated.length, failed: 0 }
1814
- });
1815
- }
1816
- });
1817
- }
1818
-
1819
- // src/commands/instructions/index.ts
1820
- function registerInstructionsCommands(program2) {
1821
- const instructions = program2.command("instructions").description("Manage instruction file injections");
1822
- registerInstructionsInject(instructions);
1823
- registerInstructionsCheck(instructions);
1824
- registerInstructionsUpdate(instructions);
1825
- }
1826
-
1827
- // src/commands/mcp/cleo.ts
1828
- import { createInterface } from "readline/promises";
1829
- import pc6 from "picocolors";
1830
- function collect(value, previous) {
1831
- return [...previous, value];
1832
- }
1833
- function collectTargetProviders(providerIds, all) {
1834
- if (all) {
1835
- return getInstalledProviders();
1836
- }
1837
- if (providerIds.length > 0) {
1838
- return providerIds.map((id) => getProvider(id)).filter((provider) => provider !== void 0);
1839
- }
1840
- return getInstalledProviders();
1841
- }
1842
- async function validateProfile(provider, scope, serverName) {
1843
- const entries = await listMcpServers(provider, scope);
1844
- const entry = entries.find((candidate) => candidate.name === serverName);
1845
- if (!entry) {
1846
- return { valid: false, reason: "server missing after write" };
1847
- }
1848
- const command = typeof entry.config.command === "string" ? entry.config.command : void 0;
1849
- if (!command) {
1850
- return { valid: true };
1851
- }
1852
- const reachability = checkCommandReachability(command);
1853
- if (!reachability.reachable) {
1854
- return {
1855
- valid: false,
1856
- reason: `command not reachable (${reachability.method}: ${reachability.detail})`
1857
- };
1858
- }
1859
- return { valid: true };
1860
- }
1861
- async function detectServerConflicts(providers, scope, targetServerName) {
1862
- const warnings = [];
1863
- for (const provider of providers) {
1864
- const entries = await listMcpServers(provider, scope);
1865
- const existing = entries.find((entry) => entry.name === targetServerName);
1866
- if (!existing) continue;
1867
- const command = typeof existing.config.command === "string" ? existing.config.command : "";
1868
- const args = Array.isArray(existing.config.args) ? existing.config.args.filter((value) => typeof value === "string") : [];
1869
- const flat = `${command} ${args.join(" ")}`.toLowerCase();
1870
- if (!flat.includes("cleo")) {
1871
- warnings.push({
1872
- providerId: provider.id,
1873
- message: `Server name '${targetServerName}' already exists with a non-CLEO command in ${provider.id}.`
1874
- });
1875
- }
1876
- }
1877
- return warnings;
1878
- }
1879
- function formatInstallResultHuman(mode, channel, serverName, scope, results, validations) {
1880
- console.log(pc6.bold(`${mode === "install" ? "Install" : "Update"} CLEO channel: ${channel}`));
1881
- console.log(pc6.dim(`Server: ${serverName} Scope: ${scope}`));
1882
- console.log();
1883
- for (const result of results) {
1884
- const validation = validations.find((entry) => entry.providerId === result.provider.id);
1885
- if (result.success) {
1886
- const validationLabel = validation?.valid ? pc6.green("validated") : pc6.yellow(`validation warning: ${validation?.reason ?? "unknown"}`);
1887
- console.log(
1888
- ` ${pc6.green("+")} ${result.provider.toolName.padEnd(22)} ${pc6.dim(result.configPath)} ${validationLabel}`
1889
- );
1890
- } else {
1891
- console.log(
1892
- ` ${pc6.red("x")} ${result.provider.toolName.padEnd(22)} ${pc6.red(result.error ?? "failed")}`
1893
- );
1894
- console.log(pc6.dim(" Recovery: verify config path permissions and retry with --dry-run."));
1895
- }
1896
- }
1897
- console.log();
1898
- }
1899
- async function runInteractiveInstall(opts) {
1900
- const rl = createInterface({ input: process.stdin, output: process.stdout });
1901
- try {
1902
- const discovered = getInstalledProviders();
1903
- if (discovered.length === 0) {
1904
- throw new Error("No installed providers were detected for interactive setup.");
1905
- }
1906
- console.log(pc6.bold("CLEO MCP Setup"));
1907
- console.log(pc6.dim("Step 1/6 - Select provider(s)"));
1908
- for (const [index, provider] of discovered.entries()) {
1909
- console.log(` ${index + 1}. ${provider.id} (${provider.toolName})`);
1910
- }
1911
- const providerAnswer = await rl.question(pc6.dim("Choose providers (e.g. 1,2 or all): "));
1912
- const selectedProviders = providerAnswer.trim().toLowerCase() === "all" ? discovered.map((provider) => provider.id) : providerAnswer.split(",").map((part) => Number(part.trim())).filter((value) => Number.isFinite(value) && value > 0 && value <= discovered.length).map((index) => discovered[index - 1]?.id).filter((id) => Boolean(id));
1913
- if (selectedProviders.length === 0) {
1914
- throw new Error("No providers selected.");
1915
- }
1916
- console.log();
1917
- console.log(pc6.dim("Step 2/6 - Select channel"));
1918
- const channelAnswer = await rl.question(pc6.dim("Channel [stable/beta/dev] (stable): "));
1919
- const selectedChannel = normalizeCleoChannel(channelAnswer || "stable");
1920
- let command = opts.command;
1921
- let args = [...opts.arg];
1922
- let env = [...opts.env];
1923
- let cleoDir = opts.cleoDir;
1924
- if (selectedChannel === "dev") {
1925
- command = await rl.question(pc6.dim("Dev command (required): "));
1926
- const argsAnswer = await rl.question(pc6.dim("Dev args (space-separated, optional): "));
1927
- args = argsAnswer.trim() === "" ? [] : argsAnswer.trim().split(/\s+/);
1928
- const dirAnswer = await rl.question(pc6.dim("CLEO_DIR (~/.cleo-dev default): "));
1929
- cleoDir = dirAnswer.trim() === "" ? "~/.cleo-dev" : dirAnswer.trim();
1930
- if (cleoDir.trim() !== "") {
1931
- env = [...env.filter((entry) => !entry.startsWith("CLEO_DIR=")), `CLEO_DIR=${cleoDir}`];
1932
- }
1933
- }
1934
- const profile = buildCleoProfile({
1935
- channel: selectedChannel,
1936
- version: opts.version,
1937
- command,
1938
- args,
1939
- env: parseEnvAssignments(env),
1940
- cleoDir
1941
- });
1942
- console.log();
1943
- console.log(pc6.dim("Step 3/6 - Preview profile diff"));
1944
- console.log(` Server: ${pc6.bold(profile.serverName)}`);
1945
- console.log(` Channel: ${selectedChannel}`);
1946
- console.log(` Config: ${JSON.stringify(profile.config)}`);
1947
- console.log();
1948
- console.log(pc6.dim("Step 4/6 - Confirm apply"));
1949
- const confirm = await rl.question(pc6.dim("Apply this configuration? [y/N] "));
1950
- if (!["y", "yes"].includes(confirm.trim().toLowerCase())) {
1951
- throw new Error("Cancelled by user.");
1952
- }
1953
- return {
1954
- ...opts,
1955
- provider: selectedProviders,
1956
- channel: selectedChannel,
1957
- command,
1958
- arg: args,
1959
- env,
1960
- cleoDir,
1961
- yes: true
1962
- };
1963
- } finally {
1964
- rl.close();
1965
- }
1966
- }
1967
- async function executeCleoInstall(mode, opts, operation) {
1968
- const mvi = "standard";
1969
- let format;
1970
- try {
1971
- format = resolveFormat({
1972
- jsonFlag: opts.json ?? false,
1973
- humanFlag: (opts.human ?? false) || isHuman(),
1974
- projectDefault: "json"
1975
- });
1976
- } catch (error) {
1977
- const message = error instanceof Error ? error.message : String(error);
1978
- emitJsonError(operation, mvi, ErrorCodes.FORMAT_CONFLICT, message, ErrorCategories.VALIDATION);
1979
- process.exit(1);
1980
- }
1981
- const interactive = (opts.interactive ?? false) && format === "human";
1982
- const resolvedOpts = interactive ? await runInteractiveInstall(opts) : opts;
1983
- const channel = normalizeCleoChannel(resolvedOpts.channel);
1984
- const providers = collectTargetProviders(resolvedOpts.provider, resolvedOpts.all);
1985
- if (providers.length === 0) {
1986
- const message = "No target providers found.";
1987
- if (format === "json") {
1988
- emitJsonError(
1989
- operation,
1990
- mvi,
1991
- ErrorCodes.PROVIDER_NOT_FOUND,
1992
- message,
1993
- ErrorCategories.NOT_FOUND
1994
- );
1995
- } else {
1996
- console.error(pc6.red(message));
1997
- }
1998
- process.exit(1);
1999
- }
2000
- const envMap = parseEnvAssignments(resolvedOpts.env);
2001
- const profile = buildCleoProfile({
2002
- channel,
2003
- version: resolvedOpts.version,
2004
- command: resolvedOpts.command,
2005
- args: resolvedOpts.arg,
2006
- env: envMap,
2007
- cleoDir: resolvedOpts.cleoDir
2008
- });
2009
- const scope = resolvedOpts.global ? "global" : "project";
2010
- if (resolvedOpts.dryRun) {
2011
- if (format === "human") {
2012
- console.log(pc6.bold(`Dry run: ${mode} CLEO (${channel})`));
2013
- console.log(pc6.dim(`Server: ${profile.serverName} Scope: ${scope}`));
2014
- console.log(pc6.dim(`Providers: ${providers.map((provider) => provider.id).join(", ")}`));
2015
- console.log(
2016
- pc6.dim(
2017
- `Command: ${profile.config.command ?? "(none)"} ${(profile.config.args ?? []).join(" ")}`
2018
- )
2019
- );
2020
- if (profile.config.env && Object.keys(profile.config.env).length > 0) {
2021
- console.log(pc6.dim(`Env: ${JSON.stringify(profile.config.env)}`));
2022
- }
2023
- } else {
2024
- outputSuccess(operation, mvi, {
2025
- action: mode,
2026
- channel,
2027
- serverName: profile.serverName,
2028
- providers: providers.map((provider) => provider.id),
2029
- scope,
2030
- command: profile.config.command,
2031
- args: profile.config.args ?? [],
2032
- env: profile.config.env ?? {},
2033
- packageSpec: profile.packageSpec,
2034
- dryRun: true
2035
- });
2036
- }
2037
- return;
2038
- }
2039
- const conflictWarnings = await detectServerConflicts(providers, scope, profile.serverName);
2040
- if (format === "human" && conflictWarnings.length > 0) {
2041
- console.log(pc6.yellow("Warning: potential server name conflicts detected."));
2042
- for (const warning of conflictWarnings) {
2043
- console.log(pc6.yellow(` - ${warning.message}`));
2044
- }
2045
- console.log(
2046
- pc6.dim(
2047
- "Recovery: run with --dry-run, inspect provider config, then retry with explicit channel/profile."
2048
- )
2049
- );
2050
- console.log();
2051
- }
2052
- const results = await installMcpServerToAll(providers, profile.serverName, profile.config, scope);
2053
- const succeeded = results.filter((result) => result.success);
2054
- const validations = [];
2055
- for (const result of succeeded) {
2056
- const validation = await validateProfile(result.provider, scope, profile.serverName);
2057
- validations.push({
2058
- providerId: result.provider.id,
2059
- valid: validation.valid,
2060
- reason: validation.reason
2061
- });
2062
- }
2063
- if (succeeded.length > 0) {
2064
- await recordMcpInstall(
2065
- profile.serverName,
2066
- profile.packageSpec ?? resolvedOpts.command ?? "cleo-dev",
2067
- channel === "dev" ? "command" : "package",
2068
- succeeded.map((result) => result.provider.id),
2069
- resolvedOpts.global ?? false,
2070
- resolvedOpts.version ?? extractVersionTag(profile.packageSpec)
2071
- );
2072
- }
2073
- if (format === "human") {
2074
- formatInstallResultHuman(mode, channel, profile.serverName, scope, results, validations);
2075
- }
2076
- const validationFailures = validations.filter((entry) => !entry.valid);
2077
- if (interactive && validationFailures.length > 0 && format === "human") {
2078
- console.log(pc6.dim("Step 5/6 - Validation"));
2079
- console.log(pc6.yellow(`Validation found ${validationFailures.length} issue(s).`));
2080
- const rl = createInterface({ input: process.stdin, output: process.stdout });
2081
- try {
2082
- console.log(pc6.dim("Step 6/6 - Rollback"));
2083
- const answer = await rl.question(pc6.dim("Rollback failed validations? [y/N] "));
2084
- if (["y", "yes"].includes(answer.trim().toLowerCase())) {
2085
- for (const failure of validationFailures) {
2086
- const provider = providers.find((candidate) => candidate.id === failure.providerId);
2087
- if (!provider) continue;
2088
- await removeMcpServer(provider, profile.serverName, scope);
2089
- }
2090
- console.log(pc6.yellow("Rollback completed for failed provider validations."));
2091
- }
2092
- } finally {
2093
- rl.close();
2094
- }
2095
- }
2096
- if (format === "json") {
2097
- outputSuccess(operation, mvi, {
2098
- action: mode,
2099
- channel,
2100
- serverName: profile.serverName,
2101
- scope,
2102
- command: profile.config.command,
2103
- args: profile.config.args ?? [],
2104
- env: profile.config.env ?? {},
2105
- packageSpec: profile.packageSpec,
2106
- providers: results.map((result) => ({
2107
- id: result.provider.id,
2108
- success: result.success,
2109
- configPath: result.configPath,
2110
- error: result.error,
2111
- validation: validations.find((entry) => entry.providerId === result.provider.id) ?? null
2112
- })),
2113
- conflicts: conflictWarnings,
2114
- validationStatus: validationFailures.length === 0 ? "ok" : "warning"
2115
- });
2116
- }
2117
- }
2118
- async function executeCleoUninstall(opts, operation) {
2119
- const mvi = "standard";
2120
- let format;
2121
- try {
2122
- format = resolveFormat({
2123
- jsonFlag: opts.json ?? false,
2124
- humanFlag: (opts.human ?? false) || isHuman(),
2125
- projectDefault: "json"
2126
- });
2127
- } catch (error) {
2128
- const message = error instanceof Error ? error.message : String(error);
2129
- emitJsonError(operation, mvi, ErrorCodes.FORMAT_CONFLICT, message, ErrorCategories.VALIDATION);
2130
- process.exit(1);
2131
- }
2132
- const channel = normalizeCleoChannel(opts.channel);
2133
- const serverName = resolveCleoServerName(channel);
2134
- const providers = collectTargetProviders(opts.provider, opts.all);
2135
- if (providers.length === 0) {
2136
- const message = "No target providers found.";
2137
- if (format === "json") {
2138
- emitJsonError(
2139
- operation,
2140
- mvi,
2141
- ErrorCodes.PROVIDER_NOT_FOUND,
2142
- message,
2143
- ErrorCategories.NOT_FOUND
2144
- );
2145
- } else {
2146
- console.error(pc6.red(message));
2147
- }
2148
- process.exit(1);
2149
- }
2150
- const scope = opts.global ? "global" : "project";
2151
- if (opts.dryRun) {
2152
- if (format === "human") {
2153
- console.log(pc6.bold("Dry run: uninstall CLEO profile"));
2154
- console.log(pc6.dim(`Server: ${serverName} Channel: ${channel} Scope: ${scope}`));
2155
- console.log(pc6.dim(`Providers: ${providers.map((provider) => provider.id).join(", ")}`));
2156
- } else {
2157
- outputSuccess(operation, mvi, {
2158
- action: "uninstall",
2159
- channel,
2160
- serverName,
2161
- providers: providers.map((provider) => provider.id),
2162
- scope,
2163
- dryRun: true
2164
- });
2165
- }
2166
- return;
2167
- }
2168
- const removed = [];
2169
- for (const provider of providers) {
2170
- const success = await removeMcpServer(provider, serverName, scope);
2171
- if (success) removed.push(provider.id);
2172
- }
2173
- if (removed.length > 0) {
2174
- await removeMcpFromLock(serverName);
2175
- }
2176
- if (format === "human") {
2177
- const prefix = removed.length > 0 ? pc6.green("Removed") : pc6.yellow("No matching profile found for");
2178
- console.log(
2179
- `${prefix} ${pc6.bold(serverName)} (${channel}) on ${removed.length}/${providers.length} providers.`
2180
- );
2181
- }
2182
- if (format === "json") {
2183
- outputSuccess(operation, mvi, {
2184
- action: "uninstall",
2185
- channel,
2186
- serverName,
2187
- scope,
2188
- removed,
2189
- providerCount: providers.length,
2190
- dryRun: false
2191
- });
2192
- }
2193
- }
2194
- function checkCleoEntryHealth(command, lockTracked) {
2195
- if (!command) {
2196
- return {
2197
- commandReachable: true,
2198
- commandDetail: "(no command)",
2199
- configPresent: true,
2200
- lockTracked,
2201
- status: lockTracked ? "healthy" : "degraded"
2202
- };
2203
- }
2204
- const reachability = checkCommandReachability(command);
2205
- if (!reachability.reachable) {
2206
- return {
2207
- commandReachable: false,
2208
- commandDetail: reachability.detail,
2209
- configPresent: true,
2210
- lockTracked,
2211
- status: "broken"
2212
- };
2213
- }
2214
- return {
2215
- commandReachable: true,
2216
- commandDetail: reachability.detail,
2217
- configPresent: true,
2218
- lockTracked,
2219
- status: lockTracked ? "healthy" : "degraded"
2220
- };
2221
- }
2222
- async function executeCleoShow(opts, operation) {
2223
- const mvi = "standard";
2224
- let format;
2225
- try {
2226
- format = resolveFormat({
2227
- jsonFlag: opts.json ?? false,
2228
- humanFlag: (opts.human ?? false) || isHuman(),
2229
- projectDefault: "json"
2230
- });
2231
- } catch (error) {
2232
- const message = error instanceof Error ? error.message : String(error);
2233
- emitJsonError(operation, mvi, ErrorCodes.FORMAT_CONFLICT, message, ErrorCategories.VALIDATION);
2234
- process.exit(1);
2235
- }
2236
- const providers = collectTargetProviders(opts.provider, opts.all);
2237
- if (providers.length === 0) {
2238
- const message = "No target providers found.";
2239
- if (format === "json") {
2240
- emitJsonError(
2241
- operation,
2242
- mvi,
2243
- ErrorCodes.PROVIDER_NOT_FOUND,
2244
- message,
2245
- ErrorCategories.NOT_FOUND
2246
- );
2247
- } else {
2248
- console.error(pc6.red(message));
2249
- }
2250
- process.exit(1);
2251
- }
2252
- const channelFilter = opts.channel ? normalizeCleoChannel(opts.channel) : null;
2253
- const scopes = [];
2254
- if (opts.global && !opts.project) {
2255
- scopes.push("global");
2256
- } else if (opts.project && !opts.global) {
2257
- scopes.push("project");
2258
- } else {
2259
- scopes.push("project", "global");
2260
- }
2261
- const lockEntries = await getTrackedMcpServers();
2262
- const entries = [];
2263
- const warnings = [];
2264
- for (const scope of scopes) {
2265
- for (const provider of providers) {
2266
- const providerEntries = await listMcpServers(provider, scope);
2267
- for (const entry of providerEntries) {
2268
- const channel = resolveChannelFromServerName(entry.name);
2269
- if (!channel) continue;
2270
- if (channelFilter && channel !== channelFilter) continue;
2271
- const command = typeof entry.config.command === "string" ? entry.config.command : void 0;
2272
- const args = Array.isArray(entry.config.args) ? entry.config.args.filter((value) => typeof value === "string") : [];
2273
- const env = typeof entry.config.env === "object" && entry.config.env !== null ? entry.config.env : {};
2274
- const lockEntry = lockEntries[entry.name];
2275
- const lockTracked = lockEntry !== void 0;
2276
- const health = checkCleoEntryHealth(command, lockTracked);
2277
- entries.push({
2278
- provider: provider.id,
2279
- providerName: provider.toolName,
2280
- serverName: entry.name,
2281
- channel,
2282
- scope,
2283
- command,
2284
- args,
2285
- env,
2286
- version: lockEntry?.version ?? null,
2287
- source: lockEntry?.source ?? null,
2288
- sourceType: lockEntry?.sourceType ?? null,
2289
- installedAt: lockEntry?.installedAt ?? null,
2290
- updatedAt: lockEntry?.updatedAt ?? null,
2291
- health
2292
- });
2293
- if (health.status === "broken") {
2294
- warnings.push({
2295
- code: "W_COMMAND_UNREACHABLE",
2296
- message: `${entry.name} command not reachable on ${provider.toolName} (${health.commandDetail})`
2297
- });
2298
- } else if (health.status === "degraded") {
2299
- warnings.push({
2300
- code: "W_NOT_TRACKED",
2301
- message: `${entry.name} on ${provider.toolName} is not tracked in lock file`
2302
- });
2303
- }
2304
- }
2305
- }
2306
- }
2307
- const issueCount = entries.filter((e) => e.health.status !== "healthy").length;
2308
- if (format === "human") {
2309
- if (entries.length === 0) {
2310
- console.log(pc6.dim("No CLEO channel profiles found."));
2311
- } else {
2312
- console.log(pc6.bold("CLEO Channel Profiles"));
2313
- console.log();
2314
- const header = [
2315
- "Channel".padEnd(10),
2316
- "Version".padEnd(10),
2317
- "Provider".padEnd(22),
2318
- "Scope".padEnd(9),
2319
- "Command".padEnd(33),
2320
- "Status".padEnd(10),
2321
- "Installed".padEnd(12)
2322
- ].join("");
2323
- console.log(` ${pc6.dim(header)}`);
2324
- console.log(` ${pc6.dim("-".repeat(106))}`);
2325
- for (const entry of entries) {
2326
- const commandStr = entry.command ? `${entry.command} ${entry.args.join(" ")}`.slice(0, 31).padEnd(33) : pc6.dim("-").padEnd(33);
2327
- const versionStr = (entry.version ?? "-").padEnd(10);
2328
- const installedStr = entry.installedAt ? entry.installedAt.slice(0, 10).padEnd(12) : "-".padEnd(12);
2329
- let statusStr;
2330
- if (entry.health.status === "healthy") {
2331
- statusStr = pc6.green("healthy".padEnd(10));
2332
- } else if (entry.health.status === "degraded") {
2333
- statusStr = pc6.yellow("degraded".padEnd(10));
2334
- } else {
2335
- statusStr = pc6.red("broken".padEnd(10));
2336
- }
2337
- console.log(
2338
- ` ${entry.channel.padEnd(10)}${versionStr}${entry.providerName.padEnd(22)}${entry.scope.padEnd(9)}${commandStr}${statusStr}${installedStr}`
2339
- );
2340
- }
2341
- console.log();
2342
- const summary = ` ${entries.length} profile${entries.length !== 1 ? "s" : ""}`;
2343
- if (issueCount > 0) {
2344
- console.log(
2345
- `${summary} | ${pc6.yellow(`${issueCount} issue${issueCount !== 1 ? "s" : ""}`)}`
2346
- );
2347
- console.log();
2348
- console.log(" Issues:");
2349
- for (const w of warnings) {
2350
- console.log(` ${pc6.yellow("!")} ${w.message}`);
2351
- }
2352
- } else {
2353
- console.log(summary);
2354
- }
2355
- }
2356
- }
2357
- if (format === "json") {
2358
- outputSuccess(
2359
- operation,
2360
- mvi,
2361
- {
2362
- providers: providers.map((provider) => provider.id),
2363
- scopes,
2364
- channel: channelFilter,
2365
- profiles: entries,
2366
- count: entries.length
2367
- },
2368
- void 0,
2369
- void 0,
2370
- warnings.length > 0 ? warnings : void 0
2371
- );
2372
- }
2373
- }
2374
- async function executeCleoRepair(opts, operation) {
2375
- const mvi = "standard";
2376
- let format;
2377
- try {
2378
- format = resolveFormat({
2379
- jsonFlag: opts.json ?? false,
2380
- humanFlag: (opts.human ?? false) || isHuman(),
2381
- projectDefault: "json"
2382
- });
2383
- } catch (error) {
2384
- const message = error instanceof Error ? error.message : String(error);
2385
- emitJsonError(operation, mvi, ErrorCodes.FORMAT_CONFLICT, message, ErrorCategories.VALIDATION);
2386
- process.exit(1);
2387
- }
2388
- const providerIds = opts.provider.length > 0 ? opts.provider : void 0;
2389
- const result = await reconcileCleoLock({
2390
- providerIds,
2391
- all: opts.all,
2392
- global: opts.global,
2393
- project: opts.project,
2394
- prune: opts.prune,
2395
- dryRun: opts.dryRun
2396
- });
2397
- if (format === "human") {
2398
- const prefix = opts.dryRun ? "CLEO Lock Repair (dry run)" : "CLEO Lock Repair";
2399
- console.log(pc6.bold(prefix));
2400
- console.log();
2401
- if (result.backfilled.length > 0) {
2402
- for (const entry of result.backfilled) {
2403
- const agents = entry.agents.join(", ");
2404
- const versionStr = entry.version ? `(${entry.version})` : "";
2405
- console.log(
2406
- ` ${pc6.green("+")} ${entry.serverName.padEnd(12)}${entry.channel.padEnd(10)}${agents.padEnd(22)}${entry.scope.padEnd(10)}${entry.source} ${pc6.dim(versionStr)}`
2407
- );
2408
- }
2409
- }
2410
- if (result.pruned.length > 0) {
2411
- for (const name of result.pruned) {
2412
- console.log(` ${pc6.red("-")} ${name} (removed from lock)`);
2413
- }
2414
- }
2415
- if (result.backfilled.length === 0 && result.pruned.length === 0) {
2416
- console.log(pc6.dim(" No changes needed. All CLEO entries are tracked."));
2417
- }
2418
- console.log();
2419
- console.log(
2420
- ` ${result.backfilled.length} backfilled | ${result.pruned.length} pruned | ${result.alreadyTracked} already tracked`
2421
- );
2422
- if (result.errors.length > 0) {
2423
- console.log();
2424
- for (const err of result.errors) {
2425
- console.log(` ${pc6.red("!")} ${err.message}`);
2426
- }
2427
- }
2428
- }
2429
- if (format === "json") {
2430
- outputSuccess(operation, mvi, {
2431
- backfilled: result.backfilled,
2432
- pruned: result.pruned,
2433
- alreadyTracked: result.alreadyTracked,
2434
- dryRun: opts.dryRun ?? false,
2435
- errors: result.errors
2436
- });
2437
- }
2438
- }
2439
- function buildInstallOptions(command) {
2440
- return command.requiredOption("--channel <channel>", "CLEO channel: stable|beta|dev").option("--provider <id>", "Target provider (repeatable)", collect, []).option("--all", "Apply to all detected providers").option("-g, --global", "Use global scope").option("--version <tag>", "Tag/version for stable or beta").option("--command <command>", "Dev channel command").option("--arg <arg>", "Dev command arg (repeatable)", collect, []).option("--env <kv>", "Environment assignment KEY=value (repeatable)", collect, []).option("--cleo-dir <path>", "CLEO_DIR override for dev channel").option("--dry-run", "Preview without writing").option("-y, --yes", "Skip confirmation").option("--interactive", "Guided interactive setup").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format");
2441
- }
2442
- function registerMcpCleoCommands(parent) {
2443
- const cleo = parent.command("cleo").description("Manage CLEO MCP channel profiles");
2444
- buildInstallOptions(
2445
- cleo.command("install").description("Install CLEO MCP profile by channel")
2446
- ).action(async (opts) => {
2447
- await executeCleoInstall("install", opts, "mcp.cleo.install");
2448
- });
2449
- buildInstallOptions(
2450
- cleo.command("update").description("Update CLEO MCP profile by channel")
2451
- ).action(async (opts) => {
2452
- await executeCleoInstall("update", opts, "mcp.cleo.update");
2453
- });
2454
- cleo.command("uninstall").description("Uninstall CLEO MCP profile for a channel").requiredOption("--channel <channel>", "CLEO channel: stable|beta|dev").option("--provider <id>", "Target provider (repeatable)", collect, []).option("--all", "Apply to all detected providers").option("-g, --global", "Use global scope").option("--dry-run", "Preview without writing").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(async (opts) => {
2455
- await executeCleoUninstall(opts, "mcp.cleo.uninstall");
2456
- });
2457
- cleo.command("show").description("Show installed CLEO MCP channel profiles").option("--provider <id>", "Target provider (repeatable)", collect, []).option("--all", "Inspect all detected providers").option("-g, --global", "Global scope only").option("-p, --project", "Project scope only").option("--channel <channel>", "Filter channel: stable|beta|dev").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(async (opts) => {
2458
- await executeCleoShow(opts, "mcp.cleo.show");
2459
- });
2460
- cleo.command("repair").description("Repair lock file by backfilling untracked CLEO entries").option("--provider <id>", "Target provider (repeatable)", collect, []).option("--all", "Scan all detected providers").option("-g, --global", "Global scope only").option("-p, --project", "Project scope only").option("--prune", "Remove orphaned lock entries not in any config").option("--dry-run", "Preview without writing").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(async (opts) => {
2461
- await executeCleoRepair(opts, "mcp.cleo.repair");
2462
- });
2463
- }
2464
- function registerMcpCleoCompatibilityCommands(parent) {
2465
- parent.command("update").description("Update channel-managed MCP profile").argument("<name>", "Managed MCP profile name (cleo)").requiredOption("--channel <channel>", "CLEO channel: stable|beta|dev").option("--provider <id>", "Target provider (repeatable)", collect, []).option("--all", "Apply to all detected providers").option("-g, --global", "Use global scope").option("--version <tag>", "Tag/version for stable or beta").option("--command <command>", "Dev channel command").option("--arg <arg>", "Dev command arg (repeatable)", collect, []).option("--env <kv>", "Environment assignment KEY=value (repeatable)", collect, []).option("--cleo-dir <path>", "CLEO_DIR override for dev channel").option("--dry-run", "Preview without writing").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(async (name, opts) => {
2466
- if (name !== "cleo") {
2467
- emitJsonError(
2468
- "mcp.update",
2469
- "standard",
2470
- ErrorCodes.INVALID_INPUT,
2471
- "Only managed profile 'cleo' is supported by mcp update.",
2472
- ErrorCategories.VALIDATION,
2473
- { name }
2474
- );
2475
- process.exit(1);
2476
- }
2477
- await executeCleoInstall("update", opts, "mcp.update");
2478
- });
2479
- parent.command("uninstall").description("Uninstall channel-managed MCP profile").argument("<name>", "Managed MCP profile name (cleo)").requiredOption("--channel <channel>", "CLEO channel: stable|beta|dev").option("--provider <id>", "Target provider (repeatable)", collect, []).option("--all", "Apply to all detected providers").option("-g, --global", "Use global scope").option("--dry-run", "Preview without writing").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(async (name, opts) => {
2480
- if (name !== "cleo") {
2481
- emitJsonError(
2482
- "mcp.uninstall",
2483
- "standard",
2484
- ErrorCodes.INVALID_INPUT,
2485
- "Only managed profile 'cleo' is supported by mcp uninstall.",
2486
- ErrorCategories.VALIDATION,
2487
- { name }
2488
- );
2489
- process.exit(1);
2490
- }
2491
- await executeCleoUninstall(opts, "mcp.uninstall");
2492
- });
2493
- parent.command("show").description("Show channel-managed MCP profile").argument("<name>", "Managed MCP profile name (cleo)").option("--provider <id>", "Target provider (repeatable)", collect, []).option("--all", "Inspect all detected providers").option("-g, --global", "Global scope only").option("-p, --project", "Project scope only").option("--channel <channel>", "Filter channel: stable|beta|dev").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(async (name, opts) => {
2494
- if (name !== "cleo") {
2495
- emitJsonError(
2496
- "mcp.show",
2497
- "standard",
2498
- ErrorCodes.INVALID_INPUT,
2499
- "Only managed profile 'cleo' is supported by mcp show.",
2500
- ErrorCategories.VALIDATION,
2501
- { name }
2502
- );
2503
- process.exit(1);
2504
- }
2505
- await executeCleoShow(opts, "mcp.show");
2506
- });
2507
- }
2508
- function mapCompatibilityInstallOptions(opts) {
2509
- return {
2510
- channel: opts.channel,
2511
- provider: [...opts.provider ?? [], ...opts.agent ?? []],
2512
- all: opts.all,
2513
- global: opts.global,
2514
- version: opts.version,
2515
- command: opts.command,
2516
- arg: opts.arg ?? [],
2517
- env: opts.env ?? [],
2518
- cleoDir: opts.cleoDir,
2519
- dryRun: opts.dryRun,
2520
- yes: opts.yes,
2521
- interactive: opts.interactive,
2522
- json: opts.json,
2523
- human: opts.human
2524
- };
2525
- }
2526
- function shouldUseCleoCompatibilityInstall(source, channel) {
2527
- if (source.trim().toLowerCase() !== "cleo") return false;
2528
- return typeof channel === "string" && channel.trim() !== "";
2529
- }
2530
- function registerCleoCommands(program2) {
2531
- const cleo = program2.command("cleo").description("Manage CLEO channel profiles");
2532
- buildInstallOptions(
2533
- cleo.command("install").description("Install CLEO profile by channel")
2534
- ).action(async (opts) => {
2535
- await executeCleoInstall("install", opts, "cleo.install");
2536
- });
2537
- buildInstallOptions(cleo.command("update").description("Update CLEO profile by channel")).action(
2538
- async (opts) => {
2539
- await executeCleoInstall("update", opts, "cleo.update");
2540
- }
2541
- );
2542
- cleo.command("uninstall").description("Uninstall CLEO profile for a channel").requiredOption("--channel <channel>", "CLEO channel: stable|beta|dev").option("--provider <id>", "Target provider (repeatable)", collect, []).option("--all", "Apply to all detected providers").option("-g, --global", "Use global scope").option("--dry-run", "Preview without writing").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(async (opts) => {
2543
- await executeCleoUninstall(opts, "cleo.uninstall");
2544
- });
2545
- cleo.command("show").description("Show installed CLEO channel profiles").option("--provider <id>", "Target provider (repeatable)", collect, []).option("--all", "Inspect all detected providers").option("-g, --global", "Global scope only").option("-p, --project", "Project scope only").option("--channel <channel>", "Filter channel: stable|beta|dev").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(async (opts) => {
2546
- await executeCleoShow(opts, "cleo.show");
2547
- });
2548
- cleo.command("repair").description("Repair lock file by backfilling untracked CLEO entries").option("--provider <id>", "Target provider (repeatable)", collect, []).option("--all", "Scan all detected providers").option("-g, --global", "Global scope only").option("-p, --project", "Project scope only").option("--prune", "Remove orphaned lock entries not in any config").option("--dry-run", "Preview without writing").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(async (opts) => {
2549
- await executeCleoRepair(opts, "cleo.repair");
2550
- });
2551
- }
2552
-
2553
- // src/commands/mcp/detect.ts
2554
- import { existsSync as existsSync3 } from "fs";
2555
- import pc7 from "picocolors";
2556
- function registerMcpDetect(parent) {
2557
- parent.command("detect").description("Auto-detect installed MCP tools and their configurations").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(async (opts) => {
2558
- const operation = "mcp.detect";
2559
- const mvi = "standard";
2560
- let format;
2561
- try {
2562
- format = resolveFormat({
2563
- jsonFlag: opts.json ?? false,
2564
- humanFlag: (opts.human ?? false) || isHuman(),
2565
- projectDefault: "json"
2566
- });
2567
- } catch (error) {
2568
- const message = error instanceof Error ? error.message : String(error);
2569
- emitJsonError(
2570
- operation,
2571
- mvi,
2572
- ErrorCodes.FORMAT_CONFLICT,
2573
- message,
2574
- ErrorCategories.VALIDATION
2575
- );
2576
- process.exit(1);
2577
- }
2578
- const providers = getInstalledProviders();
2579
- const providersResult = [];
2580
- let totalConfigs = 0;
2581
- for (const provider of providers) {
2582
- const globalPath = resolveConfigPath(provider, "global");
2583
- const projectPath = resolveConfigPath(provider, "project");
2584
- const globalEntries = await listMcpServers(provider, "global");
2585
- const projectEntries = await listMcpServers(provider, "project");
2586
- const configsFound = (globalPath && existsSync3(globalPath) ? 1 : 0) + (projectPath && existsSync3(projectPath) ? 1 : 0);
2587
- totalConfigs += configsFound;
2588
- const allServers = [
2589
- ...globalEntries.map((e) => e.name),
2590
- ...projectEntries.map((e) => e.name)
2591
- ];
2592
- providersResult.push({
2593
- id: provider.id,
2594
- configsFound,
2595
- servers: allServers
2596
- });
2597
- }
2598
- if (format === "json") {
2599
- outputSuccess(operation, mvi, {
2600
- providers: providersResult,
2601
- totalConfigs
2602
- });
2603
- return;
2604
- }
2605
- console.log(pc7.bold(`
2606
- ${providers.length} provider(s) with MCP support:
2607
- `));
2608
- for (const provider of providersResult) {
2609
- const globalPath = resolveConfigPath(
2610
- providers.find((p) => p.id === provider.id),
2611
- "global"
2612
- );
2613
- const projectPath = resolveConfigPath(
2614
- providers.find((p) => p.id === provider.id),
2615
- "project"
2616
- );
2617
- const hasGlobal = globalPath && existsSync3(globalPath);
2618
- const hasProject = projectPath && existsSync3(projectPath);
2619
- const globalIcon = hasGlobal ? pc7.green("G") : pc7.dim("-");
2620
- const projectIcon = hasProject ? pc7.green("P") : pc7.dim("-");
2621
- const serverList = provider.servers.length > 0 ? pc7.dim(provider.servers.join(", ")) : pc7.dim("no servers");
2622
- console.log(
2623
- ` [${globalIcon}${projectIcon}] ${pc7.bold(provider.id.padEnd(20))} ${serverList}`
2624
- );
2625
- }
2626
- console.log(pc7.dim("\nG = global config, P = project config"));
2627
- console.log();
2628
- });
2629
- }
2630
-
2631
- // src/commands/mcp/install.ts
2632
- import pc8 from "picocolors";
2633
- function registerMcpInstall(parent) {
2634
- parent.command("install").description("Install MCP server to agent configs").argument("<source>", "MCP server source (URL, npm package, or command)").option(
2635
- "-a, --agent <name>",
2636
- "Target specific agent(s)",
2637
- (v, prev) => [...prev, v],
2638
- []
2639
- ).option(
2640
- "--provider <id>",
2641
- "Target provider ID (alias for --agent)",
2642
- (v, prev) => [...prev, v],
2643
- []
2644
- ).option("-g, --global", "Install to global/user config").option("-n, --name <name>", "Override inferred server name").option("--channel <channel>", "Managed channel profile (stable|beta|dev)").option("--version <tag>", "Managed profile tag/version for stable or beta").option("--command <command>", "Managed dev profile command").option(
2645
- "--arg <arg>",
2646
- "Managed dev command arg (repeatable)",
2647
- (v, prev) => [...prev, v],
2648
- []
2649
- ).option(
2650
- "--env <kv>",
2651
- "Managed env assignment KEY=value (repeatable)",
2652
- (v, prev) => [...prev, v],
2653
- []
2654
- ).option("--cleo-dir <path>", "Managed dev CLEO_DIR override").option("-t, --transport <type>", "Transport type: http (default) or sse", "http").option(
2655
- "--header <header>",
2656
- "HTTP header (Key: Value)",
2657
- (v, prev) => [...prev, v],
2658
- []
2659
- ).option("-y, --yes", "Skip confirmation").option("--all", "Install to all detected agents").option("--interactive", "Guided interactive setup for managed profiles").option("--dry-run", "Preview without writing").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(
2660
- async (source, opts) => {
2661
- const operation = "mcp.install";
2662
- const mvi = "standard";
2663
- let format;
2664
- try {
2665
- format = resolveFormat({
2666
- jsonFlag: opts.json ?? false,
2667
- humanFlag: (opts.human ?? false) || isHuman(),
2668
- projectDefault: "json"
2669
- });
2670
- } catch (error) {
2671
- const message = error instanceof Error ? error.message : String(error);
2672
- emitJsonError(
2673
- operation,
2674
- mvi,
2675
- ErrorCodes.FORMAT_CONFLICT,
2676
- message,
2677
- ErrorCategories.VALIDATION
2678
- );
2679
- process.exit(1);
2680
- }
2681
- if (shouldUseCleoCompatibilityInstall(source, opts.channel)) {
2682
- const cleoOpts = mapCompatibilityInstallOptions(opts);
2683
- await executeCleoInstall("install", cleoOpts, operation);
2684
- return;
2685
- }
2686
- const parsed = parseSource(source);
2687
- const serverName = opts.name ?? parsed.inferredName;
2688
- const headers = {};
2689
- for (const h of opts.header) {
2690
- const idx = h.indexOf(":");
2691
- if (idx > 0) {
2692
- headers[h.slice(0, idx).trim()] = h.slice(idx + 1).trim();
2693
- }
2694
- }
2695
- const config = buildServerConfig(parsed, opts.transport, headers);
2696
- let providers;
2697
- if (opts.all) {
2698
- providers = getInstalledProviders();
2699
- } else if (opts.agent.length > 0) {
2700
- providers = opts.agent.map((a) => getProvider(a)).filter((p) => p !== void 0);
2701
- } else if (opts.provider.length > 0) {
2702
- providers = opts.provider.map((a) => getProvider(a)).filter((p) => p !== void 0);
2703
- } else {
2704
- providers = getInstalledProviders();
2705
- }
2706
- if (providers.length === 0) {
2707
- const message = "No target providers found.";
2708
- if (format === "json") {
2709
- emitJsonError(
2710
- operation,
2711
- mvi,
2712
- ErrorCodes.PROVIDER_NOT_FOUND,
2713
- message,
2714
- ErrorCategories.NOT_FOUND
2715
- );
2716
- } else {
2717
- console.error(pc8.red(message));
2718
- }
2719
- process.exit(1);
2720
- }
2721
- const scope = opts.global ? "global" : "project";
2722
- if (opts.dryRun) {
2723
- if (format === "json") {
2724
- outputSuccess(operation, mvi, {
2725
- installed: [
2726
- {
2727
- name: serverName,
2728
- providers: providers.map((p) => p.id),
2729
- config
2730
- }
2731
- ],
2732
- dryRun: true
2733
- });
2734
- } else {
2735
- console.log(pc8.bold("Dry run - would install:"));
2736
- console.log(` Server: ${pc8.bold(serverName)}`);
2737
- console.log(` Config: ${JSON.stringify(config, null, 2)}`);
2738
- console.log(` Scope: ${scope}`);
2739
- console.log(` Providers: ${providers.map((p) => p.id).join(", ")}`);
2740
- }
2741
- return;
2742
- }
2743
- if (format === "human") {
2744
- console.log(pc8.dim(`Installing "${serverName}" to ${providers.length} provider(s)...
2745
- `));
2746
- }
2747
- const results = await installMcpServerToAll(providers, serverName, config, scope);
2748
- const succeeded = results.filter((r) => r.success);
2749
- const _failed = results.filter((r) => !r.success);
2750
- if (format === "human") {
2751
- for (const r of results) {
2752
- if (r.success) {
2753
- console.log(
2754
- ` ${pc8.green("\u2713")} ${r.provider.toolName.padEnd(22)} ${pc8.dim(r.configPath)}`
2755
- );
2756
- } else {
2757
- console.log(
2758
- ` ${pc8.red("\u2717")} ${r.provider.toolName.padEnd(22)} ${pc8.red(r.error ?? "failed")}`
2759
- );
2760
- }
1164
+ } catch {
2761
1165
  }
2762
1166
  }
2763
- if (succeeded.length > 0) {
2764
- await recordMcpInstall(
2765
- serverName,
2766
- source,
2767
- parsed.type,
2768
- succeeded.map((r) => r.provider.id),
2769
- opts.global ?? false
2770
- );
2771
- }
2772
- if (format === "json") {
2773
- outputSuccess(operation, mvi, {
2774
- installed: succeeded.map((r) => ({
2775
- name: serverName,
2776
- providers: [r.provider.id],
2777
- config
2778
- })),
2779
- dryRun: false
2780
- });
2781
- } else {
2782
- console.log(pc8.bold(`
2783
- ${succeeded.length}/${results.length} providers configured.`));
2784
- }
1167
+ } catch {
2785
1168
  }
2786
- );
1169
+ }
1170
+ return { canonicalCount, brokenCount, staleCount };
2787
1171
  }
2788
1172
 
2789
- // src/commands/mcp/list.ts
2790
- import pc9 from "picocolors";
2791
- function registerMcpList(parent) {
2792
- parent.command("list").description("List configured MCP servers").option("-a, --agent <name>", "List for specific agent").option("--provider <id>", "Provider ID alias for --agent").option("-g, --global", "List global config").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(
1173
+ // src/commands/instructions/check.ts
1174
+ import pc3 from "picocolors";
1175
+ function registerInstructionsCheck(parent) {
1176
+ parent.command("check").description("Check injection status across providers").option(
1177
+ "-a, --agent <name>",
1178
+ "Check specific agent(s)",
1179
+ (v, prev) => [...prev, v],
1180
+ []
1181
+ ).option("-g, --global", "Check global instruction files").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").option("--all", "Check all known providers").action(
2793
1182
  async (opts) => {
2794
- const operation = "mcp.list";
1183
+ const operation = "instructions.check";
2795
1184
  const mvi = "standard";
2796
1185
  let format;
2797
1186
  try {
2798
1187
  format = resolveFormat({
2799
1188
  jsonFlag: opts.json ?? false,
2800
- humanFlag: (opts.human ?? false) || isHuman(),
1189
+ humanFlag: opts.human ?? false,
2801
1190
  projectDefault: "json"
2802
1191
  });
2803
1192
  } catch (error) {
@@ -2811,90 +1200,79 @@ function registerMcpList(parent) {
2811
1200
  );
2812
1201
  process.exit(1);
2813
1202
  }
2814
- const selectedProvider = opts.provider ?? opts.agent;
2815
- const providers = selectedProvider ? [getProvider(selectedProvider)].filter(
2816
- (p) => p !== void 0
2817
- ) : getInstalledProviders();
2818
- if (selectedProvider && providers.length === 0) {
2819
- const message = `Provider not found: ${selectedProvider}`;
2820
- if (format === "json") {
2821
- emitJsonError(
2822
- operation,
2823
- mvi,
2824
- ErrorCodes.PROVIDER_NOT_FOUND,
2825
- message,
2826
- ErrorCategories.NOT_FOUND,
2827
- {
2828
- provider: selectedProvider
2829
- }
2830
- );
2831
- } else {
2832
- console.error(pc9.red(message));
2833
- }
2834
- process.exit(1);
2835
- }
2836
- const allEntries = [];
2837
- for (const provider of providers) {
2838
- const scope = resolvePreferredConfigScope(provider, opts.global);
2839
- const entries = await listMcpServers(provider, scope);
2840
- for (const entry of entries) {
2841
- allEntries.push({
2842
- name: entry.name,
2843
- command: typeof entry.config.command === "string" ? entry.config.command : void 0,
2844
- scope
2845
- });
2846
- }
1203
+ let providers;
1204
+ if (opts.all) {
1205
+ providers = getAllProviders();
1206
+ } else if (opts.agent.length > 0) {
1207
+ providers = opts.agent.map((a) => getProvider(a)).filter((p) => p !== void 0);
1208
+ } else {
1209
+ providers = getInstalledProviders();
2847
1210
  }
1211
+ const scope = opts.global ? "global" : "project";
1212
+ const results = await checkAllInjections(providers, process.cwd(), scope);
1213
+ const providerStatus = results.map((r) => ({
1214
+ id: r.provider,
1215
+ present: r.status === "current" || r.status === "outdated",
1216
+ path: r.file
1217
+ }));
1218
+ const present = providerStatus.filter((p) => p.present).length;
1219
+ const missing = providerStatus.filter((p) => !p.present).length;
2848
1220
  if (format === "json") {
2849
1221
  outputSuccess(operation, mvi, {
2850
- servers: allEntries,
2851
- count: allEntries.length,
2852
- scope: opts.global ? "global" : selectedProvider ? `agent:${selectedProvider}` : "project"
1222
+ providers: providerStatus,
1223
+ present,
1224
+ missing
2853
1225
  });
2854
1226
  return;
2855
1227
  }
2856
- if (allEntries.length === 0) {
2857
- console.log(pc9.dim("No MCP servers configured."));
2858
- return;
2859
- }
2860
- console.log(pc9.bold(`
2861
- ${allEntries.length} MCP server(s) configured:
1228
+ console.log(pc3.bold(`
1229
+ Instruction file status (${scope}):
2862
1230
  `));
2863
- for (const entry of allEntries) {
2864
- const scopeIndicator = entry.scope === "global" ? pc9.dim("[G] ") : pc9.dim("[P] ");
2865
- console.log(
2866
- ` ${scopeIndicator}${pc9.bold(entry.name.padEnd(25))} ${entry.command ? pc9.dim(entry.command) : ""}`
2867
- );
1231
+ for (const r of results) {
1232
+ let icon;
1233
+ let label;
1234
+ switch (r.status) {
1235
+ case "current":
1236
+ icon = pc3.green("\u2713");
1237
+ label = "current";
1238
+ break;
1239
+ case "outdated":
1240
+ icon = pc3.yellow("~");
1241
+ label = "outdated";
1242
+ break;
1243
+ case "missing":
1244
+ icon = pc3.red("\u2717");
1245
+ label = "missing";
1246
+ break;
1247
+ case "none":
1248
+ icon = pc3.dim("-");
1249
+ label = "no injection";
1250
+ break;
1251
+ }
1252
+ console.log(` ${icon} ${r.file.padEnd(40)} ${label}`);
2868
1253
  }
2869
1254
  console.log();
2870
- console.log(pc9.dim("G = global config, P = project config"));
2871
- console.log();
2872
1255
  }
2873
1256
  );
2874
1257
  }
2875
1258
 
2876
- // src/commands/mcp/remove.ts
2877
- import pc10 from "picocolors";
2878
- function registerMcpRemove(parent) {
2879
- parent.command("remove").description("Remove MCP server from agent configs").argument("<name>", "MCP server name to remove").option(
1259
+ // src/commands/instructions/inject.ts
1260
+ import pc4 from "picocolors";
1261
+ function registerInstructionsInject(parent) {
1262
+ parent.command("inject").description("Inject instruction blocks into all provider files").option(
2880
1263
  "-a, --agent <name>",
2881
1264
  "Target specific agent(s)",
2882
1265
  (v, prev) => [...prev, v],
2883
1266
  []
2884
- ).option(
2885
- "--provider <id>",
2886
- "Target provider ID (alias for --agent)",
2887
- (v, prev) => [...prev, v],
2888
- []
2889
- ).option("-g, --global", "Remove from global config").option("--all", "Remove from all detected agents").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(
2890
- async (name, opts) => {
2891
- const operation = "mcp.remove";
1267
+ ).option("-g, --global", "Inject into global instruction files").option("--content <text>", "Custom content to inject").option("--dry-run", "Preview without writing").option("--all", "Target all known providers").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(
1268
+ async (opts) => {
1269
+ const operation = "instructions.inject";
2892
1270
  const mvi = "standard";
2893
1271
  let format;
2894
1272
  try {
2895
1273
  format = resolveFormat({
2896
1274
  jsonFlag: opts.json ?? false,
2897
- humanFlag: (opts.human ?? false) || isHuman(),
1275
+ humanFlag: opts.human ?? false,
2898
1276
  projectDefault: "json"
2899
1277
  });
2900
1278
  } catch (error) {
@@ -2910,16 +1288,14 @@ function registerMcpRemove(parent) {
2910
1288
  }
2911
1289
  let providers;
2912
1290
  if (opts.all) {
2913
- providers = getInstalledProviders();
1291
+ providers = getAllProviders();
2914
1292
  } else if (opts.agent.length > 0) {
2915
1293
  providers = opts.agent.map((a) => getProvider(a)).filter((p) => p !== void 0);
2916
- } else if (opts.provider.length > 0) {
2917
- providers = opts.provider.map((a) => getProvider(a)).filter((p) => p !== void 0);
2918
1294
  } else {
2919
1295
  providers = getInstalledProviders();
2920
1296
  }
2921
1297
  if (providers.length === 0) {
2922
- const message = "No target providers found.";
1298
+ const message = "No providers found.";
2923
1299
  if (format === "json") {
2924
1300
  emitJsonError(
2925
1301
  operation,
@@ -2929,60 +1305,144 @@ function registerMcpRemove(parent) {
2929
1305
  ErrorCategories.NOT_FOUND
2930
1306
  );
2931
1307
  } else {
2932
- console.error(pc10.red(message));
1308
+ console.error(pc4.red(message));
2933
1309
  }
2934
1310
  process.exit(1);
2935
1311
  }
1312
+ const content = opts.content ?? generateInjectionContent();
2936
1313
  const scope = opts.global ? "global" : "project";
2937
- const removed = [];
2938
- const notFound = [];
2939
- for (const provider of providers) {
2940
- const success = await removeMcpServer(provider, name, scope);
2941
- if (success) {
2942
- removed.push(provider.id);
2943
- if (format === "human") {
2944
- console.log(` ${pc10.green("\u2713")} Removed from ${provider.toolName}`);
2945
- }
1314
+ const groups = groupByInstructFile(providers);
1315
+ if (opts.dryRun) {
1316
+ if (format === "json") {
1317
+ outputSuccess(operation, mvi, {
1318
+ injected: [],
1319
+ providers: providers.map((p) => p.id),
1320
+ count: 0,
1321
+ dryRun: true,
1322
+ wouldInject: Array.from(groups.entries()).map(([file, group]) => ({
1323
+ file,
1324
+ providers: group.map((p) => p.id)
1325
+ }))
1326
+ });
2946
1327
  } else {
2947
- notFound.push(provider.id);
1328
+ console.log(pc4.bold("Dry run - would inject into:\n"));
1329
+ for (const [file, group] of groups) {
1330
+ console.log(` ${pc4.bold(file)}: ${group.map((p) => p.id).join(", ")}`);
1331
+ }
1332
+ console.log(pc4.dim(`
1333
+ Scope: ${scope}`));
1334
+ console.log(pc4.dim(` Content length: ${content.length} chars`));
2948
1335
  }
1336
+ return;
2949
1337
  }
2950
- if (removed.length > 0) {
2951
- await removeMcpFromLock(name);
1338
+ const results = await injectAll(providers, process.cwd(), scope, content);
1339
+ const injected = [];
1340
+ for (const [file] of results) {
1341
+ injected.push(file);
2952
1342
  }
2953
1343
  if (format === "json") {
2954
1344
  outputSuccess(operation, mvi, {
2955
- removed,
2956
- providers: removed,
2957
- notFound: notFound.length > 0 ? notFound : void 0
1345
+ injected,
1346
+ providers: providers.map((p) => p.id),
1347
+ count: results.size
2958
1348
  });
2959
1349
  } else {
2960
- if (removed.length > 0) {
2961
- console.log(pc10.green(`
2962
- \u2713 Removed "${name}" from ${removed.length} provider(s).`));
2963
- } else {
2964
- console.log(pc10.yellow(`Server "${name}" not found in any provider config.`));
1350
+ for (const [file, action] of results) {
1351
+ const icon = action === "created" ? pc4.green("+") : action === "updated" ? pc4.yellow("~") : pc4.blue("^");
1352
+ console.log(` ${icon} ${file} (${action})`);
2965
1353
  }
1354
+ console.log(pc4.bold(`
1355
+ ${results.size} file(s) processed.`));
2966
1356
  }
2967
1357
  }
2968
1358
  );
2969
1359
  }
2970
1360
 
2971
- // src/commands/mcp/index.ts
2972
- function registerMcpCommands(program2) {
2973
- const mcp = program2.command("mcp").description("Manage MCP server configurations");
2974
- registerMcpInstall(mcp);
2975
- registerMcpRemove(mcp);
2976
- registerMcpList(mcp);
2977
- registerMcpDetect(mcp);
2978
- registerMcpCleoCommands(mcp);
2979
- registerMcpCleoCompatibilityCommands(mcp);
1361
+ // src/commands/instructions/update.ts
1362
+ import pc5 from "picocolors";
1363
+ function registerInstructionsUpdate(parent) {
1364
+ parent.command("update").description("Update all instruction file injections").option("-g, --global", "Update global instruction files").option("-y, --yes", "Skip confirmation").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(async (opts) => {
1365
+ const operation = "instructions.update";
1366
+ const mvi = "standard";
1367
+ let format;
1368
+ try {
1369
+ format = resolveFormat({
1370
+ jsonFlag: opts.json ?? false,
1371
+ humanFlag: opts.human ?? false,
1372
+ projectDefault: "json"
1373
+ });
1374
+ } catch (error) {
1375
+ const message = error instanceof Error ? error.message : String(error);
1376
+ emitJsonError(
1377
+ operation,
1378
+ mvi,
1379
+ ErrorCodes.FORMAT_CONFLICT,
1380
+ message,
1381
+ ErrorCategories.VALIDATION
1382
+ );
1383
+ process.exit(1);
1384
+ }
1385
+ const providers = getInstalledProviders();
1386
+ const scope = opts.global ? "global" : "project";
1387
+ const content = generateInjectionContent();
1388
+ const checks = await checkAllInjections(providers, process.cwd(), scope, content);
1389
+ const needsUpdate = checks.filter((c) => c.status !== "current");
1390
+ if (needsUpdate.length === 0) {
1391
+ if (format === "json") {
1392
+ outputSuccess(operation, mvi, {
1393
+ updated: [],
1394
+ failed: [],
1395
+ count: { updated: 0, failed: 0 }
1396
+ });
1397
+ } else {
1398
+ console.log(pc5.green("All instruction files are up to date."));
1399
+ }
1400
+ return;
1401
+ }
1402
+ if (format === "human") {
1403
+ console.log(pc5.bold(`${needsUpdate.length} file(s) need updating:
1404
+ `));
1405
+ for (const c of needsUpdate) {
1406
+ console.log(` ${c.file} (${c.status})`);
1407
+ }
1408
+ }
1409
+ const providerIds = new Set(needsUpdate.map((c) => c.provider));
1410
+ const toUpdate = providers.filter((p) => providerIds.has(p.id));
1411
+ const results = await injectAll(toUpdate, process.cwd(), scope, content);
1412
+ const updated = [];
1413
+ for (const [file] of results) {
1414
+ updated.push(file);
1415
+ }
1416
+ if (format === "human") {
1417
+ console.log();
1418
+ for (const [file, action] of results) {
1419
+ console.log(` ${pc5.green("\u2713")} ${file} (${action})`);
1420
+ }
1421
+ console.log(pc5.bold(`
1422
+ ${results.size} file(s) updated.`));
1423
+ }
1424
+ if (format === "json") {
1425
+ outputSuccess(operation, mvi, {
1426
+ updated,
1427
+ failed: [],
1428
+ count: { updated: updated.length, failed: 0 }
1429
+ });
1430
+ }
1431
+ });
1432
+ }
1433
+
1434
+ // src/commands/instructions/index.ts
1435
+ function registerInstructionsCommands(program2) {
1436
+ const instructions = program2.command("instructions").description("Manage instruction file injections");
1437
+ registerInstructionsInject(instructions);
1438
+ registerInstructionsCheck(instructions);
1439
+ registerInstructionsUpdate(instructions);
2980
1440
  }
2981
1441
 
2982
1442
  // src/commands/providers.ts
2983
1443
  import { randomUUID as randomUUID3 } from "crypto";
2984
1444
  import { resolveOutputFormat as resolveOutputFormat2 } from "@cleocode/lafs";
2985
- import pc11 from "picocolors";
1445
+ import pc6 from "picocolors";
2986
1446
  function registerProvidersCommand(program2) {
2987
1447
  const providers = program2.command("providers").description("Manage AI agent providers");
2988
1448
  providers.command("list").description("List all supported providers").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").option("--tier <tier>", "Filter by priority tier (high, medium, low)").action(async (opts) => {
@@ -3016,20 +1476,20 @@ function registerProvidersCommand(program2) {
3016
1476
  console.log(JSON.stringify(envelope, null, 2));
3017
1477
  return;
3018
1478
  }
3019
- console.log(pc11.bold(`
1479
+ console.log(pc6.bold(`
3020
1480
  CAMP Provider Registry v${getRegistryVersion()}`));
3021
- console.log(pc11.dim(`${getProviderCount()} providers
1481
+ console.log(pc6.dim(`${getProviderCount()} providers
3022
1482
  `));
3023
1483
  const tiers = ["high", "medium", "low"];
3024
1484
  for (const tier of tiers) {
3025
1485
  const tierProviders = all.filter((p) => p.priority === tier);
3026
1486
  if (tierProviders.length === 0) continue;
3027
- const tierLabel = tier === "high" ? pc11.green("HIGH") : tier === "medium" ? pc11.yellow("MEDIUM") : pc11.dim("LOW");
1487
+ const tierLabel = tier === "high" ? pc6.green("HIGH") : tier === "medium" ? pc6.yellow("MEDIUM") : pc6.dim("LOW");
3028
1488
  console.log(`${tierLabel} priority:`);
3029
1489
  for (const p of tierProviders) {
3030
- const status = p.status === "active" ? pc11.green("active") : p.status === "beta" ? pc11.yellow("beta") : pc11.dim(p.status);
1490
+ const status = p.status === "active" ? pc6.green("active") : p.status === "beta" ? pc6.yellow("beta") : pc6.dim(p.status);
3031
1491
  console.log(
3032
- ` ${pc11.bold(p.agentFlag.padEnd(20))} ${p.toolName.padEnd(22)} ${p.vendor.padEnd(16)} [${status}]`
1492
+ ` ${pc6.bold(p.agentFlag.padEnd(20))} ${p.toolName.padEnd(22)} ${p.vendor.padEnd(16)} [${status}]`
3033
1493
  );
3034
1494
  }
3035
1495
  console.log();
@@ -3074,19 +1534,19 @@ CAMP Provider Registry v${getRegistryVersion()}`));
3074
1534
  console.log(JSON.stringify(envelope, null, 2));
3075
1535
  return;
3076
1536
  }
3077
- console.log(pc11.bold(`
1537
+ console.log(pc6.bold(`
3078
1538
  Detected ${installed.length} installed providers:
3079
1539
  `));
3080
1540
  for (const r of installed) {
3081
1541
  const methods = r.methods.join(", ");
3082
- const project = r.projectDetected ? pc11.green(" [project]") : "";
1542
+ const project = r.projectDetected ? pc6.green(" [project]") : "";
3083
1543
  console.log(
3084
- ` ${pc11.green("\u2713")} ${pc11.bold(r.provider.toolName.padEnd(22))} via ${pc11.dim(methods)}${project}`
1544
+ ` ${pc6.green("\u2713")} ${pc6.bold(r.provider.toolName.padEnd(22))} via ${pc6.dim(methods)}${project}`
3085
1545
  );
3086
1546
  }
3087
1547
  const notInstalled = results.filter((r) => !r.installed);
3088
1548
  if (notInstalled.length > 0) {
3089
- console.log(pc11.dim(`
1549
+ console.log(pc6.dim(`
3090
1550
  ${notInstalled.length} providers not detected`));
3091
1551
  }
3092
1552
  console.log();
@@ -3114,7 +1574,7 @@ Detected ${installed.length} installed providers:
3114
1574
  id
3115
1575
  });
3116
1576
  } else {
3117
- console.error(pc11.red(message));
1577
+ console.error(pc6.red(message));
3118
1578
  }
3119
1579
  process.exit(1);
3120
1580
  }
@@ -3130,9 +1590,9 @@ Detected ${installed.length} installed providers:
3130
1590
  console.log(JSON.stringify(envelope, null, 2));
3131
1591
  return;
3132
1592
  }
3133
- console.log(pc11.bold(`
1593
+ console.log(pc6.bold(`
3134
1594
  ${provider.toolName}`));
3135
- console.log(pc11.dim(`by ${provider.vendor}
1595
+ console.log(pc6.dim(`by ${provider.vendor}
3136
1596
  `));
3137
1597
  console.log(` ID: ${provider.id}`);
3138
1598
  console.log(` Flag: --agent ${provider.agentFlag}`);
@@ -3148,7 +1608,7 @@ ${provider.toolName}`));
3148
1608
  console.log(` Transports: ${provider.supportedTransports.join(", ")}`);
3149
1609
  console.log(` Headers: ${provider.supportsHeaders ? "yes" : "no"}`);
3150
1610
  console.log();
3151
- console.log(pc11.dim(" Paths:"));
1611
+ console.log(pc6.dim(" Paths:"));
3152
1612
  console.log(` Global dir: ${provider.pathGlobal}`);
3153
1613
  console.log(` Project dir: ${provider.pathProject || "(none)"}`);
3154
1614
  console.log(` Global config: ${provider.configPathGlobal}`);
@@ -3182,7 +1642,7 @@ ${provider.toolName}`));
3182
1642
  id: opts.provider
3183
1643
  });
3184
1644
  } else {
3185
- console.error(pc11.red(message));
1645
+ console.error(pc6.red(message));
3186
1646
  }
3187
1647
  process.exit(1);
3188
1648
  }
@@ -3200,9 +1660,9 @@ ${provider.toolName}`));
3200
1660
  console.log(JSON.stringify(envelope, null, 2));
3201
1661
  return;
3202
1662
  }
3203
- console.log(pc11.bold("\nProvider Skills Map\n"));
1663
+ console.log(pc6.bold("\nProvider Skills Map\n"));
3204
1664
  console.log(
3205
- ` ${pc11.bold("Provider".padEnd(22))} ${pc11.bold("Precedence".padEnd(30))} ${pc11.bold("Global Path".padEnd(40))} ${pc11.bold("Project Path")}`
1665
+ ` ${pc6.bold("Provider".padEnd(22))} ${pc6.bold("Precedence".padEnd(30))} ${pc6.bold("Global Path".padEnd(40))} ${pc6.bold("Project Path")}`
3206
1666
  );
3207
1667
  console.log(` ${"\u2500".repeat(22)} ${"\u2500".repeat(30)} ${"\u2500".repeat(40)} ${"\u2500".repeat(30)}`);
3208
1668
  for (const entry of map) {
@@ -3210,7 +1670,7 @@ ${provider.toolName}`));
3210
1670
  ` ${entry.toolName.padEnd(22)} ${entry.precedence.padEnd(30)} ${(entry.paths.global ?? "-").padEnd(40)} ${entry.paths.project ?? "-"}`
3211
1671
  );
3212
1672
  }
3213
- console.log(pc11.dim(`
1673
+ console.log(pc6.dim(`
3214
1674
  ${map.length} providers shown`));
3215
1675
  console.log();
3216
1676
  });
@@ -3246,25 +1706,25 @@ ${provider.toolName}`));
3246
1706
  console.log(JSON.stringify(envelope, null, 2));
3247
1707
  return;
3248
1708
  }
3249
- console.log(pc11.bold(`
1709
+ console.log(pc6.bold(`
3250
1710
  CAMP Hook Support (mappings v${getHookMappingsVersion()})
3251
1711
  `));
3252
- console.log(pc11.dim(` ${CANONICAL_HOOK_EVENTS.length} canonical events defined
1712
+ console.log(pc6.dim(` ${CANONICAL_HOOK_EVENTS.length} canonical events defined
3253
1713
  `));
3254
1714
  console.log(
3255
- ` ${pc11.bold("Provider".padEnd(22))} ${pc11.bold("System".padEnd(10))} ${pc11.bold("Coverage".padEnd(12))} ${pc11.bold("Supported".padEnd(12))} ${pc11.bold("Provider-Only")}`
1715
+ ` ${pc6.bold("Provider".padEnd(22))} ${pc6.bold("System".padEnd(10))} ${pc6.bold("Coverage".padEnd(12))} ${pc6.bold("Supported".padEnd(12))} ${pc6.bold("Provider-Only")}`
3256
1716
  );
3257
1717
  console.log(
3258
1718
  ` ${"\u2500".repeat(22)} ${"\u2500".repeat(10)} ${"\u2500".repeat(12)} ${"\u2500".repeat(12)} ${"\u2500".repeat(20)}`
3259
1719
  );
3260
1720
  for (const s of summaries) {
3261
1721
  if (!s) continue;
3262
- const system = s.hookSystem === "none" ? pc11.dim("none") : s.experimental ? pc11.yellow(s.hookSystem + "*") : pc11.green(s.hookSystem);
3263
- const coverage = s.coverage > 0 ? (s.coverage >= 75 ? pc11.green : s.coverage >= 40 ? pc11.yellow : pc11.dim)(
1722
+ const system = s.hookSystem === "none" ? pc6.dim("none") : s.experimental ? pc6.yellow(s.hookSystem + "*") : pc6.green(s.hookSystem);
1723
+ const coverage = s.coverage > 0 ? (s.coverage >= 75 ? pc6.green : s.coverage >= 40 ? pc6.yellow : pc6.dim)(
3264
1724
  `${s.coverage}%`
3265
- ) : pc11.dim("0%");
3266
- const supported = s.supportedCount > 0 ? `${s.supportedCount}/${s.totalCanonical}` : pc11.dim("0");
3267
- const provOnly = s.providerOnly.length > 0 ? String(s.providerOnly.length) : pc11.dim("-");
1725
+ ) : pc6.dim("0%");
1726
+ const supported = s.supportedCount > 0 ? `${s.supportedCount}/${s.totalCanonical}` : pc6.dim("0");
1727
+ const provOnly = s.providerOnly.length > 0 ? String(s.providerOnly.length) : pc6.dim("-");
3268
1728
  const provider = getProvider(s.providerId);
3269
1729
  const name = provider?.toolName ?? s.providerId;
3270
1730
  console.log(
@@ -3273,13 +1733,13 @@ CAMP Hook Support (mappings v${getHookMappingsVersion()})
3273
1733
  }
3274
1734
  const withHooks = summaries.filter((s) => s && s.supportedCount > 0);
3275
1735
  console.log(
3276
- pc11.dim(
1736
+ pc6.dim(
3277
1737
  `
3278
1738
  ${withHooks.length} providers with hook support, ${summaries.length - withHooks.length} without`
3279
1739
  )
3280
1740
  );
3281
1741
  if (summaries.some((s) => s?.experimental)) {
3282
- console.log(pc11.dim(" * = experimental hook system"));
1742
+ console.log(pc6.dim(" * = experimental hook system"));
3283
1743
  }
3284
1744
  console.log();
3285
1745
  });
@@ -3309,22 +1769,22 @@ CAMP Hook Support (mappings v${getHookMappingsVersion()})
3309
1769
  const p = getProvider(id);
3310
1770
  return (p?.toolName ?? id).slice(0, 14);
3311
1771
  });
3312
- console.log(pc11.bold("\nHook Support Matrix\n"));
1772
+ console.log(pc6.bold("\nHook Support Matrix\n"));
3313
1773
  const eventCol = "CAAMP Event".padEnd(22);
3314
- const provCols = providerNames.map((n) => pc11.bold(n.padEnd(16))).join("");
3315
- console.log(` ${pc11.bold(eventCol)} ${provCols}`);
1774
+ const provCols = providerNames.map((n) => pc6.bold(n.padEnd(16))).join("");
1775
+ console.log(` ${pc6.bold(eventCol)} ${provCols}`);
3316
1776
  console.log(` ${"\u2500".repeat(22)} ${providerNames.map(() => "\u2500".repeat(16)).join("")}`);
3317
1777
  for (const event of matrix.events) {
3318
1778
  const cells = matrix.providers.map((id) => {
3319
1779
  const m = matrix.matrix[event][id];
3320
- if (!m?.supported) return pc11.dim("\xB7".padEnd(16));
3321
- return pc11.green((m.nativeName ?? "?").slice(0, 14).padEnd(16));
1780
+ if (!m?.supported) return pc6.dim("\xB7".padEnd(16));
1781
+ return pc6.green((m.nativeName ?? "?").slice(0, 14).padEnd(16));
3322
1782
  }).join("");
3323
1783
  console.log(` ${event.padEnd(22)} ${cells}`);
3324
1784
  }
3325
1785
  const commonEvents = getCommonEvents(matrix.providers);
3326
1786
  console.log(
3327
- pc11.dim(`
1787
+ pc6.dim(`
3328
1788
  Common events: ${commonEvents.length > 0 ? commonEvents.join(", ") : "none"}`)
3329
1789
  );
3330
1790
  console.log();
@@ -3352,7 +1812,7 @@ CAMP Hook Support (mappings v${getHookMappingsVersion()})
3352
1812
  if (format === "json") {
3353
1813
  emitJsonError2(operation, mvi, "E_UNKNOWN_EVENT", msg, "VALIDATION");
3354
1814
  } else {
3355
- console.error(pc11.red(msg));
1815
+ console.error(pc6.red(msg));
3356
1816
  }
3357
1817
  process.exit(1);
3358
1818
  }
@@ -3372,18 +1832,18 @@ CAMP Hook Support (mappings v${getHookMappingsVersion()})
3372
1832
  } else {
3373
1833
  if (result.supported) {
3374
1834
  console.log(`
3375
- ${pc11.green(event)} \u2192 ${pc11.bold(result.native)} (${opts.to})`);
3376
- if (result.notes) console.log(pc11.dim(` Note: ${result.notes}`));
1835
+ ${pc6.green(event)} \u2192 ${pc6.bold(result.native)} (${opts.to})`);
1836
+ if (result.notes) console.log(pc6.dim(` Note: ${result.notes}`));
3377
1837
  } else {
3378
1838
  console.log(`
3379
- ${pc11.red(event)} \u2192 ${pc11.dim("not supported")} (${opts.to})`);
1839
+ ${pc6.red(event)} \u2192 ${pc6.dim("not supported")} (${opts.to})`);
3380
1840
  }
3381
1841
  console.log();
3382
1842
  }
3383
1843
  return;
3384
1844
  }
3385
1845
  if (opts.from) {
3386
- const { toCanonical } = await import("./hooks-Q7KO2SGK.js");
1846
+ const { toCanonical } = await import("./hooks-VLIP52LY.js");
3387
1847
  const canonical2 = toCanonical(event, opts.from);
3388
1848
  if (format === "json") {
3389
1849
  const envelope = buildEnvelope2(
@@ -3402,11 +1862,11 @@ CAMP Hook Support (mappings v${getHookMappingsVersion()})
3402
1862
  } else {
3403
1863
  if (canonical2) {
3404
1864
  console.log(`
3405
- ${pc11.bold(event)} (${opts.from}) \u2192 ${pc11.green(canonical2)}`);
1865
+ ${pc6.bold(event)} (${opts.from}) \u2192 ${pc6.green(canonical2)}`);
3406
1866
  } else {
3407
1867
  console.log(
3408
1868
  `
3409
- ${pc11.bold(event)} (${opts.from}) \u2192 ${pc11.dim("no canonical mapping (provider-only event)")}`
1869
+ ${pc6.bold(event)} (${opts.from}) \u2192 ${pc6.dim("no canonical mapping (provider-only event)")}`
3410
1870
  );
3411
1871
  }
3412
1872
  console.log();
@@ -3419,11 +1879,11 @@ CAMP Hook Support (mappings v${getHookMappingsVersion()})
3419
1879
  if (format === "json") {
3420
1880
  emitJsonError2(operation, mvi, "E_UNKNOWN_EVENT", msg, "VALIDATION");
3421
1881
  } else {
3422
- console.error(pc11.red(msg));
1882
+ console.error(pc6.red(msg));
3423
1883
  }
3424
1884
  process.exit(1);
3425
1885
  }
3426
- const { getMappedProviderIds } = await import("./hooks-Q7KO2SGK.js");
1886
+ const { getMappedProviderIds } = await import("./hooks-VLIP52LY.js");
3427
1887
  const allIds = getMappedProviderIds();
3428
1888
  const translations = translateToAll(canonical, allIds);
3429
1889
  if (format === "json") {
@@ -3441,7 +1901,7 @@ CAMP Hook Support (mappings v${getHookMappingsVersion()})
3441
1901
  );
3442
1902
  console.log(JSON.stringify(envelope, null, 2));
3443
1903
  } else {
3444
- console.log(pc11.bold(`
1904
+ console.log(pc6.bold(`
3445
1905
  ${event} across providers:
3446
1906
  `));
3447
1907
  for (const id of allIds) {
@@ -3449,9 +1909,9 @@ CAMP Hook Support (mappings v${getHookMappingsVersion()})
3449
1909
  const provider = getProvider(id);
3450
1910
  const name = (provider?.toolName ?? id).padEnd(22);
3451
1911
  if (native) {
3452
- console.log(` ${pc11.green("\u2713")} ${name} ${pc11.bold(native)}`);
1912
+ console.log(` ${pc6.green("\u2713")} ${name} ${pc6.bold(native)}`);
3453
1913
  } else {
3454
- console.log(` ${pc11.dim("\xB7")} ${name} ${pc11.dim("not supported")}`);
1914
+ console.log(` ${pc6.dim("\xB7")} ${name} ${pc6.dim("not supported")}`);
3455
1915
  }
3456
1916
  }
3457
1917
  console.log();
@@ -3507,13 +1967,13 @@ CAMP Hook Support (mappings v${getHookMappingsVersion()})
3507
1967
  console.log(JSON.stringify(envelope, null, 2));
3508
1968
  return;
3509
1969
  }
3510
- console.log(pc11.bold("\nProvider Capability Matrix\n"));
1970
+ console.log(pc6.bold("\nProvider Capability Matrix\n"));
3511
1971
  if (opts.filter) {
3512
- console.log(pc11.dim(` Filter: ${opts.filter}
1972
+ console.log(pc6.dim(` Filter: ${opts.filter}
3513
1973
  `));
3514
1974
  }
3515
1975
  console.log(
3516
- ` ${pc11.bold("Provider".padEnd(22))} ${pc11.bold("Skills Precedence".padEnd(20))} ${pc11.bold("Hooks".padEnd(8))} ${pc11.bold("Spawn")}`
1976
+ ` ${pc6.bold("Provider".padEnd(22))} ${pc6.bold("Skills Precedence".padEnd(20))} ${pc6.bold("Hooks".padEnd(8))} ${pc6.bold("Spawn")}`
3517
1977
  );
3518
1978
  console.log(` ${"\u2500".repeat(22)} ${"\u2500".repeat(20)} ${"\u2500".repeat(8)} ${"\u2500".repeat(20)}`);
3519
1979
  for (const row of matrix) {
@@ -3523,7 +1983,7 @@ CAMP Hook Support (mappings v${getHookMappingsVersion()})
3523
1983
  ` ${row.toolName.padEnd(22)} ${row.skillsPrecedence.padEnd(20)} ${hooks2.padEnd(8)} ${spawn}`
3524
1984
  );
3525
1985
  }
3526
- console.log(pc11.dim(`
1986
+ console.log(pc6.dim(`
3527
1987
  ${matrix.length} providers shown`));
3528
1988
  console.log();
3529
1989
  });
@@ -3561,13 +2021,13 @@ function emitJsonError2(operation, mvi, code, message, category, details = {}) {
3561
2021
  }
3562
2022
 
3563
2023
  // src/commands/skills/audit.ts
3564
- import { existsSync as existsSync4, statSync } from "fs";
3565
- import pc12 from "picocolors";
2024
+ import { existsSync as existsSync3, statSync } from "fs";
2025
+ import pc7 from "picocolors";
3566
2026
  function registerSkillsAudit(parent) {
3567
2027
  parent.command("audit").description("Security scan skill files (46+ rules, SARIF output)").argument("[path]", "Path to SKILL.md or directory", ".").option("--sarif", "Output in SARIF format (raw SARIF, not LAFS envelope)").option("--json", "Output as JSON (LAFS envelope)").option("--human", "Output in human-readable format").action(async (path, opts) => {
3568
2028
  const operation = "skills.audit";
3569
2029
  const mvi = "standard";
3570
- if (!existsSync4(path)) {
2030
+ if (!existsSync3(path)) {
3571
2031
  const message = `Path not found: ${path}`;
3572
2032
  if (opts.sarif) {
3573
2033
  console.error(
@@ -3691,7 +2151,7 @@ function registerSkillsAudit(parent) {
3691
2151
  outputSuccess(operation, mvi, summary2);
3692
2152
  return;
3693
2153
  }
3694
- console.log(pc12.dim("No SKILL.md files found to scan."));
2154
+ console.log(pc7.dim("No SKILL.md files found to scan."));
3695
2155
  return;
3696
2156
  }
3697
2157
  const summary = {
@@ -3725,21 +2185,21 @@ function registerSkillsAudit(parent) {
3725
2185
  }
3726
2186
  let totalFindings = 0;
3727
2187
  for (const result of results) {
3728
- const icon = result.passed ? pc12.green("\u2713") : pc12.red("\u2717");
2188
+ const icon = result.passed ? pc7.green("\u2713") : pc7.red("\u2717");
3729
2189
  console.log(`
3730
- ${icon} ${pc12.bold(result.file)} (score: ${result.score}/100)`);
2190
+ ${icon} ${pc7.bold(result.file)} (score: ${result.score}/100)`);
3731
2191
  if (result.findings.length === 0) {
3732
- console.log(pc12.dim(" No issues found."));
2192
+ console.log(pc7.dim(" No issues found."));
3733
2193
  continue;
3734
2194
  }
3735
2195
  totalFindings += result.findings.length;
3736
2196
  for (const f of result.findings) {
3737
- const sev = f.rule.severity === "critical" ? pc12.red(f.rule.severity) : f.rule.severity === "high" ? pc12.red(f.rule.severity) : f.rule.severity === "medium" ? pc12.yellow(f.rule.severity) : pc12.dim(f.rule.severity);
2197
+ const sev = f.rule.severity === "critical" ? pc7.red(f.rule.severity) : f.rule.severity === "high" ? pc7.red(f.rule.severity) : f.rule.severity === "medium" ? pc7.yellow(f.rule.severity) : pc7.dim(f.rule.severity);
3738
2198
  console.log(` ${sev.padEnd(20)} ${f.rule.id} ${f.rule.name}`);
3739
- console.log(` ${pc12.dim(`L${f.line}: ${f.context.slice(0, 80)}`)}`);
2199
+ console.log(` ${pc7.dim(`L${f.line}: ${f.context.slice(0, 80)}`)}`);
3740
2200
  }
3741
2201
  }
3742
- console.log(pc12.bold(`
2202
+ console.log(pc7.bold(`
3743
2203
  ${results.length} file(s) scanned, ${totalFindings} finding(s)`));
3744
2204
  if (!allPassed) {
3745
2205
  process.exit(1);
@@ -3748,7 +2208,7 @@ ${results.length} file(s) scanned, ${totalFindings} finding(s)`));
3748
2208
  }
3749
2209
 
3750
2210
  // src/commands/skills/check.ts
3751
- import pc13 from "picocolors";
2211
+ import pc8 from "picocolors";
3752
2212
  function registerSkillsCheck(parent) {
3753
2213
  parent.command("check").description("Check for available skill updates").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(async (opts) => {
3754
2214
  const operation = "skills.check";
@@ -3781,12 +2241,12 @@ function registerSkillsCheck(parent) {
3781
2241
  total: 0
3782
2242
  });
3783
2243
  } else {
3784
- console.log(pc13.dim("No tracked skills."));
2244
+ console.log(pc8.dim("No tracked skills."));
3785
2245
  }
3786
2246
  return;
3787
2247
  }
3788
2248
  if (format === "human") {
3789
- console.log(pc13.dim(`Checking ${entries.length} skill(s) for updates...
2249
+ console.log(pc8.dim(`Checking ${entries.length} skill(s) for updates...
3790
2250
  `));
3791
2251
  }
3792
2252
  const skillResults = [];
@@ -3822,31 +2282,31 @@ function registerSkillsCheck(parent) {
3822
2282
  for (const r of skillResults) {
3823
2283
  let statusLabel;
3824
2284
  if (r.hasUpdate) {
3825
- statusLabel = pc13.yellow("update available");
2285
+ statusLabel = pc8.yellow("update available");
3826
2286
  } else if (r.currentVersion !== "unknown") {
3827
- statusLabel = pc13.green("up to date");
2287
+ statusLabel = pc8.green("up to date");
3828
2288
  } else {
3829
- statusLabel = pc13.dim("unknown");
2289
+ statusLabel = pc8.dim("unknown");
3830
2290
  }
3831
- console.log(` ${pc13.bold(r.name.padEnd(30))} ${statusLabel}`);
2291
+ console.log(` ${pc8.bold(r.name.padEnd(30))} ${statusLabel}`);
3832
2292
  if (r.currentVersion !== "unknown" || r.latestVersion !== "unknown") {
3833
2293
  const current = r.currentVersion !== "unknown" ? r.currentVersion.slice(0, 12) : "?";
3834
2294
  const latest = r.latestVersion !== "unknown" ? r.latestVersion : "?";
3835
2295
  if (r.hasUpdate) {
3836
- console.log(` ${pc13.dim("current:")} ${current} ${pc13.dim("->")} ${pc13.cyan(latest)}`);
2296
+ console.log(` ${pc8.dim("current:")} ${current} ${pc8.dim("->")} ${pc8.cyan(latest)}`);
3837
2297
  } else {
3838
- console.log(` ${pc13.dim("version:")} ${current}`);
2298
+ console.log(` ${pc8.dim("version:")} ${current}`);
3839
2299
  }
3840
2300
  }
3841
- console.log(` ${pc13.dim(`source: ${r.source}`)}`);
3842
- console.log(` ${pc13.dim(`agents: ${r.agents.join(", ")}`)}`);
2301
+ console.log(` ${pc8.dim(`source: ${r.source}`)}`);
2302
+ console.log(` ${pc8.dim(`agents: ${r.agents.join(", ")}`)}`);
3843
2303
  console.log();
3844
2304
  }
3845
2305
  if (updatesAvailable > 0) {
3846
- console.log(pc13.yellow(`${updatesAvailable} update(s) available.`));
3847
- console.log(pc13.dim("Run `caamp skills update` to update all."));
2306
+ console.log(pc8.yellow(`${updatesAvailable} update(s) available.`));
2307
+ console.log(pc8.dim("Run `caamp skills update` to update all."));
3848
2308
  } else {
3849
- console.log(pc13.green("All skills are up to date."));
2309
+ console.log(pc8.green("All skills are up to date."));
3850
2310
  }
3851
2311
  });
3852
2312
  }
@@ -3854,7 +2314,7 @@ function registerSkillsCheck(parent) {
3854
2314
  // src/commands/skills/find.ts
3855
2315
  import { randomUUID as randomUUID4 } from "crypto";
3856
2316
  import { resolveOutputFormat as resolveOutputFormat3 } from "@cleocode/lafs";
3857
- import pc14 from "picocolors";
2317
+ import pc9 from "picocolors";
3858
2318
  var SkillsFindValidationError = class extends Error {
3859
2319
  code;
3860
2320
  constructor(code, message) {
@@ -3895,7 +2355,7 @@ function registerSkillsFind(parent) {
3895
2355
  if (opts.json) {
3896
2356
  emitJsonError3(operation, mvi, "E_FORMAT_CONFLICT", message, "VALIDATION");
3897
2357
  } else {
3898
- console.error(pc14.red(message));
2358
+ console.error(pc9.red(message));
3899
2359
  }
3900
2360
  process.exit(1);
3901
2361
  }
@@ -3962,19 +2422,19 @@ function registerSkillsFind(parent) {
3962
2422
  query: query ?? null
3963
2423
  });
3964
2424
  } else {
3965
- console.error(pc14.red(`Recommendation failed: ${message}`));
2425
+ console.error(pc9.red(`Recommendation failed: ${message}`));
3966
2426
  }
3967
2427
  process.exit(1);
3968
2428
  }
3969
2429
  }
3970
2430
  if (!query) {
3971
- console.log(pc14.dim("Usage: caamp skills find <query>"));
2431
+ console.log(pc9.dim("Usage: caamp skills find <query>"));
3972
2432
  return;
3973
2433
  }
3974
2434
  const limit = parseInt(opts.limit, 10);
3975
2435
  const client = new MarketplaceClient();
3976
2436
  if (format === "human") {
3977
- console.log(pc14.dim(`Searching marketplaces for "${query}"...
2437
+ console.log(pc9.dim(`Searching marketplaces for "${query}"...
3978
2438
  `));
3979
2439
  }
3980
2440
  let results;
@@ -3988,7 +2448,7 @@ function registerSkillsFind(parent) {
3988
2448
  limit
3989
2449
  });
3990
2450
  } else {
3991
- console.error(pc14.red(`Marketplace search failed: ${message}`));
2451
+ console.error(pc9.red(`Marketplace search failed: ${message}`));
3992
2452
  }
3993
2453
  process.exit(1);
3994
2454
  }
@@ -4008,21 +2468,21 @@ function registerSkillsFind(parent) {
4008
2468
  return;
4009
2469
  }
4010
2470
  if (results.length === 0) {
4011
- console.log(pc14.yellow("No results found."));
2471
+ console.log(pc9.yellow("No results found."));
4012
2472
  return;
4013
2473
  }
4014
- console.log(pc14.dim(`Found ${results.length} result(s) for "${query}":
2474
+ console.log(pc9.dim(`Found ${results.length} result(s) for "${query}":
4015
2475
  `));
4016
2476
  results.forEach((skill, index) => {
4017
2477
  const num = (index + 1).toString().padStart(2);
4018
- const stars = skill.stars > 0 ? pc14.yellow(`\u2605 ${formatStars(skill.stars)}`) : "";
4019
- console.log(` ${pc14.cyan(num)}. ${pc14.bold(skill.scopedName)} ${stars}`);
4020
- console.log(` ${pc14.dim(skill.description?.slice(0, 80) ?? "")}`);
4021
- console.log(` ${pc14.dim(`from ${skill.source}`)}`);
2478
+ const stars = skill.stars > 0 ? pc9.yellow(`\u2605 ${formatStars(skill.stars)}`) : "";
2479
+ console.log(` ${pc9.cyan(num)}. ${pc9.bold(skill.scopedName)} ${stars}`);
2480
+ console.log(` ${pc9.dim(skill.description?.slice(0, 80) ?? "")}`);
2481
+ console.log(` ${pc9.dim(`from ${skill.source}`)}`);
4022
2482
  console.log();
4023
2483
  });
4024
- console.log(pc14.dim("Install with: caamp skills install <name>"));
4025
- console.log(pc14.dim("Or select by number: caamp skills install <n>"));
2484
+ console.log(pc9.dim("Install with: caamp skills install <name>"));
2485
+ console.log(pc9.dim("Or select by number: caamp skills install <n>"));
4026
2486
  });
4027
2487
  }
4028
2488
  function formatStars(n) {
@@ -4139,10 +2599,10 @@ function emitJsonError3(operation, mvi, code, message, category, details = {}) {
4139
2599
  }
4140
2600
 
4141
2601
  // src/commands/skills/init.ts
4142
- import { existsSync as existsSync5 } from "fs";
2602
+ import { existsSync as existsSync4 } from "fs";
4143
2603
  import { mkdir, writeFile } from "fs/promises";
4144
2604
  import { join as join3 } from "path";
4145
- import pc15 from "picocolors";
2605
+ import pc10 from "picocolors";
4146
2606
  function registerSkillsInit(parent) {
4147
2607
  parent.command("init").description("Create a new SKILL.md template").argument("[name]", "Skill name").option("-d, --dir <path>", "Output directory", ".").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(
4148
2608
  async (name, opts) => {
@@ -4168,7 +2628,7 @@ function registerSkillsInit(parent) {
4168
2628
  }
4169
2629
  const skillName = name ?? "my-skill";
4170
2630
  const skillDir = join3(opts.dir, skillName);
4171
- if (existsSync5(skillDir)) {
2631
+ if (existsSync4(skillDir)) {
4172
2632
  const message = `Directory already exists: ${skillDir}`;
4173
2633
  if (format === "json") {
4174
2634
  emitJsonError(
@@ -4182,7 +2642,7 @@ function registerSkillsInit(parent) {
4182
2642
  }
4183
2643
  );
4184
2644
  } else {
4185
- console.error(pc15.red(message));
2645
+ console.error(pc10.red(message));
4186
2646
  }
4187
2647
  process.exit(1);
4188
2648
  }
@@ -4221,18 +2681,18 @@ Show example inputs and expected outputs.
4221
2681
  outputSuccess(operation, mvi, result);
4222
2682
  return;
4223
2683
  }
4224
- console.log(pc15.green(`\u2713 Created skill template: ${skillDir}/SKILL.md`));
4225
- console.log(pc15.dim("\nNext steps:"));
4226
- console.log(pc15.dim(" 1. Edit SKILL.md with your instructions"));
4227
- console.log(pc15.dim(` 2. Validate: caamp skills validate ${join3(skillDir, "SKILL.md")}`));
4228
- console.log(pc15.dim(` 3. Install: caamp skills install ${skillDir}`));
2684
+ console.log(pc10.green(`\u2713 Created skill template: ${skillDir}/SKILL.md`));
2685
+ console.log(pc10.dim("\nNext steps:"));
2686
+ console.log(pc10.dim(" 1. Edit SKILL.md with your instructions"));
2687
+ console.log(pc10.dim(` 2. Validate: caamp skills validate ${join3(skillDir, "SKILL.md")}`));
2688
+ console.log(pc10.dim(` 3. Install: caamp skills install ${skillDir}`));
4229
2689
  }
4230
2690
  );
4231
2691
  }
4232
2692
 
4233
2693
  // src/commands/skills/install.ts
4234
- import { existsSync as existsSync6 } from "fs";
4235
- import pc16 from "picocolors";
2694
+ import { existsSync as existsSync5 } from "fs";
2695
+ import pc11 from "picocolors";
4236
2696
 
4237
2697
  // src/core/sources/github.ts
4238
2698
  import { mkdtemp, rm } from "fs/promises";
@@ -4337,7 +2797,7 @@ function registerSkillsInstall(parent) {
4337
2797
  ErrorCategories.NOT_FOUND
4338
2798
  );
4339
2799
  }
4340
- console.error(pc16.red(message));
2800
+ console.error(pc11.red(message));
4341
2801
  process.exit(1);
4342
2802
  }
4343
2803
  if (opts.profile) {
@@ -4362,14 +2822,14 @@ function registerSkillsInstall(parent) {
4362
2822
  ErrorCategories.VALIDATION
4363
2823
  );
4364
2824
  }
4365
- console.error(pc16.red(message));
2825
+ console.error(pc11.red(message));
4366
2826
  console.log(
4367
- pc16.dim("Usage: caamp skills install <source> or caamp skills install --profile <name>")
2827
+ pc11.dim("Usage: caamp skills install <source> or caamp skills install --profile <name>")
4368
2828
  );
4369
2829
  process.exit(1);
4370
2830
  }
4371
2831
  if (format === "human") {
4372
- console.log(pc16.dim(`Installing to ${providers.length} provider(s)...`));
2832
+ console.log(pc11.dim(`Installing to ${providers.length} provider(s)...`));
4373
2833
  }
4374
2834
  let localPath;
4375
2835
  let cleanup;
@@ -4415,7 +2875,7 @@ function registerSkillsInstall(parent) {
4415
2875
  ErrorCategories.TRANSIENT
4416
2876
  );
4417
2877
  }
4418
- console.error(pc16.red(message));
2878
+ console.error(pc11.red(message));
4419
2879
  process.exit(1);
4420
2880
  }
4421
2881
  } else if (parsed.type === "gitlab" && parsed.owner && parsed.repo) {
@@ -4439,7 +2899,7 @@ function registerSkillsInstall(parent) {
4439
2899
  ErrorCategories.TRANSIENT
4440
2900
  );
4441
2901
  }
4442
- console.error(pc16.red(message));
2902
+ console.error(pc11.red(message));
4443
2903
  process.exit(1);
4444
2904
  }
4445
2905
  } else if (parsed.type === "local") {
@@ -4460,7 +2920,7 @@ function registerSkillsInstall(parent) {
4460
2920
  ErrorCategories.VALIDATION
4461
2921
  );
4462
2922
  }
4463
- console.error(pc16.red(message));
2923
+ console.error(pc11.red(message));
4464
2924
  process.exit(1);
4465
2925
  }
4466
2926
  const catalogSkill = getSkill(parsed.inferredName);
@@ -4471,7 +2931,7 @@ function registerSkillsInstall(parent) {
4471
2931
  sourceType = "library";
4472
2932
  if (format === "human") {
4473
2933
  console.log(
4474
- ` Found in catalog: ${pc16.bold(catalogSkill.name)} v${catalogSkill.version} (${pc16.dim(catalogSkill.category)})`
2934
+ ` Found in catalog: ${pc11.bold(catalogSkill.name)} v${catalogSkill.version} (${pc11.dim(catalogSkill.category)})`
4475
2935
  );
4476
2936
  }
4477
2937
  } else {
@@ -4488,8 +2948,8 @@ function registerSkillsInstall(parent) {
4488
2948
  }
4489
2949
  );
4490
2950
  }
4491
- console.error(pc16.red(message));
4492
- console.log(pc16.dim("Available skills: " + listSkills().join(", ")));
2951
+ console.error(pc11.red(message));
2952
+ console.log(pc11.dim("Available skills: " + listSkills().join(", ")));
4493
2953
  process.exit(1);
4494
2954
  }
4495
2955
  } else {
@@ -4503,7 +2963,7 @@ function registerSkillsInstall(parent) {
4503
2963
  ErrorCategories.VALIDATION
4504
2964
  );
4505
2965
  }
4506
- console.error(pc16.red(message));
2966
+ console.error(pc11.red(message));
4507
2967
  process.exit(1);
4508
2968
  }
4509
2969
  }
@@ -4519,7 +2979,7 @@ function registerSkillsInstall(parent) {
4519
2979
  ErrorCategories.INTERNAL
4520
2980
  );
4521
2981
  }
4522
- console.error(pc16.red(message));
2982
+ console.error(pc11.red(message));
4523
2983
  process.exit(1);
4524
2984
  }
4525
2985
  const result = await installSkill(localPath, skillName, providers, opts.global ?? false);
@@ -4552,14 +3012,14 @@ function registerSkillsInstall(parent) {
4552
3012
  if (format === "json") {
4553
3013
  outputSuccess(operation, mvi, summary);
4554
3014
  } else {
4555
- console.log(pc16.green(`
4556
- \u2713 Installed ${pc16.bold(skillName)}`));
4557
- console.log(` Canonical: ${pc16.dim(result.canonicalPath)}`);
3015
+ console.log(pc11.green(`
3016
+ \u2713 Installed ${pc11.bold(skillName)}`));
3017
+ console.log(` Canonical: ${pc11.dim(result.canonicalPath)}`);
4558
3018
  console.log(` Linked to: ${result.linkedAgents.join(", ")}`);
4559
3019
  if (result.errors.length > 0) {
4560
- console.log(pc16.yellow("\nWarnings:"));
3020
+ console.log(pc11.yellow("\nWarnings:"));
4561
3021
  for (const err of result.errors) {
4562
- console.log(` ${pc16.yellow("!")} ${err}`);
3022
+ console.log(` ${pc11.yellow("!")} ${err}`);
4563
3023
  }
4564
3024
  }
4565
3025
  }
@@ -4589,11 +3049,11 @@ function registerSkillsInstall(parent) {
4589
3049
  });
4590
3050
  console.error(JSON.stringify(envelope, null, 2));
4591
3051
  } else {
4592
- console.log(pc16.yellow(`
4593
- \u2717 Failed to install ${pc16.bold(skillName)}`));
4594
- console.log(pc16.yellow("Errors:"));
3052
+ console.log(pc11.yellow(`
3053
+ \u2717 Failed to install ${pc11.bold(skillName)}`));
3054
+ console.log(pc11.yellow("Errors:"));
4595
3055
  for (const err of result.errors) {
4596
- console.log(` ${pc16.yellow("!")} ${err}`);
3056
+ console.log(` ${pc11.yellow("!")} ${err}`);
4597
3057
  }
4598
3058
  }
4599
3059
  process.exit(1);
@@ -4610,7 +3070,7 @@ async function handleProfileInstall(profileName, providers, isGlobal, format, op
4610
3070
  if (format === "json") {
4611
3071
  emitError2(operation, mvi, ErrorCodes.INVALID_INPUT, message, ErrorCategories.VALIDATION);
4612
3072
  }
4613
- console.error(pc16.red(message));
3073
+ console.error(pc11.red(message));
4614
3074
  process.exit(1);
4615
3075
  }
4616
3076
  const profileSkills = resolveProfile(profileName);
@@ -4628,16 +3088,16 @@ async function handleProfileInstall(profileName, providers, isGlobal, format, op
4628
3088
  }
4629
3089
  );
4630
3090
  }
4631
- console.error(pc16.red(message));
3091
+ console.error(pc11.red(message));
4632
3092
  const available = listProfiles();
4633
3093
  if (available.length > 0) {
4634
- console.log(pc16.dim("Available profiles: " + available.join(", ")));
3094
+ console.log(pc11.dim("Available profiles: " + available.join(", ")));
4635
3095
  }
4636
3096
  process.exit(1);
4637
3097
  }
4638
3098
  if (format === "human") {
4639
- console.log(`Installing profile ${pc16.bold(profileName)} (${profileSkills.length} skill(s))...`);
4640
- console.log(pc16.dim(`Target: ${providers.length} provider(s)`));
3099
+ console.log(`Installing profile ${pc11.bold(profileName)} (${profileSkills.length} skill(s))...`);
3100
+ console.log(pc11.dim(`Target: ${providers.length} provider(s)`));
4641
3101
  }
4642
3102
  const installed = [];
4643
3103
  const failed = [];
@@ -4647,7 +3107,7 @@ async function handleProfileInstall(profileName, providers, isGlobal, format, op
4647
3107
  const result = await installSkill(skillDir, name, providers, isGlobal);
4648
3108
  if (result.success) {
4649
3109
  if (format === "human") {
4650
- console.log(pc16.green(` + ${name}`));
3110
+ console.log(pc11.green(` + ${name}`));
4651
3111
  }
4652
3112
  await recordSkillInstall(
4653
3113
  name,
@@ -4666,7 +3126,7 @@ async function handleProfileInstall(profileName, providers, isGlobal, format, op
4666
3126
  });
4667
3127
  } else {
4668
3128
  if (format === "human") {
4669
- console.log(pc16.yellow(` ! ${name}: ${result.errors.join(", ")}`));
3129
+ console.log(pc11.yellow(` ! ${name}: ${result.errors.join(", ")}`));
4670
3130
  }
4671
3131
  failed.push({
4672
3132
  name,
@@ -4676,7 +3136,7 @@ async function handleProfileInstall(profileName, providers, isGlobal, format, op
4676
3136
  } catch (err) {
4677
3137
  const errorMsg = err instanceof Error ? err.message : String(err);
4678
3138
  if (format === "human") {
4679
- console.log(pc16.red(` x ${name}: ${errorMsg}`));
3139
+ console.log(pc11.red(` x ${name}: ${errorMsg}`));
4680
3140
  }
4681
3141
  failed.push({
4682
3142
  name,
@@ -4711,7 +3171,7 @@ async function handleProfileInstall(profileName, providers, isGlobal, format, op
4711
3171
  } else {
4712
3172
  console.log(
4713
3173
  `
4714
- ${pc16.green(`${installed.length} installed`)}, ${failed.length > 0 ? pc16.yellow(`${failed.length} failed`) : "0 failed"}`
3174
+ ${pc11.green(`${installed.length} installed`)}, ${failed.length > 0 ? pc11.yellow(`${failed.length} failed`) : "0 failed"}`
4715
3175
  );
4716
3176
  if (failed.length > 0) {
4717
3177
  process.exit(1);
@@ -4720,7 +3180,7 @@ ${pc16.green(`${installed.length} installed`)}, ${failed.length > 0 ? pc16.yello
4720
3180
  }
4721
3181
  async function handleMarketplaceSource(source, _providers, _isGlobal, format, operation, mvi) {
4722
3182
  if (format === "human") {
4723
- console.log(pc16.dim(`Searching marketplace for ${source}...`));
3183
+ console.log(pc11.dim(`Searching marketplace for ${source}...`));
4724
3184
  }
4725
3185
  const client = new MarketplaceClient();
4726
3186
  let skill;
@@ -4731,7 +3191,7 @@ async function handleMarketplaceSource(source, _providers, _isGlobal, format, op
4731
3191
  if (format === "json") {
4732
3192
  emitJsonError(operation, mvi, ErrorCodes.NETWORK_ERROR, message, ErrorCategories.TRANSIENT);
4733
3193
  }
4734
- console.error(pc16.red(message));
3194
+ console.error(pc11.red(message));
4735
3195
  return { success: false };
4736
3196
  }
4737
3197
  if (!skill) {
@@ -4739,12 +3199,12 @@ async function handleMarketplaceSource(source, _providers, _isGlobal, format, op
4739
3199
  if (format === "json") {
4740
3200
  emitJsonError(operation, mvi, ErrorCodes.SKILL_NOT_FOUND, message, ErrorCategories.NOT_FOUND);
4741
3201
  }
4742
- console.error(pc16.red(message));
3202
+ console.error(pc11.red(message));
4743
3203
  return { success: false };
4744
3204
  }
4745
3205
  if (format === "human") {
4746
3206
  console.log(
4747
- ` Found: ${pc16.bold(skill.name)} by ${skill.author} (${pc16.dim(skill.repoFullName)})`
3207
+ ` Found: ${pc11.bold(skill.name)} by ${skill.author} (${pc11.dim(skill.repoFullName)})`
4748
3208
  );
4749
3209
  }
4750
3210
  const parsed = parseSource(skill.githubUrl);
@@ -4753,7 +3213,7 @@ async function handleMarketplaceSource(source, _providers, _isGlobal, format, op
4753
3213
  if (format === "json") {
4754
3214
  emitJsonError(operation, mvi, ErrorCodes.INVALID_FORMAT, message, ErrorCategories.VALIDATION);
4755
3215
  }
4756
- console.error(pc16.red(message));
3216
+ console.error(pc11.red(message));
4757
3217
  return { success: false };
4758
3218
  }
4759
3219
  try {
@@ -4765,7 +3225,7 @@ async function handleMarketplaceSource(source, _providers, _isGlobal, format, op
4765
3225
  for (const subPath of subPathCandidates) {
4766
3226
  try {
4767
3227
  const result = await cloneRepo(parsed.owner, parsed.repo, parsed.ref, subPath);
4768
- if (subPath && !existsSync6(result.localPath)) {
3228
+ if (subPath && !existsSync5(result.localPath)) {
4769
3229
  await result.cleanup();
4770
3230
  continue;
4771
3231
  }
@@ -4793,7 +3253,7 @@ async function handleMarketplaceSource(source, _providers, _isGlobal, format, op
4793
3253
  if (format === "json") {
4794
3254
  emitJsonError(operation, mvi, ErrorCodes.NETWORK_ERROR, message, ErrorCategories.TRANSIENT);
4795
3255
  }
4796
- console.error(pc16.red(message));
3256
+ console.error(pc11.red(message));
4797
3257
  return { success: false };
4798
3258
  }
4799
3259
  }
@@ -4801,7 +3261,7 @@ async function handleMarketplaceSource(source, _providers, _isGlobal, format, op
4801
3261
  // src/commands/skills/list.ts
4802
3262
  import { randomUUID as randomUUID5 } from "crypto";
4803
3263
  import { resolveOutputFormat as resolveOutputFormat4 } from "@cleocode/lafs";
4804
- import pc17 from "picocolors";
3264
+ import pc12 from "picocolors";
4805
3265
  function registerSkillsList(parent) {
4806
3266
  parent.command("list").description("List installed skills").option("-g, --global", "List global skills").option("-a, --agent <name>", "List skills for specific agent").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(async (opts) => {
4807
3267
  const operation = "skills.list";
@@ -4828,7 +3288,7 @@ function registerSkillsList(parent) {
4828
3288
  agent: opts.agent
4829
3289
  });
4830
3290
  } else {
4831
- console.error(pc17.red(message));
3291
+ console.error(pc12.red(message));
4832
3292
  }
4833
3293
  process.exit(1);
4834
3294
  }
@@ -4856,21 +3316,21 @@ function registerSkillsList(parent) {
4856
3316
  return;
4857
3317
  }
4858
3318
  if (skills.length === 0) {
4859
- console.log(pc17.dim("No skills found."));
3319
+ console.log(pc12.dim("No skills found."));
4860
3320
  return;
4861
3321
  }
4862
- console.log(pc17.bold(`
3322
+ console.log(pc12.bold(`
4863
3323
  ${skills.length} skill(s) found:
4864
3324
  `));
4865
3325
  skills.forEach((skill, index) => {
4866
3326
  const num = (index + 1).toString().padStart(2);
4867
3327
  console.log(
4868
- ` ${pc17.cyan(num)}. ${pc17.bold(skill.name.padEnd(30))} ${pc17.dim(skill.metadata?.description ?? "")}`
3328
+ ` ${pc12.cyan(num)}. ${pc12.bold(skill.name.padEnd(30))} ${pc12.dim(skill.metadata?.description ?? "")}`
4869
3329
  );
4870
3330
  });
4871
- console.log(pc17.dim(`
3331
+ console.log(pc12.dim(`
4872
3332
  Install with: caamp skills install <name>`));
4873
- console.log(pc17.dim(`Remove with: caamp skills remove <name>`));
3333
+ console.log(pc12.dim(`Remove with: caamp skills remove <name>`));
4874
3334
  });
4875
3335
  }
4876
3336
  function buildEnvelope4(operation, mvi, result, error) {
@@ -4906,7 +3366,7 @@ function emitJsonError4(operation, mvi, code, message, category, details = {}) {
4906
3366
  }
4907
3367
 
4908
3368
  // src/commands/skills/remove.ts
4909
- import pc18 from "picocolors";
3369
+ import pc13 from "picocolors";
4910
3370
  function registerSkillsRemove(parent) {
4911
3371
  parent.command("remove").description("Remove installed skill(s)").argument("[name]", "Skill name to remove").option("-g, --global", "Remove from global scope").option("-y, --yes", "Skip confirmation").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(
4912
3372
  async (name, opts) => {
@@ -4952,14 +3412,14 @@ function registerSkillsRemove(parent) {
4952
3412
  return;
4953
3413
  }
4954
3414
  if (removed.length > 0) {
4955
- console.log(pc18.green(`\u2713 Removed ${pc18.bold(name)} from: ${removed.join(", ")}`));
3415
+ console.log(pc13.green(`\u2713 Removed ${pc13.bold(name)} from: ${removed.join(", ")}`));
4956
3416
  await removeSkillFromLock(name);
4957
3417
  } else {
4958
- console.log(pc18.yellow(`Skill ${name} not found in any provider.`));
3418
+ console.log(pc13.yellow(`Skill ${name} not found in any provider.`));
4959
3419
  }
4960
3420
  if (result.errors.length > 0) {
4961
3421
  for (const err of result.errors) {
4962
- console.log(pc18.red(` ${err}`));
3422
+ console.log(pc13.red(` ${err}`));
4963
3423
  }
4964
3424
  }
4965
3425
  } else {
@@ -4972,7 +3432,7 @@ function registerSkillsRemove(parent) {
4972
3432
  count: { removed: 0, total: 0 }
4973
3433
  });
4974
3434
  } else {
4975
- console.log(pc18.dim("No skills installed."));
3435
+ console.log(pc13.dim("No skills installed."));
4976
3436
  }
4977
3437
  return;
4978
3438
  }
@@ -4985,18 +3445,18 @@ function registerSkillsRemove(parent) {
4985
3445
  });
4986
3446
  return;
4987
3447
  }
4988
- console.log(pc18.bold("Installed skills:"));
3448
+ console.log(pc13.bold("Installed skills:"));
4989
3449
  for (const s of skills) {
4990
3450
  console.log(` ${s}`);
4991
3451
  }
4992
- console.log(pc18.dim("\nUse: caamp skills remove <name>"));
3452
+ console.log(pc13.dim("\nUse: caamp skills remove <name>"));
4993
3453
  }
4994
3454
  }
4995
3455
  );
4996
3456
  }
4997
3457
 
4998
3458
  // src/commands/skills/update.ts
4999
- import pc19 from "picocolors";
3459
+ import pc14 from "picocolors";
5000
3460
  function registerSkillsUpdate(parent) {
5001
3461
  parent.command("update").description("Update all outdated skills").option("-y, --yes", "Skip confirmation").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(async (opts) => {
5002
3462
  const operation = "skills.update";
@@ -5030,12 +3490,12 @@ function registerSkillsUpdate(parent) {
5030
3490
  count: { updated: 0, failed: 0, skipped: 0 }
5031
3491
  });
5032
3492
  } else {
5033
- console.log(pc19.dim("No tracked skills to update."));
3493
+ console.log(pc14.dim("No tracked skills to update."));
5034
3494
  }
5035
3495
  return;
5036
3496
  }
5037
3497
  if (format === "human") {
5038
- console.log(pc19.dim(`Checking ${entries.length} skill(s) for updates...`));
3498
+ console.log(pc14.dim(`Checking ${entries.length} skill(s) for updates...`));
5039
3499
  }
5040
3500
  const outdated = [];
5041
3501
  for (const [name] of entries) {
@@ -5057,19 +3517,19 @@ function registerSkillsUpdate(parent) {
5057
3517
  count: { updated: 0, failed: 0, skipped: 0 }
5058
3518
  });
5059
3519
  } else {
5060
- console.log(pc19.green("\nAll skills are up to date."));
3520
+ console.log(pc14.green("\nAll skills are up to date."));
5061
3521
  }
5062
3522
  return;
5063
3523
  }
5064
3524
  if (format === "human") {
5065
- console.log(pc19.yellow(`
3525
+ console.log(pc14.yellow(`
5066
3526
  ${outdated.length} skill(s) have updates available:
5067
3527
  `));
5068
3528
  for (const skill of outdated) {
5069
3529
  const current = skill.currentVersion?.slice(0, 12) ?? "?";
5070
3530
  const latest = skill.latestVersion ?? "?";
5071
3531
  console.log(
5072
- ` ${pc19.bold(skill.name)} ${pc19.dim(current)} ${pc19.dim("->")} ${pc19.cyan(latest)}`
3532
+ ` ${pc14.bold(skill.name)} ${pc14.dim(current)} ${pc14.dim("->")} ${pc14.cyan(latest)}`
5073
3533
  );
5074
3534
  }
5075
3535
  }
@@ -5077,11 +3537,11 @@ ${outdated.length} skill(s) have updates available:
5077
3537
  const readline = await import("readline");
5078
3538
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
5079
3539
  const answer = await new Promise((resolve) => {
5080
- rl.question(pc19.dim("\nProceed with update? [y/N] "), resolve);
3540
+ rl.question(pc14.dim("\nProceed with update? [y/N] "), resolve);
5081
3541
  });
5082
3542
  rl.close();
5083
3543
  if (answer.toLowerCase() !== "y" && answer.toLowerCase() !== "yes") {
5084
- console.log(pc19.dim("Update cancelled."));
3544
+ console.log(pc14.dim("Update cancelled."));
5085
3545
  return;
5086
3546
  }
5087
3547
  }
@@ -5095,7 +3555,7 @@ ${outdated.length} skill(s) have updates available:
5095
3555
  const entry = tracked[skill.name];
5096
3556
  if (!entry) continue;
5097
3557
  if (format === "human") {
5098
- console.log(pc19.dim(`Updating ${pc19.bold(skill.name)}...`));
3558
+ console.log(pc14.dim(`Updating ${pc14.bold(skill.name)}...`));
5099
3559
  }
5100
3560
  try {
5101
3561
  const parsed = parseSource(entry.source);
@@ -5117,7 +3577,7 @@ ${outdated.length} skill(s) have updates available:
5117
3577
  } else {
5118
3578
  if (format === "human") {
5119
3579
  console.log(
5120
- pc19.yellow(
3580
+ pc14.yellow(
5121
3581
  ` Skipped ${skill.name}: source type "${parsed.type}" does not support auto-update`
5122
3582
  )
5123
3583
  );
@@ -5129,7 +3589,7 @@ ${outdated.length} skill(s) have updates available:
5129
3589
  const providers = entry.agents.map((a) => getProvider(a)).filter((p) => p !== void 0);
5130
3590
  if (providers.length === 0) {
5131
3591
  if (format === "human") {
5132
- console.log(pc19.yellow(` Skipped ${skill.name}: no valid providers found`));
3592
+ console.log(pc14.yellow(` Skipped ${skill.name}: no valid providers found`));
5133
3593
  }
5134
3594
  skipped.push(skill.name);
5135
3595
  continue;
@@ -5154,18 +3614,18 @@ ${outdated.length} skill(s) have updates available:
5154
3614
  skill.latestVersion
5155
3615
  );
5156
3616
  if (format === "human") {
5157
- console.log(pc19.green(` Updated ${pc19.bold(skill.name)}`));
3617
+ console.log(pc14.green(` Updated ${pc14.bold(skill.name)}`));
5158
3618
  }
5159
3619
  updated.push(skill.name);
5160
3620
  } else {
5161
3621
  if (format === "human") {
5162
- console.log(pc19.red(` Failed to update ${skill.name}: no agents linked`));
3622
+ console.log(pc14.red(` Failed to update ${skill.name}: no agents linked`));
5163
3623
  }
5164
3624
  failed.push({ name: skill.name, error: "no agents linked" });
5165
3625
  }
5166
3626
  if (installResult.errors.length > 0 && format === "human") {
5167
3627
  for (const err of installResult.errors) {
5168
- console.log(pc19.yellow(` ${err}`));
3628
+ console.log(pc14.yellow(` ${err}`));
5169
3629
  }
5170
3630
  }
5171
3631
  } finally {
@@ -5174,7 +3634,7 @@ ${outdated.length} skill(s) have updates available:
5174
3634
  } catch (err) {
5175
3635
  const msg = err instanceof Error ? err.message : String(err);
5176
3636
  if (format === "human") {
5177
- console.log(pc19.red(` Failed to update ${skill.name}: ${msg}`));
3637
+ console.log(pc14.red(` Failed to update ${skill.name}: ${msg}`));
5178
3638
  }
5179
3639
  failed.push({ name: skill.name, error: msg });
5180
3640
  }
@@ -5194,17 +3654,17 @@ ${outdated.length} skill(s) have updates available:
5194
3654
  }
5195
3655
  console.log();
5196
3656
  if (updated.length > 0) {
5197
- console.log(pc19.green(`Updated ${updated.length} skill(s).`));
3657
+ console.log(pc14.green(`Updated ${updated.length} skill(s).`));
5198
3658
  }
5199
3659
  if (failed.length > 0) {
5200
- console.log(pc19.red(`Failed to update ${failed.length} skill(s).`));
3660
+ console.log(pc14.red(`Failed to update ${failed.length} skill(s).`));
5201
3661
  }
5202
3662
  });
5203
3663
  }
5204
3664
 
5205
3665
  // src/commands/skills/validate.ts
5206
3666
  import { resolveOutputFormat as resolveOutputFormat5 } from "@cleocode/lafs";
5207
- import pc20 from "picocolors";
3667
+ import pc15 from "picocolors";
5208
3668
  function registerSkillsValidate(parent) {
5209
3669
  parent.command("validate").description("Validate SKILL.md format").argument("[path]", "Path to SKILL.md", "SKILL.md").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(async (path, opts) => {
5210
3670
  const operation = "skills.validate";
@@ -5244,7 +3704,7 @@ function registerSkillsValidate(parent) {
5244
3704
  }
5245
3705
  );
5246
3706
  } else {
5247
- console.error(pc20.red(message));
3707
+ console.error(pc15.red(message));
5248
3708
  }
5249
3709
  process.exit(1);
5250
3710
  }
@@ -5266,12 +3726,12 @@ function registerSkillsValidate(parent) {
5266
3726
  console.log(JSON.stringify(envelope, null, 2));
5267
3727
  } else {
5268
3728
  if (result.valid) {
5269
- console.log(pc20.green(`\u2713 ${path} is valid`));
3729
+ console.log(pc15.green(`\u2713 ${path} is valid`));
5270
3730
  } else {
5271
- console.log(pc20.red(`\u2717 ${path} has validation errors`));
3731
+ console.log(pc15.red(`\u2717 ${path} has validation errors`));
5272
3732
  }
5273
3733
  for (const issue of result.issues) {
5274
- const icon = issue.level === "error" ? pc20.red("\u2717") : pc20.yellow("!");
3734
+ const icon = issue.level === "error" ? pc15.red("\u2717") : pc15.yellow("!");
5275
3735
  console.log(` ${icon} [${issue.field}] ${issue.message}`);
5276
3736
  }
5277
3737
  }
@@ -5306,8 +3766,6 @@ program.hook("preAction", (thisCommand) => {
5306
3766
  });
5307
3767
  registerProvidersCommand(program);
5308
3768
  registerSkillsCommands(program);
5309
- registerMcpCommands(program);
5310
- registerCleoCommands(program);
5311
3769
  registerInstructionsCommands(program);
5312
3770
  registerConfigCommand(program);
5313
3771
  registerDoctorCommand(program);