@cleocode/caamp 1.1.2 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -65,7 +65,7 @@ import {
65
65
  tokenizeCriteriaValue,
66
66
  updateInstructionsSingleOperation,
67
67
  validateSkill
68
- } from "./chunk-7YV3KXEJ.js";
68
+ } from "./chunk-GR47LTXR.js";
69
69
 
70
70
  // src/cli.ts
71
71
  import { Command } from "commander";
@@ -1601,10 +1601,668 @@ function registerInstructionsCommands(program2) {
1601
1601
  registerInstructionsUpdate(instructions);
1602
1602
  }
1603
1603
 
1604
- // src/commands/mcp/install.ts
1604
+ // src/commands/mcp/cleo.ts
1605
+ import { createInterface } from "readline/promises";
1605
1606
  import pc6 from "picocolors";
1607
+
1608
+ // src/core/mcp/cleo.ts
1609
+ import { execFileSync as execFileSync2 } from "child_process";
1610
+ import { existsSync as existsSync3 } from "fs";
1611
+ import { homedir as homedir2 } from "os";
1612
+ import { isAbsolute, resolve } from "path";
1613
+ var CLEO_SERVER_NAMES = {
1614
+ stable: "cleo",
1615
+ beta: "cleo-beta",
1616
+ dev: "cleo-dev"
1617
+ };
1618
+ var CLEO_MCP_NPM_PACKAGE = "@cleocode/cleo";
1619
+ var CLEO_DEV_DIR_DEFAULT = "~/.cleo-dev";
1620
+ function normalizeCleoChannel(value) {
1621
+ if (!value || value.trim() === "") return "stable";
1622
+ const normalized = value.trim().toLowerCase();
1623
+ if (normalized === "stable" || normalized === "beta" || normalized === "dev") {
1624
+ return normalized;
1625
+ }
1626
+ throw new Error(`Invalid channel "${value}". Expected stable, beta, or dev.`);
1627
+ }
1628
+ function resolveCleoServerName(channel) {
1629
+ return CLEO_SERVER_NAMES[channel];
1630
+ }
1631
+ function resolveChannelFromServerName(serverName) {
1632
+ if (serverName === CLEO_SERVER_NAMES.stable) return "stable";
1633
+ if (serverName === CLEO_SERVER_NAMES.beta) return "beta";
1634
+ if (serverName === CLEO_SERVER_NAMES.dev) return "dev";
1635
+ return null;
1636
+ }
1637
+ function splitCommand(command, explicitArgs = []) {
1638
+ if (explicitArgs.length > 0) {
1639
+ return { command, args: explicitArgs };
1640
+ }
1641
+ const parts = command.trim().split(/\s+/);
1642
+ const binary = parts[0] ?? "";
1643
+ if (!binary) {
1644
+ throw new Error("Command is required for dev channel.");
1645
+ }
1646
+ return {
1647
+ command: binary,
1648
+ args: parts.slice(1)
1649
+ };
1650
+ }
1651
+ function normalizeEnv(env, channel, cleoDir) {
1652
+ const result = { ...env ?? {} };
1653
+ if (channel === "dev" && !result.CLEO_DIR) {
1654
+ result.CLEO_DIR = cleoDir ?? CLEO_DEV_DIR_DEFAULT;
1655
+ }
1656
+ return Object.keys(result).length > 0 ? result : void 0;
1657
+ }
1658
+ function resolvePackageSpec(channel, version) {
1659
+ const tag = version?.trim() || (channel === "stable" ? "latest" : "beta");
1660
+ return `${CLEO_MCP_NPM_PACKAGE}@${tag}`;
1661
+ }
1662
+ function buildCleoProfile(options) {
1663
+ const channel = options.channel;
1664
+ const serverName = resolveCleoServerName(channel);
1665
+ if (channel === "dev") {
1666
+ if (!options.command || options.command.trim() === "") {
1667
+ throw new Error("Dev channel requires --command.");
1668
+ }
1669
+ const parsed = splitCommand(options.command, options.args ?? []);
1670
+ const env = normalizeEnv(options.env, channel, options.cleoDir);
1671
+ return {
1672
+ channel,
1673
+ serverName,
1674
+ config: {
1675
+ command: parsed.command,
1676
+ args: parsed.args,
1677
+ ...env ? { env } : {}
1678
+ }
1679
+ };
1680
+ }
1681
+ const packageSpec = resolvePackageSpec(channel, options.version);
1682
+ return {
1683
+ channel,
1684
+ serverName,
1685
+ packageSpec,
1686
+ config: {
1687
+ command: "npx",
1688
+ args: ["-y", packageSpec, "cleo-mcp"]
1689
+ }
1690
+ };
1691
+ }
1692
+ function expandHome(pathValue) {
1693
+ if (pathValue === "~") return homedir2();
1694
+ if (pathValue.startsWith("~/")) {
1695
+ return resolve(homedir2(), pathValue.slice(2));
1696
+ }
1697
+ return pathValue;
1698
+ }
1699
+ function checkCommandReachability(command) {
1700
+ const hasPathSeparator = command.includes("/") || command.includes("\\");
1701
+ if (hasPathSeparator || command.startsWith("~")) {
1702
+ const expanded = expandHome(command);
1703
+ const candidate = isAbsolute(expanded) ? expanded : resolve(process.cwd(), expanded);
1704
+ if (existsSync3(candidate)) {
1705
+ return { reachable: true, method: "path", detail: candidate };
1706
+ }
1707
+ return { reachable: false, method: "path", detail: candidate };
1708
+ }
1709
+ try {
1710
+ const lookup = process.platform === "win32" ? "where" : "which";
1711
+ execFileSync2(lookup, [command], { stdio: "pipe" });
1712
+ return { reachable: true, method: "lookup", detail: command };
1713
+ } catch {
1714
+ return { reachable: false, method: "lookup", detail: command };
1715
+ }
1716
+ }
1717
+ function parseEnvAssignments(values) {
1718
+ const env = {};
1719
+ for (const value of values) {
1720
+ const idx = value.indexOf("=");
1721
+ if (idx <= 0) {
1722
+ throw new Error(`Invalid --env value "${value}". Use KEY=value.`);
1723
+ }
1724
+ const key = value.slice(0, idx).trim();
1725
+ const val = value.slice(idx + 1).trim();
1726
+ if (!key) {
1727
+ throw new Error(`Invalid --env value "${value}". Key cannot be empty.`);
1728
+ }
1729
+ env[key] = val;
1730
+ }
1731
+ return env;
1732
+ }
1733
+
1734
+ // src/commands/mcp/cleo.ts
1735
+ function collect(value, previous) {
1736
+ return [...previous, value];
1737
+ }
1738
+ function collectTargetProviders(providerIds, all) {
1739
+ if (all) {
1740
+ return getInstalledProviders();
1741
+ }
1742
+ if (providerIds.length > 0) {
1743
+ return providerIds.map((id) => getProvider(id)).filter((provider) => provider !== void 0);
1744
+ }
1745
+ return getInstalledProviders();
1746
+ }
1747
+ async function validateProfile(provider, scope, serverName) {
1748
+ const entries = await listMcpServers(provider, scope);
1749
+ const entry = entries.find((candidate) => candidate.name === serverName);
1750
+ if (!entry) {
1751
+ return { valid: false, reason: "server missing after write" };
1752
+ }
1753
+ const command = typeof entry.config.command === "string" ? entry.config.command : void 0;
1754
+ if (!command) {
1755
+ return { valid: true };
1756
+ }
1757
+ const reachability = checkCommandReachability(command);
1758
+ if (!reachability.reachable) {
1759
+ return {
1760
+ valid: false,
1761
+ reason: `command not reachable (${reachability.method}: ${reachability.detail})`
1762
+ };
1763
+ }
1764
+ return { valid: true };
1765
+ }
1766
+ async function detectServerConflicts(providers, scope, targetServerName) {
1767
+ const warnings = [];
1768
+ for (const provider of providers) {
1769
+ const entries = await listMcpServers(provider, scope);
1770
+ const existing = entries.find((entry) => entry.name === targetServerName);
1771
+ if (!existing) continue;
1772
+ const command = typeof existing.config.command === "string" ? existing.config.command : "";
1773
+ const args = Array.isArray(existing.config.args) ? existing.config.args.filter((value) => typeof value === "string") : [];
1774
+ const flat = `${command} ${args.join(" ")}`.toLowerCase();
1775
+ if (!flat.includes("cleo")) {
1776
+ warnings.push({
1777
+ providerId: provider.id,
1778
+ message: `Server name '${targetServerName}' already exists with a non-CLEO command in ${provider.id}.`
1779
+ });
1780
+ }
1781
+ }
1782
+ return warnings;
1783
+ }
1784
+ function formatInstallResultHuman(mode, channel, serverName, scope, results, validations) {
1785
+ console.log(pc6.bold(`${mode === "install" ? "Install" : "Update"} CLEO channel: ${channel}`));
1786
+ console.log(pc6.dim(`Server: ${serverName} Scope: ${scope}`));
1787
+ console.log();
1788
+ for (const result of results) {
1789
+ const validation = validations.find((entry) => entry.providerId === result.provider.id);
1790
+ if (result.success) {
1791
+ const validationLabel = validation?.valid ? pc6.green("validated") : pc6.yellow(`validation warning: ${validation?.reason ?? "unknown"}`);
1792
+ console.log(` ${pc6.green("+")} ${result.provider.toolName.padEnd(22)} ${pc6.dim(result.configPath)} ${validationLabel}`);
1793
+ } else {
1794
+ console.log(` ${pc6.red("x")} ${result.provider.toolName.padEnd(22)} ${pc6.red(result.error ?? "failed")}`);
1795
+ console.log(pc6.dim(" Recovery: verify config path permissions and retry with --dry-run."));
1796
+ }
1797
+ }
1798
+ console.log();
1799
+ }
1800
+ async function runInteractiveInstall(opts) {
1801
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
1802
+ try {
1803
+ const discovered = getInstalledProviders();
1804
+ if (discovered.length === 0) {
1805
+ throw new Error("No installed providers were detected for interactive setup.");
1806
+ }
1807
+ console.log(pc6.bold("CLEO MCP Setup"));
1808
+ console.log(pc6.dim("Step 1/6 - Select provider(s)"));
1809
+ for (const [index, provider] of discovered.entries()) {
1810
+ console.log(` ${index + 1}. ${provider.id} (${provider.toolName})`);
1811
+ }
1812
+ const providerAnswer = await rl.question(pc6.dim("Choose providers (e.g. 1,2 or all): "));
1813
+ 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));
1814
+ if (selectedProviders.length === 0) {
1815
+ throw new Error("No providers selected.");
1816
+ }
1817
+ console.log();
1818
+ console.log(pc6.dim("Step 2/6 - Select channel"));
1819
+ const channelAnswer = await rl.question(pc6.dim("Channel [stable/beta/dev] (stable): "));
1820
+ const selectedChannel = normalizeCleoChannel(channelAnswer || "stable");
1821
+ let command = opts.command;
1822
+ let args = [...opts.arg];
1823
+ let env = [...opts.env];
1824
+ let cleoDir = opts.cleoDir;
1825
+ if (selectedChannel === "dev") {
1826
+ command = await rl.question(pc6.dim("Dev command (required): "));
1827
+ const argsAnswer = await rl.question(pc6.dim("Dev args (space-separated, optional): "));
1828
+ args = argsAnswer.trim() === "" ? [] : argsAnswer.trim().split(/\s+/);
1829
+ const dirAnswer = await rl.question(pc6.dim("CLEO_DIR (~/.cleo-dev default): "));
1830
+ cleoDir = dirAnswer.trim() === "" ? "~/.cleo-dev" : dirAnswer.trim();
1831
+ if (cleoDir.trim() !== "") {
1832
+ env = [
1833
+ ...env.filter((entry) => !entry.startsWith("CLEO_DIR=")),
1834
+ `CLEO_DIR=${cleoDir}`
1835
+ ];
1836
+ }
1837
+ }
1838
+ const profile = buildCleoProfile({
1839
+ channel: selectedChannel,
1840
+ version: opts.version,
1841
+ command,
1842
+ args,
1843
+ env: parseEnvAssignments(env),
1844
+ cleoDir
1845
+ });
1846
+ console.log();
1847
+ console.log(pc6.dim("Step 3/6 - Preview profile diff"));
1848
+ console.log(` Server: ${pc6.bold(profile.serverName)}`);
1849
+ console.log(` Channel: ${selectedChannel}`);
1850
+ console.log(` Config: ${JSON.stringify(profile.config)}`);
1851
+ console.log();
1852
+ console.log(pc6.dim("Step 4/6 - Confirm apply"));
1853
+ const confirm = await rl.question(pc6.dim("Apply this configuration? [y/N] "));
1854
+ if (!["y", "yes"].includes(confirm.trim().toLowerCase())) {
1855
+ throw new Error("Cancelled by user.");
1856
+ }
1857
+ return {
1858
+ ...opts,
1859
+ provider: selectedProviders,
1860
+ channel: selectedChannel,
1861
+ command,
1862
+ arg: args,
1863
+ env,
1864
+ cleoDir,
1865
+ yes: true
1866
+ };
1867
+ } finally {
1868
+ rl.close();
1869
+ }
1870
+ }
1871
+ async function executeCleoInstall(mode, opts, operation) {
1872
+ const mvi = "standard";
1873
+ let format;
1874
+ try {
1875
+ format = resolveFormat({
1876
+ jsonFlag: opts.json ?? false,
1877
+ humanFlag: (opts.human ?? false) || isHuman(),
1878
+ projectDefault: "json"
1879
+ });
1880
+ } catch (error) {
1881
+ const message = error instanceof Error ? error.message : String(error);
1882
+ emitJsonError(operation, mvi, ErrorCodes.FORMAT_CONFLICT, message, ErrorCategories.VALIDATION);
1883
+ process.exit(1);
1884
+ }
1885
+ const interactive = (opts.interactive ?? false) && format === "human";
1886
+ const resolvedOpts = interactive ? await runInteractiveInstall(opts) : opts;
1887
+ const channel = normalizeCleoChannel(resolvedOpts.channel);
1888
+ const providers = collectTargetProviders(resolvedOpts.provider, resolvedOpts.all);
1889
+ if (providers.length === 0) {
1890
+ const message = "No target providers found.";
1891
+ if (format === "json") {
1892
+ emitJsonError(operation, mvi, ErrorCodes.PROVIDER_NOT_FOUND, message, ErrorCategories.NOT_FOUND);
1893
+ } else {
1894
+ console.error(pc6.red(message));
1895
+ }
1896
+ process.exit(1);
1897
+ }
1898
+ const envMap = parseEnvAssignments(resolvedOpts.env);
1899
+ const profile = buildCleoProfile({
1900
+ channel,
1901
+ version: resolvedOpts.version,
1902
+ command: resolvedOpts.command,
1903
+ args: resolvedOpts.arg,
1904
+ env: envMap,
1905
+ cleoDir: resolvedOpts.cleoDir
1906
+ });
1907
+ const scope = resolvedOpts.global ? "global" : "project";
1908
+ if (resolvedOpts.dryRun) {
1909
+ if (format === "human") {
1910
+ console.log(pc6.bold(`Dry run: ${mode} CLEO (${channel})`));
1911
+ console.log(pc6.dim(`Server: ${profile.serverName} Scope: ${scope}`));
1912
+ console.log(pc6.dim(`Providers: ${providers.map((provider) => provider.id).join(", ")}`));
1913
+ console.log(pc6.dim(`Command: ${profile.config.command ?? "(none)"} ${(profile.config.args ?? []).join(" ")}`));
1914
+ if (profile.config.env && Object.keys(profile.config.env).length > 0) {
1915
+ console.log(pc6.dim(`Env: ${JSON.stringify(profile.config.env)}`));
1916
+ }
1917
+ } else {
1918
+ outputSuccess(operation, mvi, {
1919
+ action: mode,
1920
+ channel,
1921
+ serverName: profile.serverName,
1922
+ providers: providers.map((provider) => provider.id),
1923
+ scope,
1924
+ command: profile.config.command,
1925
+ args: profile.config.args ?? [],
1926
+ env: profile.config.env ?? {},
1927
+ packageSpec: profile.packageSpec,
1928
+ dryRun: true
1929
+ });
1930
+ }
1931
+ return;
1932
+ }
1933
+ const conflictWarnings = await detectServerConflicts(providers, scope, profile.serverName);
1934
+ if (format === "human" && conflictWarnings.length > 0) {
1935
+ console.log(pc6.yellow("Warning: potential server name conflicts detected."));
1936
+ for (const warning of conflictWarnings) {
1937
+ console.log(pc6.yellow(` - ${warning.message}`));
1938
+ }
1939
+ console.log(pc6.dim("Recovery: run with --dry-run, inspect provider config, then retry with explicit channel/profile."));
1940
+ console.log();
1941
+ }
1942
+ const results = await installMcpServerToAll(providers, profile.serverName, profile.config, scope);
1943
+ const succeeded = results.filter((result) => result.success);
1944
+ const validations = [];
1945
+ for (const result of succeeded) {
1946
+ const validation = await validateProfile(result.provider, scope, profile.serverName);
1947
+ validations.push({ providerId: result.provider.id, valid: validation.valid, reason: validation.reason });
1948
+ }
1949
+ if (succeeded.length > 0) {
1950
+ await recordMcpInstall(
1951
+ profile.serverName,
1952
+ profile.packageSpec ?? resolvedOpts.command ?? "cleo-dev",
1953
+ channel === "dev" ? "command" : "package",
1954
+ succeeded.map((result) => result.provider.id),
1955
+ resolvedOpts.global ?? false
1956
+ );
1957
+ }
1958
+ if (format === "human") {
1959
+ formatInstallResultHuman(mode, channel, profile.serverName, scope, results, validations);
1960
+ }
1961
+ const validationFailures = validations.filter((entry) => !entry.valid);
1962
+ if (interactive && validationFailures.length > 0 && format === "human") {
1963
+ console.log(pc6.dim("Step 5/6 - Validation"));
1964
+ console.log(pc6.yellow(`Validation found ${validationFailures.length} issue(s).`));
1965
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
1966
+ try {
1967
+ console.log(pc6.dim("Step 6/6 - Rollback"));
1968
+ const answer = await rl.question(pc6.dim("Rollback failed validations? [y/N] "));
1969
+ if (["y", "yes"].includes(answer.trim().toLowerCase())) {
1970
+ for (const failure of validationFailures) {
1971
+ const provider = providers.find((candidate) => candidate.id === failure.providerId);
1972
+ if (!provider) continue;
1973
+ await removeMcpServer(provider, profile.serverName, scope);
1974
+ }
1975
+ console.log(pc6.yellow("Rollback completed for failed provider validations."));
1976
+ }
1977
+ } finally {
1978
+ rl.close();
1979
+ }
1980
+ }
1981
+ if (format === "json") {
1982
+ outputSuccess(operation, mvi, {
1983
+ action: mode,
1984
+ channel,
1985
+ serverName: profile.serverName,
1986
+ scope,
1987
+ command: profile.config.command,
1988
+ args: profile.config.args ?? [],
1989
+ env: profile.config.env ?? {},
1990
+ packageSpec: profile.packageSpec,
1991
+ providers: results.map((result) => ({
1992
+ id: result.provider.id,
1993
+ success: result.success,
1994
+ configPath: result.configPath,
1995
+ error: result.error,
1996
+ validation: validations.find((entry) => entry.providerId === result.provider.id) ?? null
1997
+ })),
1998
+ conflicts: conflictWarnings,
1999
+ validationStatus: validationFailures.length === 0 ? "ok" : "warning"
2000
+ });
2001
+ }
2002
+ }
2003
+ async function executeCleoUninstall(opts, operation) {
2004
+ const mvi = "standard";
2005
+ let format;
2006
+ try {
2007
+ format = resolveFormat({
2008
+ jsonFlag: opts.json ?? false,
2009
+ humanFlag: (opts.human ?? false) || isHuman(),
2010
+ projectDefault: "json"
2011
+ });
2012
+ } catch (error) {
2013
+ const message = error instanceof Error ? error.message : String(error);
2014
+ emitJsonError(operation, mvi, ErrorCodes.FORMAT_CONFLICT, message, ErrorCategories.VALIDATION);
2015
+ process.exit(1);
2016
+ }
2017
+ const channel = normalizeCleoChannel(opts.channel);
2018
+ const serverName = resolveCleoServerName(channel);
2019
+ const providers = collectTargetProviders(opts.provider, opts.all);
2020
+ if (providers.length === 0) {
2021
+ const message = "No target providers found.";
2022
+ if (format === "json") {
2023
+ emitJsonError(operation, mvi, ErrorCodes.PROVIDER_NOT_FOUND, message, ErrorCategories.NOT_FOUND);
2024
+ } else {
2025
+ console.error(pc6.red(message));
2026
+ }
2027
+ process.exit(1);
2028
+ }
2029
+ const scope = opts.global ? "global" : "project";
2030
+ if (opts.dryRun) {
2031
+ if (format === "human") {
2032
+ console.log(pc6.bold("Dry run: uninstall CLEO profile"));
2033
+ console.log(pc6.dim(`Server: ${serverName} Channel: ${channel} Scope: ${scope}`));
2034
+ console.log(pc6.dim(`Providers: ${providers.map((provider) => provider.id).join(", ")}`));
2035
+ } else {
2036
+ outputSuccess(operation, mvi, {
2037
+ action: "uninstall",
2038
+ channel,
2039
+ serverName,
2040
+ providers: providers.map((provider) => provider.id),
2041
+ scope,
2042
+ dryRun: true
2043
+ });
2044
+ }
2045
+ return;
2046
+ }
2047
+ const removed = [];
2048
+ for (const provider of providers) {
2049
+ const success = await removeMcpServer(provider, serverName, scope);
2050
+ if (success) removed.push(provider.id);
2051
+ }
2052
+ if (removed.length > 0) {
2053
+ await removeMcpFromLock(serverName);
2054
+ }
2055
+ if (format === "human") {
2056
+ const prefix = removed.length > 0 ? pc6.green("Removed") : pc6.yellow("No matching profile found for");
2057
+ console.log(`${prefix} ${pc6.bold(serverName)} (${channel}) on ${removed.length}/${providers.length} providers.`);
2058
+ }
2059
+ if (format === "json") {
2060
+ outputSuccess(operation, mvi, {
2061
+ action: "uninstall",
2062
+ channel,
2063
+ serverName,
2064
+ scope,
2065
+ removed,
2066
+ providerCount: providers.length,
2067
+ dryRun: false
2068
+ });
2069
+ }
2070
+ }
2071
+ async function executeCleoShow(opts, operation) {
2072
+ const mvi = "standard";
2073
+ let format;
2074
+ try {
2075
+ format = resolveFormat({
2076
+ jsonFlag: opts.json ?? false,
2077
+ humanFlag: (opts.human ?? false) || isHuman(),
2078
+ projectDefault: "json"
2079
+ });
2080
+ } catch (error) {
2081
+ const message = error instanceof Error ? error.message : String(error);
2082
+ emitJsonError(operation, mvi, ErrorCodes.FORMAT_CONFLICT, message, ErrorCategories.VALIDATION);
2083
+ process.exit(1);
2084
+ }
2085
+ const providers = collectTargetProviders(opts.provider, opts.all);
2086
+ if (providers.length === 0) {
2087
+ const message = "No target providers found.";
2088
+ if (format === "json") {
2089
+ emitJsonError(operation, mvi, ErrorCodes.PROVIDER_NOT_FOUND, message, ErrorCategories.NOT_FOUND);
2090
+ } else {
2091
+ console.error(pc6.red(message));
2092
+ }
2093
+ process.exit(1);
2094
+ }
2095
+ const channelFilter = opts.channel ? normalizeCleoChannel(opts.channel) : null;
2096
+ const scope = opts.global ? "global" : "project";
2097
+ const entries = [];
2098
+ for (const provider of providers) {
2099
+ const providerEntries = await listMcpServers(provider, scope);
2100
+ for (const entry of providerEntries) {
2101
+ const channel = resolveChannelFromServerName(entry.name);
2102
+ if (!channel) continue;
2103
+ if (channelFilter && channel !== channelFilter) continue;
2104
+ entries.push({
2105
+ provider: provider.id,
2106
+ serverName: entry.name,
2107
+ channel,
2108
+ command: typeof entry.config.command === "string" ? entry.config.command : void 0,
2109
+ args: Array.isArray(entry.config.args) ? entry.config.args.filter((value) => typeof value === "string") : [],
2110
+ env: typeof entry.config.env === "object" && entry.config.env !== null ? entry.config.env : {}
2111
+ });
2112
+ }
2113
+ }
2114
+ if (format === "human") {
2115
+ if (entries.length === 0) {
2116
+ console.log(pc6.dim("No CLEO MCP profiles found."));
2117
+ } else {
2118
+ for (const entry of entries) {
2119
+ console.log(`${pc6.bold(entry.provider.padEnd(22))} ${entry.serverName.padEnd(10)} ${pc6.dim(entry.channel)}`);
2120
+ }
2121
+ }
2122
+ }
2123
+ if (format === "json") {
2124
+ outputSuccess(operation, mvi, {
2125
+ providers: providers.map((provider) => provider.id),
2126
+ scope,
2127
+ channel: channelFilter,
2128
+ profiles: entries,
2129
+ count: entries.length
2130
+ });
2131
+ }
2132
+ }
2133
+ function buildInstallOptions(command) {
2134
+ 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");
2135
+ }
2136
+ function registerMcpCleoCommands(parent) {
2137
+ const cleo = parent.command("cleo").description("Manage CLEO MCP channel profiles");
2138
+ buildInstallOptions(
2139
+ cleo.command("install").description("Install CLEO MCP profile by channel")
2140
+ ).action(async (opts) => {
2141
+ await executeCleoInstall("install", opts, "mcp.cleo.install");
2142
+ });
2143
+ buildInstallOptions(
2144
+ cleo.command("update").description("Update CLEO MCP profile by channel")
2145
+ ).action(async (opts) => {
2146
+ await executeCleoInstall("update", opts, "mcp.cleo.update");
2147
+ });
2148
+ 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) => {
2149
+ await executeCleoUninstall(opts, "mcp.cleo.uninstall");
2150
+ });
2151
+ 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", "Use global scope").option("--channel <channel>", "Filter channel: stable|beta|dev").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(async (opts) => {
2152
+ await executeCleoShow(opts, "mcp.cleo.show");
2153
+ });
2154
+ }
2155
+ function registerMcpCleoCompatibilityCommands(parent) {
2156
+ 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) => {
2157
+ if (name !== "cleo") {
2158
+ emitJsonError("mcp.update", "standard", ErrorCodes.INVALID_INPUT, "Only managed profile 'cleo' is supported by mcp update.", ErrorCategories.VALIDATION, { name });
2159
+ process.exit(1);
2160
+ }
2161
+ await executeCleoInstall("update", opts, "mcp.update");
2162
+ });
2163
+ 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) => {
2164
+ if (name !== "cleo") {
2165
+ emitJsonError("mcp.uninstall", "standard", ErrorCodes.INVALID_INPUT, "Only managed profile 'cleo' is supported by mcp uninstall.", ErrorCategories.VALIDATION, { name });
2166
+ process.exit(1);
2167
+ }
2168
+ await executeCleoUninstall(opts, "mcp.uninstall");
2169
+ });
2170
+ 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", "Use global scope").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) => {
2171
+ if (name !== "cleo") {
2172
+ emitJsonError("mcp.show", "standard", ErrorCodes.INVALID_INPUT, "Only managed profile 'cleo' is supported by mcp show.", ErrorCategories.VALIDATION, { name });
2173
+ process.exit(1);
2174
+ }
2175
+ await executeCleoShow(opts, "mcp.show");
2176
+ });
2177
+ }
2178
+ function mapCompatibilityInstallOptions(opts) {
2179
+ return {
2180
+ channel: opts.channel,
2181
+ provider: [...opts.provider ?? [], ...opts.agent ?? []],
2182
+ all: opts.all,
2183
+ global: opts.global,
2184
+ version: opts.version,
2185
+ command: opts.command,
2186
+ arg: opts.arg ?? [],
2187
+ env: opts.env ?? [],
2188
+ cleoDir: opts.cleoDir,
2189
+ dryRun: opts.dryRun,
2190
+ yes: opts.yes,
2191
+ interactive: opts.interactive,
2192
+ json: opts.json,
2193
+ human: opts.human
2194
+ };
2195
+ }
2196
+ function shouldUseCleoCompatibilityInstall(source, channel) {
2197
+ if (source.trim().toLowerCase() !== "cleo") return false;
2198
+ return typeof channel === "string" && channel.trim() !== "";
2199
+ }
2200
+
2201
+ // src/commands/mcp/detect.ts
2202
+ import { existsSync as existsSync4 } from "fs";
2203
+ import pc7 from "picocolors";
2204
+ function registerMcpDetect(parent) {
2205
+ 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) => {
2206
+ const operation = "mcp.detect";
2207
+ const mvi = "standard";
2208
+ let format;
2209
+ try {
2210
+ format = resolveFormat({
2211
+ jsonFlag: opts.json ?? false,
2212
+ humanFlag: (opts.human ?? false) || isHuman(),
2213
+ projectDefault: "json"
2214
+ });
2215
+ } catch (error) {
2216
+ const message = error instanceof Error ? error.message : String(error);
2217
+ emitJsonError(operation, mvi, ErrorCodes.FORMAT_CONFLICT, message, ErrorCategories.VALIDATION);
2218
+ process.exit(1);
2219
+ }
2220
+ const providers = getInstalledProviders();
2221
+ const providersResult = [];
2222
+ let totalConfigs = 0;
2223
+ for (const provider of providers) {
2224
+ const globalPath = resolveConfigPath(provider, "global");
2225
+ const projectPath = resolveConfigPath(provider, "project");
2226
+ const globalEntries = await listMcpServers(provider, "global");
2227
+ const projectEntries = await listMcpServers(provider, "project");
2228
+ const configsFound = (globalPath && existsSync4(globalPath) ? 1 : 0) + (projectPath && existsSync4(projectPath) ? 1 : 0);
2229
+ totalConfigs += configsFound;
2230
+ const allServers = [...globalEntries.map((e) => e.name), ...projectEntries.map((e) => e.name)];
2231
+ providersResult.push({
2232
+ id: provider.id,
2233
+ configsFound,
2234
+ servers: allServers
2235
+ });
2236
+ }
2237
+ if (format === "json") {
2238
+ outputSuccess(operation, mvi, {
2239
+ providers: providersResult,
2240
+ totalConfigs
2241
+ });
2242
+ return;
2243
+ }
2244
+ console.log(pc7.bold(`
2245
+ ${providers.length} provider(s) with MCP support:
2246
+ `));
2247
+ for (const provider of providersResult) {
2248
+ const globalPath = resolveConfigPath(providers.find((p) => p.id === provider.id), "global");
2249
+ const projectPath = resolveConfigPath(providers.find((p) => p.id === provider.id), "project");
2250
+ const hasGlobal = globalPath && existsSync4(globalPath);
2251
+ const hasProject = projectPath && existsSync4(projectPath);
2252
+ const globalIcon = hasGlobal ? pc7.green("G") : pc7.dim("-");
2253
+ const projectIcon = hasProject ? pc7.green("P") : pc7.dim("-");
2254
+ const serverList = provider.servers.length > 0 ? pc7.dim(provider.servers.join(", ")) : pc7.dim("no servers");
2255
+ console.log(` [${globalIcon}${projectIcon}] ${pc7.bold(provider.id.padEnd(20))} ${serverList}`);
2256
+ }
2257
+ console.log(pc7.dim("\nG = global config, P = project config"));
2258
+ console.log();
2259
+ });
2260
+ }
2261
+
2262
+ // src/commands/mcp/install.ts
2263
+ import pc8 from "picocolors";
1606
2264
  function registerMcpInstall(parent) {
1607
- parent.command("install").description("Install MCP server to agent configs").argument("<source>", "MCP server source (URL, npm package, or command)").option("-a, --agent <name>", "Target specific agent(s)", (v, prev) => [...prev, v], []).option("-g, --global", "Install to global/user config").option("-n, --name <name>", "Override inferred server name").option("-t, --transport <type>", "Transport type: http (default) or sse", "http").option("--header <header>", "HTTP header (Key: Value)", (v, prev) => [...prev, v], []).option("-y, --yes", "Skip confirmation").option("--all", "Install to all detected agents").option("--dry-run", "Preview without writing").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(async (source, opts) => {
2265
+ parent.command("install").description("Install MCP server to agent configs").argument("<source>", "MCP server source (URL, npm package, or command)").option("-a, --agent <name>", "Target specific agent(s)", (v, prev) => [...prev, v], []).option("--provider <id>", "Target provider ID (alias for --agent)", (v, prev) => [...prev, v], []).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("--arg <arg>", "Managed dev command arg (repeatable)", (v, prev) => [...prev, v], []).option("--env <kv>", "Managed env assignment KEY=value (repeatable)", (v, prev) => [...prev, v], []).option("--cleo-dir <path>", "Managed dev CLEO_DIR override").option("-t, --transport <type>", "Transport type: http (default) or sse", "http").option("--header <header>", "HTTP header (Key: Value)", (v, prev) => [...prev, v], []).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(async (source, opts) => {
1608
2266
  const operation = "mcp.install";
1609
2267
  const mvi = "standard";
1610
2268
  let format;
@@ -1619,6 +2277,11 @@ function registerMcpInstall(parent) {
1619
2277
  emitJsonError(operation, mvi, ErrorCodes.FORMAT_CONFLICT, message, ErrorCategories.VALIDATION);
1620
2278
  process.exit(1);
1621
2279
  }
2280
+ if (shouldUseCleoCompatibilityInstall(source, opts.channel)) {
2281
+ const cleoOpts = mapCompatibilityInstallOptions(opts);
2282
+ await executeCleoInstall("install", cleoOpts, operation);
2283
+ return;
2284
+ }
1622
2285
  const parsed = parseSource(source);
1623
2286
  const serverName = opts.name ?? parsed.inferredName;
1624
2287
  const headers = {};
@@ -1634,6 +2297,8 @@ function registerMcpInstall(parent) {
1634
2297
  providers = getInstalledProviders();
1635
2298
  } else if (opts.agent.length > 0) {
1636
2299
  providers = opts.agent.map((a) => getProvider(a)).filter((p) => p !== void 0);
2300
+ } else if (opts.provider.length > 0) {
2301
+ providers = opts.provider.map((a) => getProvider(a)).filter((p) => p !== void 0);
1637
2302
  } else {
1638
2303
  providers = getInstalledProviders();
1639
2304
  }
@@ -1642,7 +2307,7 @@ function registerMcpInstall(parent) {
1642
2307
  if (format === "json") {
1643
2308
  emitJsonError(operation, mvi, ErrorCodes.PROVIDER_NOT_FOUND, message, ErrorCategories.NOT_FOUND);
1644
2309
  } else {
1645
- console.error(pc6.red(message));
2310
+ console.error(pc8.red(message));
1646
2311
  }
1647
2312
  process.exit(1);
1648
2313
  }
@@ -1658,8 +2323,8 @@ function registerMcpInstall(parent) {
1658
2323
  dryRun: true
1659
2324
  });
1660
2325
  } else {
1661
- console.log(pc6.bold("Dry run - would install:"));
1662
- console.log(` Server: ${pc6.bold(serverName)}`);
2326
+ console.log(pc8.bold("Dry run - would install:"));
2327
+ console.log(` Server: ${pc8.bold(serverName)}`);
1663
2328
  console.log(` Config: ${JSON.stringify(config, null, 2)}`);
1664
2329
  console.log(` Scope: ${scope}`);
1665
2330
  console.log(` Providers: ${providers.map((p) => p.id).join(", ")}`);
@@ -1667,7 +2332,7 @@ function registerMcpInstall(parent) {
1667
2332
  return;
1668
2333
  }
1669
2334
  if (format === "human") {
1670
- console.log(pc6.dim(`Installing "${serverName}" to ${providers.length} provider(s)...
2335
+ console.log(pc8.dim(`Installing "${serverName}" to ${providers.length} provider(s)...
1671
2336
  `));
1672
2337
  }
1673
2338
  const results = await installMcpServerToAll(
@@ -1681,9 +2346,9 @@ function registerMcpInstall(parent) {
1681
2346
  if (format === "human") {
1682
2347
  for (const r of results) {
1683
2348
  if (r.success) {
1684
- console.log(` ${pc6.green("\u2713")} ${r.provider.toolName.padEnd(22)} ${pc6.dim(r.configPath)}`);
2349
+ console.log(` ${pc8.green("\u2713")} ${r.provider.toolName.padEnd(22)} ${pc8.dim(r.configPath)}`);
1685
2350
  } else {
1686
- console.log(` ${pc6.red("\u2717")} ${r.provider.toolName.padEnd(22)} ${pc6.red(r.error ?? "failed")}`);
2351
+ console.log(` ${pc8.red("\u2717")} ${r.provider.toolName.padEnd(22)} ${pc8.red(r.error ?? "failed")}`);
1687
2352
  }
1688
2353
  }
1689
2354
  }
@@ -1706,85 +2371,16 @@ function registerMcpInstall(parent) {
1706
2371
  dryRun: false
1707
2372
  });
1708
2373
  } else {
1709
- console.log(pc6.bold(`
2374
+ console.log(pc8.bold(`
1710
2375
  ${succeeded.length}/${results.length} providers configured.`));
1711
2376
  }
1712
2377
  });
1713
2378
  }
1714
2379
 
1715
- // src/commands/mcp/remove.ts
1716
- import pc7 from "picocolors";
1717
- function registerMcpRemove(parent) {
1718
- parent.command("remove").description("Remove MCP server from agent configs").argument("<name>", "MCP server name to remove").option("-a, --agent <name>", "Target specific agent(s)", (v, prev) => [...prev, v], []).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(async (name, opts) => {
1719
- const operation = "mcp.remove";
1720
- const mvi = "standard";
1721
- let format;
1722
- try {
1723
- format = resolveFormat({
1724
- jsonFlag: opts.json ?? false,
1725
- humanFlag: (opts.human ?? false) || isHuman(),
1726
- projectDefault: "json"
1727
- });
1728
- } catch (error) {
1729
- const message = error instanceof Error ? error.message : String(error);
1730
- emitJsonError(operation, mvi, ErrorCodes.FORMAT_CONFLICT, message, ErrorCategories.VALIDATION);
1731
- process.exit(1);
1732
- }
1733
- let providers;
1734
- if (opts.all) {
1735
- providers = getInstalledProviders();
1736
- } else if (opts.agent.length > 0) {
1737
- providers = opts.agent.map((a) => getProvider(a)).filter((p) => p !== void 0);
1738
- } else {
1739
- providers = getInstalledProviders();
1740
- }
1741
- if (providers.length === 0) {
1742
- const message = "No target providers found.";
1743
- if (format === "json") {
1744
- emitJsonError(operation, mvi, ErrorCodes.PROVIDER_NOT_FOUND, message, ErrorCategories.NOT_FOUND);
1745
- } else {
1746
- console.error(pc7.red(message));
1747
- }
1748
- process.exit(1);
1749
- }
1750
- const scope = opts.global ? "global" : "project";
1751
- const removed = [];
1752
- const notFound = [];
1753
- for (const provider of providers) {
1754
- const success = await removeMcpServer(provider, name, scope);
1755
- if (success) {
1756
- removed.push(provider.id);
1757
- if (format === "human") {
1758
- console.log(` ${pc7.green("\u2713")} Removed from ${provider.toolName}`);
1759
- }
1760
- } else {
1761
- notFound.push(provider.id);
1762
- }
1763
- }
1764
- if (removed.length > 0) {
1765
- await removeMcpFromLock(name);
1766
- }
1767
- if (format === "json") {
1768
- outputSuccess(operation, mvi, {
1769
- removed,
1770
- providers: removed,
1771
- notFound: notFound.length > 0 ? notFound : void 0
1772
- });
1773
- } else {
1774
- if (removed.length > 0) {
1775
- console.log(pc7.green(`
1776
- \u2713 Removed "${name}" from ${removed.length} provider(s).`));
1777
- } else {
1778
- console.log(pc7.yellow(`Server "${name}" not found in any provider config.`));
1779
- }
1780
- }
1781
- });
1782
- }
1783
-
1784
2380
  // src/commands/mcp/list.ts
1785
- import pc8 from "picocolors";
2381
+ import pc9 from "picocolors";
1786
2382
  function registerMcpList(parent) {
1787
- parent.command("list").description("List configured MCP servers").option("-a, --agent <name>", "List for specific agent").option("-g, --global", "List global config").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(async (opts) => {
2383
+ 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(async (opts) => {
1788
2384
  const operation = "mcp.list";
1789
2385
  const mvi = "standard";
1790
2386
  let format;
@@ -1799,15 +2395,16 @@ function registerMcpList(parent) {
1799
2395
  emitJsonError(operation, mvi, ErrorCodes.FORMAT_CONFLICT, message, ErrorCategories.VALIDATION);
1800
2396
  process.exit(1);
1801
2397
  }
1802
- const providers = opts.agent ? [getProvider(opts.agent)].filter((p) => p !== void 0) : getInstalledProviders();
1803
- if (opts.agent && providers.length === 0) {
1804
- const message = `Provider not found: ${opts.agent}`;
2398
+ const selectedProvider = opts.provider ?? opts.agent;
2399
+ const providers = selectedProvider ? [getProvider(selectedProvider)].filter((p) => p !== void 0) : getInstalledProviders();
2400
+ if (selectedProvider && providers.length === 0) {
2401
+ const message = `Provider not found: ${selectedProvider}`;
1805
2402
  if (format === "json") {
1806
2403
  emitJsonError(operation, mvi, ErrorCodes.PROVIDER_NOT_FOUND, message, ErrorCategories.NOT_FOUND, {
1807
- agent: opts.agent
2404
+ provider: selectedProvider
1808
2405
  });
1809
2406
  } else {
1810
- console.error(pc8.red(message));
2407
+ console.error(pc9.red(message));
1811
2408
  }
1812
2409
  process.exit(1);
1813
2410
  }
@@ -1827,33 +2424,32 @@ function registerMcpList(parent) {
1827
2424
  outputSuccess(operation, mvi, {
1828
2425
  servers: allEntries,
1829
2426
  count: allEntries.length,
1830
- scope: opts.global ? "global" : opts.agent ? `agent:${opts.agent}` : "project"
2427
+ scope: opts.global ? "global" : selectedProvider ? `agent:${selectedProvider}` : "project"
1831
2428
  });
1832
2429
  return;
1833
2430
  }
1834
2431
  if (allEntries.length === 0) {
1835
- console.log(pc8.dim("No MCP servers configured."));
2432
+ console.log(pc9.dim("No MCP servers configured."));
1836
2433
  return;
1837
2434
  }
1838
- console.log(pc8.bold(`
2435
+ console.log(pc9.bold(`
1839
2436
  ${allEntries.length} MCP server(s) configured:
1840
2437
  `));
1841
2438
  for (const entry of allEntries) {
1842
- const scopeIndicator = entry.scope === "global" ? pc8.dim("[G] ") : pc8.dim("[P] ");
1843
- console.log(` ${scopeIndicator}${pc8.bold(entry.name.padEnd(25))} ${entry.command ? pc8.dim(entry.command) : ""}`);
2439
+ const scopeIndicator = entry.scope === "global" ? pc9.dim("[G] ") : pc9.dim("[P] ");
2440
+ console.log(` ${scopeIndicator}${pc9.bold(entry.name.padEnd(25))} ${entry.command ? pc9.dim(entry.command) : ""}`);
1844
2441
  }
1845
2442
  console.log();
1846
- console.log(pc8.dim("G = global config, P = project config"));
2443
+ console.log(pc9.dim("G = global config, P = project config"));
1847
2444
  console.log();
1848
2445
  });
1849
2446
  }
1850
2447
 
1851
- // src/commands/mcp/detect.ts
1852
- import { existsSync as existsSync3 } from "fs";
1853
- import pc9 from "picocolors";
1854
- function registerMcpDetect(parent) {
1855
- 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) => {
1856
- const operation = "mcp.detect";
2448
+ // src/commands/mcp/remove.ts
2449
+ import pc10 from "picocolors";
2450
+ function registerMcpRemove(parent) {
2451
+ parent.command("remove").description("Remove MCP server from agent configs").argument("<name>", "MCP server name to remove").option("-a, --agent <name>", "Target specific agent(s)", (v, prev) => [...prev, v], []).option("--provider <id>", "Target provider ID (alias for --agent)", (v, prev) => [...prev, v], []).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(async (name, opts) => {
2452
+ const operation = "mcp.remove";
1857
2453
  const mvi = "standard";
1858
2454
  let format;
1859
2455
  try {
@@ -1867,45 +2463,56 @@ function registerMcpDetect(parent) {
1867
2463
  emitJsonError(operation, mvi, ErrorCodes.FORMAT_CONFLICT, message, ErrorCategories.VALIDATION);
1868
2464
  process.exit(1);
1869
2465
  }
1870
- const providers = getInstalledProviders();
1871
- const providersResult = [];
1872
- let totalConfigs = 0;
2466
+ let providers;
2467
+ if (opts.all) {
2468
+ providers = getInstalledProviders();
2469
+ } else if (opts.agent.length > 0) {
2470
+ providers = opts.agent.map((a) => getProvider(a)).filter((p) => p !== void 0);
2471
+ } else if (opts.provider.length > 0) {
2472
+ providers = opts.provider.map((a) => getProvider(a)).filter((p) => p !== void 0);
2473
+ } else {
2474
+ providers = getInstalledProviders();
2475
+ }
2476
+ if (providers.length === 0) {
2477
+ const message = "No target providers found.";
2478
+ if (format === "json") {
2479
+ emitJsonError(operation, mvi, ErrorCodes.PROVIDER_NOT_FOUND, message, ErrorCategories.NOT_FOUND);
2480
+ } else {
2481
+ console.error(pc10.red(message));
2482
+ }
2483
+ process.exit(1);
2484
+ }
2485
+ const scope = opts.global ? "global" : "project";
2486
+ const removed = [];
2487
+ const notFound = [];
1873
2488
  for (const provider of providers) {
1874
- const globalPath = resolveConfigPath(provider, "global");
1875
- const projectPath = resolveConfigPath(provider, "project");
1876
- const globalEntries = await listMcpServers(provider, "global");
1877
- const projectEntries = await listMcpServers(provider, "project");
1878
- const configsFound = (globalPath && existsSync3(globalPath) ? 1 : 0) + (projectPath && existsSync3(projectPath) ? 1 : 0);
1879
- totalConfigs += configsFound;
1880
- const allServers = [...globalEntries.map((e) => e.name), ...projectEntries.map((e) => e.name)];
1881
- providersResult.push({
1882
- id: provider.id,
1883
- configsFound,
1884
- servers: allServers
1885
- });
2489
+ const success = await removeMcpServer(provider, name, scope);
2490
+ if (success) {
2491
+ removed.push(provider.id);
2492
+ if (format === "human") {
2493
+ console.log(` ${pc10.green("\u2713")} Removed from ${provider.toolName}`);
2494
+ }
2495
+ } else {
2496
+ notFound.push(provider.id);
2497
+ }
2498
+ }
2499
+ if (removed.length > 0) {
2500
+ await removeMcpFromLock(name);
1886
2501
  }
1887
2502
  if (format === "json") {
1888
2503
  outputSuccess(operation, mvi, {
1889
- providers: providersResult,
1890
- totalConfigs
2504
+ removed,
2505
+ providers: removed,
2506
+ notFound: notFound.length > 0 ? notFound : void 0
1891
2507
  });
1892
- return;
2508
+ } else {
2509
+ if (removed.length > 0) {
2510
+ console.log(pc10.green(`
2511
+ \u2713 Removed "${name}" from ${removed.length} provider(s).`));
2512
+ } else {
2513
+ console.log(pc10.yellow(`Server "${name}" not found in any provider config.`));
2514
+ }
1893
2515
  }
1894
- console.log(pc9.bold(`
1895
- ${providers.length} provider(s) with MCP support:
1896
- `));
1897
- for (const provider of providersResult) {
1898
- const globalPath = resolveConfigPath(providers.find((p) => p.id === provider.id), "global");
1899
- const projectPath = resolveConfigPath(providers.find((p) => p.id === provider.id), "project");
1900
- const hasGlobal = globalPath && existsSync3(globalPath);
1901
- const hasProject = projectPath && existsSync3(projectPath);
1902
- const globalIcon = hasGlobal ? pc9.green("G") : pc9.dim("-");
1903
- const projectIcon = hasProject ? pc9.green("P") : pc9.dim("-");
1904
- const serverList = provider.servers.length > 0 ? pc9.dim(provider.servers.join(", ")) : pc9.dim("no servers");
1905
- console.log(` [${globalIcon}${projectIcon}] ${pc9.bold(provider.id.padEnd(20))} ${serverList}`);
1906
- }
1907
- console.log(pc9.dim("\nG = global config, P = project config"));
1908
- console.log();
1909
2516
  });
1910
2517
  }
1911
2518
 
@@ -1916,12 +2523,14 @@ function registerMcpCommands(program2) {
1916
2523
  registerMcpRemove(mcp);
1917
2524
  registerMcpList(mcp);
1918
2525
  registerMcpDetect(mcp);
2526
+ registerMcpCleoCommands(mcp);
2527
+ registerMcpCleoCompatibilityCommands(mcp);
1919
2528
  }
1920
2529
 
1921
2530
  // src/commands/providers.ts
1922
2531
  import { randomUUID as randomUUID3 } from "crypto";
1923
2532
  import { resolveOutputFormat as resolveOutputFormat2 } from "@cleocode/lafs-protocol";
1924
- import pc10 from "picocolors";
2533
+ import pc11 from "picocolors";
1925
2534
  function registerProvidersCommand(program2) {
1926
2535
  const providers = program2.command("providers").description("Manage AI agent providers");
1927
2536
  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) => {
@@ -1955,19 +2564,19 @@ function registerProvidersCommand(program2) {
1955
2564
  console.log(JSON.stringify(envelope, null, 2));
1956
2565
  return;
1957
2566
  }
1958
- console.log(pc10.bold(`
2567
+ console.log(pc11.bold(`
1959
2568
  CAMP Provider Registry v${getRegistryVersion()}`));
1960
- console.log(pc10.dim(`${getProviderCount()} providers
2569
+ console.log(pc11.dim(`${getProviderCount()} providers
1961
2570
  `));
1962
2571
  const tiers = ["high", "medium", "low"];
1963
2572
  for (const tier of tiers) {
1964
2573
  const tierProviders = all.filter((p) => p.priority === tier);
1965
2574
  if (tierProviders.length === 0) continue;
1966
- const tierLabel = tier === "high" ? pc10.green("HIGH") : tier === "medium" ? pc10.yellow("MEDIUM") : pc10.dim("LOW");
2575
+ const tierLabel = tier === "high" ? pc11.green("HIGH") : tier === "medium" ? pc11.yellow("MEDIUM") : pc11.dim("LOW");
1967
2576
  console.log(`${tierLabel} priority:`);
1968
2577
  for (const p of tierProviders) {
1969
- const status = p.status === "active" ? pc10.green("active") : p.status === "beta" ? pc10.yellow("beta") : pc10.dim(p.status);
1970
- console.log(` ${pc10.bold(p.agentFlag.padEnd(20))} ${p.toolName.padEnd(22)} ${p.vendor.padEnd(16)} [${status}]`);
2578
+ const status = p.status === "active" ? pc11.green("active") : p.status === "beta" ? pc11.yellow("beta") : pc11.dim(p.status);
2579
+ console.log(` ${pc11.bold(p.agentFlag.padEnd(20))} ${p.toolName.padEnd(22)} ${p.vendor.padEnd(16)} [${status}]`);
1971
2580
  }
1972
2581
  console.log();
1973
2582
  }
@@ -2011,17 +2620,17 @@ CAMP Provider Registry v${getRegistryVersion()}`));
2011
2620
  console.log(JSON.stringify(envelope, null, 2));
2012
2621
  return;
2013
2622
  }
2014
- console.log(pc10.bold(`
2623
+ console.log(pc11.bold(`
2015
2624
  Detected ${installed.length} installed providers:
2016
2625
  `));
2017
2626
  for (const r of installed) {
2018
2627
  const methods = r.methods.join(", ");
2019
- const project = r.projectDetected ? pc10.green(" [project]") : "";
2020
- console.log(` ${pc10.green("\u2713")} ${pc10.bold(r.provider.toolName.padEnd(22))} via ${pc10.dim(methods)}${project}`);
2628
+ const project = r.projectDetected ? pc11.green(" [project]") : "";
2629
+ console.log(` ${pc11.green("\u2713")} ${pc11.bold(r.provider.toolName.padEnd(22))} via ${pc11.dim(methods)}${project}`);
2021
2630
  }
2022
2631
  const notInstalled = results.filter((r) => !r.installed);
2023
2632
  if (notInstalled.length > 0) {
2024
- console.log(pc10.dim(`
2633
+ console.log(pc11.dim(`
2025
2634
  ${notInstalled.length} providers not detected`));
2026
2635
  }
2027
2636
  console.log();
@@ -2049,7 +2658,7 @@ Detected ${installed.length} installed providers:
2049
2658
  id
2050
2659
  });
2051
2660
  } else {
2052
- console.error(pc10.red(message));
2661
+ console.error(pc11.red(message));
2053
2662
  }
2054
2663
  process.exit(1);
2055
2664
  }
@@ -2065,9 +2674,9 @@ Detected ${installed.length} installed providers:
2065
2674
  console.log(JSON.stringify(envelope, null, 2));
2066
2675
  return;
2067
2676
  }
2068
- console.log(pc10.bold(`
2677
+ console.log(pc11.bold(`
2069
2678
  ${provider.toolName}`));
2070
- console.log(pc10.dim(`by ${provider.vendor}
2679
+ console.log(pc11.dim(`by ${provider.vendor}
2071
2680
  `));
2072
2681
  console.log(` ID: ${provider.id}`);
2073
2682
  console.log(` Flag: --agent ${provider.agentFlag}`);
@@ -2083,7 +2692,7 @@ ${provider.toolName}`));
2083
2692
  console.log(` Transports: ${provider.supportedTransports.join(", ")}`);
2084
2693
  console.log(` Headers: ${provider.supportsHeaders ? "yes" : "no"}`);
2085
2694
  console.log();
2086
- console.log(pc10.dim(" Paths:"));
2695
+ console.log(pc11.dim(" Paths:"));
2087
2696
  console.log(` Global dir: ${provider.pathGlobal}`);
2088
2697
  console.log(` Project dir: ${provider.pathProject || "(none)"}`);
2089
2698
  console.log(` Global config: ${provider.configPathGlobal}`);
@@ -2126,8 +2735,8 @@ function emitJsonError2(operation, mvi, code, message, category, details = {}) {
2126
2735
  }
2127
2736
 
2128
2737
  // src/commands/skills/install.ts
2129
- import { existsSync as existsSync4 } from "fs";
2130
- import pc11 from "picocolors";
2738
+ import { existsSync as existsSync5 } from "fs";
2739
+ import pc12 from "picocolors";
2131
2740
 
2132
2741
  // src/core/sources/github.ts
2133
2742
  import { simpleGit } from "simple-git";
@@ -2211,7 +2820,7 @@ function registerSkillsInstall(parent) {
2211
2820
  if (format === "json") {
2212
2821
  emitError2(operation, mvi, ErrorCodes.PROVIDER_NOT_FOUND, message, ErrorCategories.NOT_FOUND);
2213
2822
  }
2214
- console.error(pc11.red(message));
2823
+ console.error(pc12.red(message));
2215
2824
  process.exit(1);
2216
2825
  }
2217
2826
  if (opts.profile) {
@@ -2223,12 +2832,12 @@ function registerSkillsInstall(parent) {
2223
2832
  if (format === "json") {
2224
2833
  emitError2(operation, mvi, ErrorCodes.INVALID_INPUT, message, ErrorCategories.VALIDATION);
2225
2834
  }
2226
- console.error(pc11.red(message));
2227
- console.log(pc11.dim("Usage: caamp skills install <source> or caamp skills install --profile <name>"));
2835
+ console.error(pc12.red(message));
2836
+ console.log(pc12.dim("Usage: caamp skills install <source> or caamp skills install --profile <name>"));
2228
2837
  process.exit(1);
2229
2838
  }
2230
2839
  if (format === "human") {
2231
- console.log(pc11.dim(`Installing to ${providers.length} provider(s)...`));
2840
+ console.log(pc12.dim(`Installing to ${providers.length} provider(s)...`));
2232
2841
  }
2233
2842
  let localPath;
2234
2843
  let cleanup;
@@ -2268,7 +2877,7 @@ function registerSkillsInstall(parent) {
2268
2877
  if (format === "json") {
2269
2878
  emitJsonError(operation, mvi, ErrorCodes.NETWORK_ERROR, message, ErrorCategories.TRANSIENT);
2270
2879
  }
2271
- console.error(pc11.red(message));
2880
+ console.error(pc12.red(message));
2272
2881
  process.exit(1);
2273
2882
  }
2274
2883
  } else if (parsed.type === "gitlab" && parsed.owner && parsed.repo) {
@@ -2281,7 +2890,7 @@ function registerSkillsInstall(parent) {
2281
2890
  if (format === "json") {
2282
2891
  emitJsonError(operation, mvi, ErrorCodes.NETWORK_ERROR, message, ErrorCategories.TRANSIENT);
2283
2892
  }
2284
- console.error(pc11.red(message));
2893
+ console.error(pc12.red(message));
2285
2894
  process.exit(1);
2286
2895
  }
2287
2896
  } else if (parsed.type === "local") {
@@ -2296,7 +2905,7 @@ function registerSkillsInstall(parent) {
2296
2905
  if (format === "json") {
2297
2906
  emitJsonError(operation, mvi, ErrorCodes.INVALID_INPUT, message, ErrorCategories.VALIDATION);
2298
2907
  }
2299
- console.error(pc11.red(message));
2908
+ console.error(pc12.red(message));
2300
2909
  process.exit(1);
2301
2910
  }
2302
2911
  const catalogSkill = getSkill(parsed.inferredName);
@@ -2306,7 +2915,7 @@ function registerSkillsInstall(parent) {
2306
2915
  sourceValue = `library:${catalogSkill.name}`;
2307
2916
  sourceType = "library";
2308
2917
  if (format === "human") {
2309
- console.log(` Found in catalog: ${pc11.bold(catalogSkill.name)} v${catalogSkill.version} (${pc11.dim(catalogSkill.category)})`);
2918
+ console.log(` Found in catalog: ${pc12.bold(catalogSkill.name)} v${catalogSkill.version} (${pc12.dim(catalogSkill.category)})`);
2310
2919
  }
2311
2920
  } else {
2312
2921
  const message = `Skill not found in catalog: ${parsed.inferredName}`;
@@ -2315,8 +2924,8 @@ function registerSkillsInstall(parent) {
2315
2924
  availableSkills: listSkills()
2316
2925
  });
2317
2926
  }
2318
- console.error(pc11.red(message));
2319
- console.log(pc11.dim("Available skills: " + listSkills().join(", ")));
2927
+ console.error(pc12.red(message));
2928
+ console.log(pc12.dim("Available skills: " + listSkills().join(", ")));
2320
2929
  process.exit(1);
2321
2930
  }
2322
2931
  } else {
@@ -2324,7 +2933,7 @@ function registerSkillsInstall(parent) {
2324
2933
  if (format === "json") {
2325
2934
  emitJsonError(operation, mvi, ErrorCodes.INVALID_FORMAT, message, ErrorCategories.VALIDATION);
2326
2935
  }
2327
- console.error(pc11.red(message));
2936
+ console.error(pc12.red(message));
2328
2937
  process.exit(1);
2329
2938
  }
2330
2939
  }
@@ -2334,7 +2943,7 @@ function registerSkillsInstall(parent) {
2334
2943
  if (format === "json") {
2335
2944
  emitJsonError(operation, mvi, ErrorCodes.INTERNAL_ERROR, message, ErrorCategories.INTERNAL);
2336
2945
  }
2337
- console.error(pc11.red(message));
2946
+ console.error(pc12.red(message));
2338
2947
  process.exit(1);
2339
2948
  }
2340
2949
  const result = await installSkill(
@@ -2372,14 +2981,14 @@ function registerSkillsInstall(parent) {
2372
2981
  if (format === "json") {
2373
2982
  outputSuccess(operation, mvi, summary);
2374
2983
  } else {
2375
- console.log(pc11.green(`
2376
- \u2713 Installed ${pc11.bold(skillName)}`));
2377
- console.log(` Canonical: ${pc11.dim(result.canonicalPath)}`);
2984
+ console.log(pc12.green(`
2985
+ \u2713 Installed ${pc12.bold(skillName)}`));
2986
+ console.log(` Canonical: ${pc12.dim(result.canonicalPath)}`);
2378
2987
  console.log(` Linked to: ${result.linkedAgents.join(", ")}`);
2379
2988
  if (result.errors.length > 0) {
2380
- console.log(pc11.yellow("\nWarnings:"));
2989
+ console.log(pc12.yellow("\nWarnings:"));
2381
2990
  for (const err of result.errors) {
2382
- console.log(` ${pc11.yellow("!")} ${err}`);
2991
+ console.log(` ${pc12.yellow("!")} ${err}`);
2383
2992
  }
2384
2993
  }
2385
2994
  }
@@ -2407,11 +3016,11 @@ function registerSkillsInstall(parent) {
2407
3016
  });
2408
3017
  console.error(JSON.stringify(envelope, null, 2));
2409
3018
  } else {
2410
- console.log(pc11.yellow(`
2411
- \u2717 Failed to install ${pc11.bold(skillName)}`));
2412
- console.log(pc11.yellow("Errors:"));
3019
+ console.log(pc12.yellow(`
3020
+ \u2717 Failed to install ${pc12.bold(skillName)}`));
3021
+ console.log(pc12.yellow("Errors:"));
2413
3022
  for (const err of result.errors) {
2414
- console.log(` ${pc11.yellow("!")} ${err}`);
3023
+ console.log(` ${pc12.yellow("!")} ${err}`);
2415
3024
  }
2416
3025
  }
2417
3026
  process.exit(1);
@@ -2427,7 +3036,7 @@ async function handleProfileInstall(profileName, providers, isGlobal, format, op
2427
3036
  if (format === "json") {
2428
3037
  emitError2(operation, mvi, ErrorCodes.INVALID_INPUT, message, ErrorCategories.VALIDATION);
2429
3038
  }
2430
- console.error(pc11.red(message));
3039
+ console.error(pc12.red(message));
2431
3040
  process.exit(1);
2432
3041
  }
2433
3042
  const profileSkills = resolveProfile(profileName);
@@ -2438,16 +3047,16 @@ async function handleProfileInstall(profileName, providers, isGlobal, format, op
2438
3047
  availableProfiles: listProfiles()
2439
3048
  });
2440
3049
  }
2441
- console.error(pc11.red(message));
3050
+ console.error(pc12.red(message));
2442
3051
  const available = listProfiles();
2443
3052
  if (available.length > 0) {
2444
- console.log(pc11.dim("Available profiles: " + available.join(", ")));
3053
+ console.log(pc12.dim("Available profiles: " + available.join(", ")));
2445
3054
  }
2446
3055
  process.exit(1);
2447
3056
  }
2448
3057
  if (format === "human") {
2449
- console.log(`Installing profile ${pc11.bold(profileName)} (${profileSkills.length} skill(s))...`);
2450
- console.log(pc11.dim(`Target: ${providers.length} provider(s)`));
3058
+ console.log(`Installing profile ${pc12.bold(profileName)} (${profileSkills.length} skill(s))...`);
3059
+ console.log(pc12.dim(`Target: ${providers.length} provider(s)`));
2451
3060
  }
2452
3061
  const installed = [];
2453
3062
  const failed = [];
@@ -2462,7 +3071,7 @@ async function handleProfileInstall(profileName, providers, isGlobal, format, op
2462
3071
  );
2463
3072
  if (result.success) {
2464
3073
  if (format === "human") {
2465
- console.log(pc11.green(` + ${name}`));
3074
+ console.log(pc12.green(` + ${name}`));
2466
3075
  }
2467
3076
  await recordSkillInstall(
2468
3077
  name,
@@ -2481,7 +3090,7 @@ async function handleProfileInstall(profileName, providers, isGlobal, format, op
2481
3090
  });
2482
3091
  } else {
2483
3092
  if (format === "human") {
2484
- console.log(pc11.yellow(` ! ${name}: ${result.errors.join(", ")}`));
3093
+ console.log(pc12.yellow(` ! ${name}: ${result.errors.join(", ")}`));
2485
3094
  }
2486
3095
  failed.push({
2487
3096
  name,
@@ -2491,7 +3100,7 @@ async function handleProfileInstall(profileName, providers, isGlobal, format, op
2491
3100
  } catch (err) {
2492
3101
  const errorMsg = err instanceof Error ? err.message : String(err);
2493
3102
  if (format === "human") {
2494
- console.log(pc11.red(` x ${name}: ${errorMsg}`));
3103
+ console.log(pc12.red(` x ${name}: ${errorMsg}`));
2495
3104
  }
2496
3105
  failed.push({
2497
3106
  name,
@@ -2525,7 +3134,7 @@ async function handleProfileInstall(profileName, providers, isGlobal, format, op
2525
3134
  }
2526
3135
  } else {
2527
3136
  console.log(`
2528
- ${pc11.green(`${installed.length} installed`)}, ${failed.length > 0 ? pc11.yellow(`${failed.length} failed`) : "0 failed"}`);
3137
+ ${pc12.green(`${installed.length} installed`)}, ${failed.length > 0 ? pc12.yellow(`${failed.length} failed`) : "0 failed"}`);
2529
3138
  if (failed.length > 0) {
2530
3139
  process.exit(1);
2531
3140
  }
@@ -2533,7 +3142,7 @@ ${pc11.green(`${installed.length} installed`)}, ${failed.length > 0 ? pc11.yello
2533
3142
  }
2534
3143
  async function handleMarketplaceSource(source, _providers, _isGlobal, format, operation, mvi) {
2535
3144
  if (format === "human") {
2536
- console.log(pc11.dim(`Searching marketplace for ${source}...`));
3145
+ console.log(pc12.dim(`Searching marketplace for ${source}...`));
2537
3146
  }
2538
3147
  const client = new MarketplaceClient();
2539
3148
  let skill;
@@ -2544,7 +3153,7 @@ async function handleMarketplaceSource(source, _providers, _isGlobal, format, op
2544
3153
  if (format === "json") {
2545
3154
  emitJsonError(operation, mvi, ErrorCodes.NETWORK_ERROR, message, ErrorCategories.TRANSIENT);
2546
3155
  }
2547
- console.error(pc11.red(message));
3156
+ console.error(pc12.red(message));
2548
3157
  return { success: false };
2549
3158
  }
2550
3159
  if (!skill) {
@@ -2552,11 +3161,11 @@ async function handleMarketplaceSource(source, _providers, _isGlobal, format, op
2552
3161
  if (format === "json") {
2553
3162
  emitJsonError(operation, mvi, ErrorCodes.SKILL_NOT_FOUND, message, ErrorCategories.NOT_FOUND);
2554
3163
  }
2555
- console.error(pc11.red(message));
3164
+ console.error(pc12.red(message));
2556
3165
  return { success: false };
2557
3166
  }
2558
3167
  if (format === "human") {
2559
- console.log(` Found: ${pc11.bold(skill.name)} by ${skill.author} (${pc11.dim(skill.repoFullName)})`);
3168
+ console.log(` Found: ${pc12.bold(skill.name)} by ${skill.author} (${pc12.dim(skill.repoFullName)})`);
2560
3169
  }
2561
3170
  const parsed = parseSource(skill.githubUrl);
2562
3171
  if (parsed.type !== "github" || !parsed.owner || !parsed.repo) {
@@ -2564,7 +3173,7 @@ async function handleMarketplaceSource(source, _providers, _isGlobal, format, op
2564
3173
  if (format === "json") {
2565
3174
  emitJsonError(operation, mvi, ErrorCodes.INVALID_FORMAT, message, ErrorCategories.VALIDATION);
2566
3175
  }
2567
- console.error(pc11.red(message));
3176
+ console.error(pc12.red(message));
2568
3177
  return { success: false };
2569
3178
  }
2570
3179
  try {
@@ -2576,7 +3185,7 @@ async function handleMarketplaceSource(source, _providers, _isGlobal, format, op
2576
3185
  for (const subPath of subPathCandidates) {
2577
3186
  try {
2578
3187
  const result = await cloneRepo(parsed.owner, parsed.repo, parsed.ref, subPath);
2579
- if (subPath && !existsSync4(result.localPath)) {
3188
+ if (subPath && !existsSync5(result.localPath)) {
2580
3189
  await result.cleanup();
2581
3190
  continue;
2582
3191
  }
@@ -2604,13 +3213,13 @@ async function handleMarketplaceSource(source, _providers, _isGlobal, format, op
2604
3213
  if (format === "json") {
2605
3214
  emitJsonError(operation, mvi, ErrorCodes.NETWORK_ERROR, message, ErrorCategories.TRANSIENT);
2606
3215
  }
2607
- console.error(pc11.red(message));
3216
+ console.error(pc12.red(message));
2608
3217
  return { success: false };
2609
3218
  }
2610
3219
  }
2611
3220
 
2612
3221
  // src/commands/skills/remove.ts
2613
- import pc12 from "picocolors";
3222
+ import pc13 from "picocolors";
2614
3223
  function registerSkillsRemove(parent) {
2615
3224
  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(async (name, opts) => {
2616
3225
  const operation = "skills.remove";
@@ -2649,14 +3258,14 @@ function registerSkillsRemove(parent) {
2649
3258
  return;
2650
3259
  }
2651
3260
  if (removed.length > 0) {
2652
- console.log(pc12.green(`\u2713 Removed ${pc12.bold(name)} from: ${removed.join(", ")}`));
3261
+ console.log(pc13.green(`\u2713 Removed ${pc13.bold(name)} from: ${removed.join(", ")}`));
2653
3262
  await removeSkillFromLock(name);
2654
3263
  } else {
2655
- console.log(pc12.yellow(`Skill ${name} not found in any provider.`));
3264
+ console.log(pc13.yellow(`Skill ${name} not found in any provider.`));
2656
3265
  }
2657
3266
  if (result.errors.length > 0) {
2658
3267
  for (const err of result.errors) {
2659
- console.log(pc12.red(` ${err}`));
3268
+ console.log(pc13.red(` ${err}`));
2660
3269
  }
2661
3270
  }
2662
3271
  } else {
@@ -2669,7 +3278,7 @@ function registerSkillsRemove(parent) {
2669
3278
  count: { removed: 0, total: 0 }
2670
3279
  });
2671
3280
  } else {
2672
- console.log(pc12.dim("No skills installed."));
3281
+ console.log(pc13.dim("No skills installed."));
2673
3282
  }
2674
3283
  return;
2675
3284
  }
@@ -2682,11 +3291,11 @@ function registerSkillsRemove(parent) {
2682
3291
  });
2683
3292
  return;
2684
3293
  }
2685
- console.log(pc12.bold("Installed skills:"));
3294
+ console.log(pc13.bold("Installed skills:"));
2686
3295
  for (const s of skills) {
2687
3296
  console.log(` ${s}`);
2688
3297
  }
2689
- console.log(pc12.dim("\nUse: caamp skills remove <name>"));
3298
+ console.log(pc13.dim("\nUse: caamp skills remove <name>"));
2690
3299
  }
2691
3300
  });
2692
3301
  }
@@ -2694,7 +3303,7 @@ function registerSkillsRemove(parent) {
2694
3303
  // src/commands/skills/list.ts
2695
3304
  import { randomUUID as randomUUID4 } from "crypto";
2696
3305
  import { resolveOutputFormat as resolveOutputFormat3 } from "@cleocode/lafs-protocol";
2697
- import pc13 from "picocolors";
3306
+ import pc14 from "picocolors";
2698
3307
  function registerSkillsList(parent) {
2699
3308
  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) => {
2700
3309
  const operation = "skills.list";
@@ -2721,7 +3330,7 @@ function registerSkillsList(parent) {
2721
3330
  agent: opts.agent
2722
3331
  });
2723
3332
  } else {
2724
- console.error(pc13.red(message));
3333
+ console.error(pc14.red(message));
2725
3334
  }
2726
3335
  process.exit(1);
2727
3336
  }
@@ -2749,19 +3358,19 @@ function registerSkillsList(parent) {
2749
3358
  return;
2750
3359
  }
2751
3360
  if (skills.length === 0) {
2752
- console.log(pc13.dim("No skills found."));
3361
+ console.log(pc14.dim("No skills found."));
2753
3362
  return;
2754
3363
  }
2755
- console.log(pc13.bold(`
3364
+ console.log(pc14.bold(`
2756
3365
  ${skills.length} skill(s) found:
2757
3366
  `));
2758
3367
  skills.forEach((skill, index) => {
2759
3368
  const num = (index + 1).toString().padStart(2);
2760
- console.log(` ${pc13.cyan(num)}. ${pc13.bold(skill.name.padEnd(30))} ${pc13.dim(skill.metadata?.description ?? "")}`);
3369
+ console.log(` ${pc14.cyan(num)}. ${pc14.bold(skill.name.padEnd(30))} ${pc14.dim(skill.metadata?.description ?? "")}`);
2761
3370
  });
2762
- console.log(pc13.dim(`
3371
+ console.log(pc14.dim(`
2763
3372
  Install with: caamp skills install <name>`));
2764
- console.log(pc13.dim(`Remove with: caamp skills remove <name>`));
3373
+ console.log(pc14.dim(`Remove with: caamp skills remove <name>`));
2765
3374
  });
2766
3375
  }
2767
3376
  function buildEnvelope5(operation, mvi, result, error) {
@@ -2801,7 +3410,7 @@ import { randomUUID as randomUUID5 } from "crypto";
2801
3410
  import {
2802
3411
  resolveOutputFormat as resolveOutputFormat4
2803
3412
  } from "@cleocode/lafs-protocol";
2804
- import pc14 from "picocolors";
3413
+ import pc15 from "picocolors";
2805
3414
  var SkillsFindValidationError = class extends Error {
2806
3415
  code;
2807
3416
  constructor(code, message) {
@@ -2827,7 +3436,7 @@ function registerSkillsFind(parent) {
2827
3436
  if (opts.json) {
2828
3437
  emitJsonError4(operation, mvi, "E_FORMAT_CONFLICT", message, "VALIDATION");
2829
3438
  } else {
2830
- console.error(pc14.red(message));
3439
+ console.error(pc15.red(message));
2831
3440
  }
2832
3441
  process.exit(1);
2833
3442
  }
@@ -2888,19 +3497,19 @@ function registerSkillsFind(parent) {
2888
3497
  query: query ?? null
2889
3498
  });
2890
3499
  } else {
2891
- console.error(pc14.red(`Recommendation failed: ${message}`));
3500
+ console.error(pc15.red(`Recommendation failed: ${message}`));
2892
3501
  }
2893
3502
  process.exit(1);
2894
3503
  }
2895
3504
  }
2896
3505
  if (!query) {
2897
- console.log(pc14.dim("Usage: caamp skills find <query>"));
3506
+ console.log(pc15.dim("Usage: caamp skills find <query>"));
2898
3507
  return;
2899
3508
  }
2900
3509
  const limit = parseInt(opts.limit, 10);
2901
3510
  const client = new MarketplaceClient();
2902
3511
  if (format === "human") {
2903
- console.log(pc14.dim(`Searching marketplaces for "${query}"...
3512
+ console.log(pc15.dim(`Searching marketplaces for "${query}"...
2904
3513
  `));
2905
3514
  }
2906
3515
  let results;
@@ -2914,7 +3523,7 @@ function registerSkillsFind(parent) {
2914
3523
  limit
2915
3524
  });
2916
3525
  } else {
2917
- console.error(pc14.red(`Marketplace search failed: ${message}`));
3526
+ console.error(pc15.red(`Marketplace search failed: ${message}`));
2918
3527
  }
2919
3528
  process.exit(1);
2920
3529
  }
@@ -2934,21 +3543,21 @@ function registerSkillsFind(parent) {
2934
3543
  return;
2935
3544
  }
2936
3545
  if (results.length === 0) {
2937
- console.log(pc14.yellow("No results found."));
3546
+ console.log(pc15.yellow("No results found."));
2938
3547
  return;
2939
3548
  }
2940
- console.log(pc14.dim(`Found ${results.length} result(s) for "${query}":
3549
+ console.log(pc15.dim(`Found ${results.length} result(s) for "${query}":
2941
3550
  `));
2942
3551
  results.forEach((skill, index) => {
2943
3552
  const num = (index + 1).toString().padStart(2);
2944
- const stars = skill.stars > 0 ? pc14.yellow(`\u2605 ${formatStars(skill.stars)}`) : "";
2945
- console.log(` ${pc14.cyan(num)}. ${pc14.bold(skill.scopedName)} ${stars}`);
2946
- console.log(` ${pc14.dim(skill.description?.slice(0, 80) ?? "")}`);
2947
- console.log(` ${pc14.dim(`from ${skill.source}`)}`);
3553
+ const stars = skill.stars > 0 ? pc15.yellow(`\u2605 ${formatStars(skill.stars)}`) : "";
3554
+ console.log(` ${pc15.cyan(num)}. ${pc15.bold(skill.scopedName)} ${stars}`);
3555
+ console.log(` ${pc15.dim(skill.description?.slice(0, 80) ?? "")}`);
3556
+ console.log(` ${pc15.dim(`from ${skill.source}`)}`);
2948
3557
  console.log();
2949
3558
  });
2950
- console.log(pc14.dim("Install with: caamp skills install <name>"));
2951
- console.log(pc14.dim("Or select by number: caamp skills install <n>"));
3559
+ console.log(pc15.dim("Install with: caamp skills install <name>"));
3560
+ console.log(pc15.dim("Or select by number: caamp skills install <n>"));
2952
3561
  });
2953
3562
  }
2954
3563
  function formatStars(n) {
@@ -3062,7 +3671,7 @@ function emitJsonError4(operation, mvi, code, message, category, details = {}) {
3062
3671
  }
3063
3672
 
3064
3673
  // src/commands/skills/check.ts
3065
- import pc15 from "picocolors";
3674
+ import pc16 from "picocolors";
3066
3675
  function registerSkillsCheck(parent) {
3067
3676
  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) => {
3068
3677
  const operation = "skills.check";
@@ -3089,12 +3698,12 @@ function registerSkillsCheck(parent) {
3089
3698
  total: 0
3090
3699
  });
3091
3700
  } else {
3092
- console.log(pc15.dim("No tracked skills."));
3701
+ console.log(pc16.dim("No tracked skills."));
3093
3702
  }
3094
3703
  return;
3095
3704
  }
3096
3705
  if (format === "human") {
3097
- console.log(pc15.dim(`Checking ${entries.length} skill(s) for updates...
3706
+ console.log(pc16.dim(`Checking ${entries.length} skill(s) for updates...
3098
3707
  `));
3099
3708
  }
3100
3709
  const skillResults = [];
@@ -3130,37 +3739,37 @@ function registerSkillsCheck(parent) {
3130
3739
  for (const r of skillResults) {
3131
3740
  let statusLabel;
3132
3741
  if (r.hasUpdate) {
3133
- statusLabel = pc15.yellow("update available");
3742
+ statusLabel = pc16.yellow("update available");
3134
3743
  } else if (r.currentVersion !== "unknown") {
3135
- statusLabel = pc15.green("up to date");
3744
+ statusLabel = pc16.green("up to date");
3136
3745
  } else {
3137
- statusLabel = pc15.dim("unknown");
3746
+ statusLabel = pc16.dim("unknown");
3138
3747
  }
3139
- console.log(` ${pc15.bold(r.name.padEnd(30))} ${statusLabel}`);
3748
+ console.log(` ${pc16.bold(r.name.padEnd(30))} ${statusLabel}`);
3140
3749
  if (r.currentVersion !== "unknown" || r.latestVersion !== "unknown") {
3141
3750
  const current = r.currentVersion !== "unknown" ? r.currentVersion.slice(0, 12) : "?";
3142
3751
  const latest = r.latestVersion !== "unknown" ? r.latestVersion : "?";
3143
3752
  if (r.hasUpdate) {
3144
- console.log(` ${pc15.dim("current:")} ${current} ${pc15.dim("->")} ${pc15.cyan(latest)}`);
3753
+ console.log(` ${pc16.dim("current:")} ${current} ${pc16.dim("->")} ${pc16.cyan(latest)}`);
3145
3754
  } else {
3146
- console.log(` ${pc15.dim("version:")} ${current}`);
3755
+ console.log(` ${pc16.dim("version:")} ${current}`);
3147
3756
  }
3148
3757
  }
3149
- console.log(` ${pc15.dim(`source: ${r.source}`)}`);
3150
- console.log(` ${pc15.dim(`agents: ${r.agents.join(", ")}`)}`);
3758
+ console.log(` ${pc16.dim(`source: ${r.source}`)}`);
3759
+ console.log(` ${pc16.dim(`agents: ${r.agents.join(", ")}`)}`);
3151
3760
  console.log();
3152
3761
  }
3153
3762
  if (updatesAvailable > 0) {
3154
- console.log(pc15.yellow(`${updatesAvailable} update(s) available.`));
3155
- console.log(pc15.dim("Run `caamp skills update` to update all."));
3763
+ console.log(pc16.yellow(`${updatesAvailable} update(s) available.`));
3764
+ console.log(pc16.dim("Run `caamp skills update` to update all."));
3156
3765
  } else {
3157
- console.log(pc15.green("All skills are up to date."));
3766
+ console.log(pc16.green("All skills are up to date."));
3158
3767
  }
3159
3768
  });
3160
3769
  }
3161
3770
 
3162
3771
  // src/commands/skills/update.ts
3163
- import pc16 from "picocolors";
3772
+ import pc17 from "picocolors";
3164
3773
  function registerSkillsUpdate(parent) {
3165
3774
  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) => {
3166
3775
  const operation = "skills.update";
@@ -3188,12 +3797,12 @@ function registerSkillsUpdate(parent) {
3188
3797
  count: { updated: 0, failed: 0, skipped: 0 }
3189
3798
  });
3190
3799
  } else {
3191
- console.log(pc16.dim("No tracked skills to update."));
3800
+ console.log(pc17.dim("No tracked skills to update."));
3192
3801
  }
3193
3802
  return;
3194
3803
  }
3195
3804
  if (format === "human") {
3196
- console.log(pc16.dim(`Checking ${entries.length} skill(s) for updates...`));
3805
+ console.log(pc17.dim(`Checking ${entries.length} skill(s) for updates...`));
3197
3806
  }
3198
3807
  const outdated = [];
3199
3808
  for (const [name] of entries) {
@@ -3215,29 +3824,29 @@ function registerSkillsUpdate(parent) {
3215
3824
  count: { updated: 0, failed: 0, skipped: 0 }
3216
3825
  });
3217
3826
  } else {
3218
- console.log(pc16.green("\nAll skills are up to date."));
3827
+ console.log(pc17.green("\nAll skills are up to date."));
3219
3828
  }
3220
3829
  return;
3221
3830
  }
3222
3831
  if (format === "human") {
3223
- console.log(pc16.yellow(`
3832
+ console.log(pc17.yellow(`
3224
3833
  ${outdated.length} skill(s) have updates available:
3225
3834
  `));
3226
3835
  for (const skill of outdated) {
3227
3836
  const current = skill.currentVersion?.slice(0, 12) ?? "?";
3228
3837
  const latest = skill.latestVersion ?? "?";
3229
- console.log(` ${pc16.bold(skill.name)} ${pc16.dim(current)} ${pc16.dim("->")} ${pc16.cyan(latest)}`);
3838
+ console.log(` ${pc17.bold(skill.name)} ${pc17.dim(current)} ${pc17.dim("->")} ${pc17.cyan(latest)}`);
3230
3839
  }
3231
3840
  }
3232
3841
  if (!opts.yes && format === "human") {
3233
3842
  const readline = await import("readline");
3234
3843
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
3235
- const answer = await new Promise((resolve) => {
3236
- rl.question(pc16.dim("\nProceed with update? [y/N] "), resolve);
3844
+ const answer = await new Promise((resolve2) => {
3845
+ rl.question(pc17.dim("\nProceed with update? [y/N] "), resolve2);
3237
3846
  });
3238
3847
  rl.close();
3239
3848
  if (answer.toLowerCase() !== "y" && answer.toLowerCase() !== "yes") {
3240
- console.log(pc16.dim("Update cancelled."));
3849
+ console.log(pc17.dim("Update cancelled."));
3241
3850
  return;
3242
3851
  }
3243
3852
  }
@@ -3251,7 +3860,7 @@ ${outdated.length} skill(s) have updates available:
3251
3860
  const entry = tracked[skill.name];
3252
3861
  if (!entry) continue;
3253
3862
  if (format === "human") {
3254
- console.log(pc16.dim(`Updating ${pc16.bold(skill.name)}...`));
3863
+ console.log(pc17.dim(`Updating ${pc17.bold(skill.name)}...`));
3255
3864
  }
3256
3865
  try {
3257
3866
  const parsed = parseSource(entry.source);
@@ -3267,7 +3876,7 @@ ${outdated.length} skill(s) have updates available:
3267
3876
  cleanup = result.cleanup;
3268
3877
  } else {
3269
3878
  if (format === "human") {
3270
- console.log(pc16.yellow(` Skipped ${skill.name}: source type "${parsed.type}" does not support auto-update`));
3879
+ console.log(pc17.yellow(` Skipped ${skill.name}: source type "${parsed.type}" does not support auto-update`));
3271
3880
  }
3272
3881
  skipped.push(skill.name);
3273
3882
  continue;
@@ -3276,7 +3885,7 @@ ${outdated.length} skill(s) have updates available:
3276
3885
  const providers = entry.agents.map((a) => getProvider(a)).filter((p) => p !== void 0);
3277
3886
  if (providers.length === 0) {
3278
3887
  if (format === "human") {
3279
- console.log(pc16.yellow(` Skipped ${skill.name}: no valid providers found`));
3888
+ console.log(pc17.yellow(` Skipped ${skill.name}: no valid providers found`));
3280
3889
  }
3281
3890
  skipped.push(skill.name);
3282
3891
  continue;
@@ -3301,18 +3910,18 @@ ${outdated.length} skill(s) have updates available:
3301
3910
  skill.latestVersion
3302
3911
  );
3303
3912
  if (format === "human") {
3304
- console.log(pc16.green(` Updated ${pc16.bold(skill.name)}`));
3913
+ console.log(pc17.green(` Updated ${pc17.bold(skill.name)}`));
3305
3914
  }
3306
3915
  updated.push(skill.name);
3307
3916
  } else {
3308
3917
  if (format === "human") {
3309
- console.log(pc16.red(` Failed to update ${skill.name}: no agents linked`));
3918
+ console.log(pc17.red(` Failed to update ${skill.name}: no agents linked`));
3310
3919
  }
3311
3920
  failed.push({ name: skill.name, error: "no agents linked" });
3312
3921
  }
3313
3922
  if (installResult.errors.length > 0 && format === "human") {
3314
3923
  for (const err of installResult.errors) {
3315
- console.log(pc16.yellow(` ${err}`));
3924
+ console.log(pc17.yellow(` ${err}`));
3316
3925
  }
3317
3926
  }
3318
3927
  } finally {
@@ -3321,7 +3930,7 @@ ${outdated.length} skill(s) have updates available:
3321
3930
  } catch (err) {
3322
3931
  const msg = err instanceof Error ? err.message : String(err);
3323
3932
  if (format === "human") {
3324
- console.log(pc16.red(` Failed to update ${skill.name}: ${msg}`));
3933
+ console.log(pc17.red(` Failed to update ${skill.name}: ${msg}`));
3325
3934
  }
3326
3935
  failed.push({ name: skill.name, error: msg });
3327
3936
  }
@@ -3341,19 +3950,19 @@ ${outdated.length} skill(s) have updates available:
3341
3950
  }
3342
3951
  console.log();
3343
3952
  if (updated.length > 0) {
3344
- console.log(pc16.green(`Updated ${updated.length} skill(s).`));
3953
+ console.log(pc17.green(`Updated ${updated.length} skill(s).`));
3345
3954
  }
3346
3955
  if (failed.length > 0) {
3347
- console.log(pc16.red(`Failed to update ${failed.length} skill(s).`));
3956
+ console.log(pc17.red(`Failed to update ${failed.length} skill(s).`));
3348
3957
  }
3349
3958
  });
3350
3959
  }
3351
3960
 
3352
3961
  // src/commands/skills/init.ts
3353
- import { existsSync as existsSync5 } from "fs";
3962
+ import { existsSync as existsSync6 } from "fs";
3354
3963
  import { mkdir, writeFile } from "fs/promises";
3355
3964
  import { join as join5 } from "path";
3356
- import pc17 from "picocolors";
3965
+ import pc18 from "picocolors";
3357
3966
  function registerSkillsInit(parent) {
3358
3967
  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(async (name, opts) => {
3359
3968
  const operation = "skills.init";
@@ -3372,14 +3981,14 @@ function registerSkillsInit(parent) {
3372
3981
  }
3373
3982
  const skillName = name ?? "my-skill";
3374
3983
  const skillDir = join5(opts.dir, skillName);
3375
- if (existsSync5(skillDir)) {
3984
+ if (existsSync6(skillDir)) {
3376
3985
  const message = `Directory already exists: ${skillDir}`;
3377
3986
  if (format === "json") {
3378
3987
  emitJsonError(operation, mvi, ErrorCodes.INVALID_CONSTRAINT, message, ErrorCategories.CONFLICT, {
3379
3988
  path: skillDir
3380
3989
  });
3381
3990
  } else {
3382
- console.error(pc17.red(message));
3991
+ console.error(pc18.red(message));
3383
3992
  }
3384
3993
  process.exit(1);
3385
3994
  }
@@ -3418,22 +4027,22 @@ Show example inputs and expected outputs.
3418
4027
  outputSuccess(operation, mvi, result);
3419
4028
  return;
3420
4029
  }
3421
- console.log(pc17.green(`\u2713 Created skill template: ${skillDir}/SKILL.md`));
3422
- console.log(pc17.dim("\nNext steps:"));
3423
- console.log(pc17.dim(" 1. Edit SKILL.md with your instructions"));
3424
- console.log(pc17.dim(` 2. Validate: caamp skills validate ${join5(skillDir, "SKILL.md")}`));
3425
- console.log(pc17.dim(` 3. Install: caamp skills install ${skillDir}`));
4030
+ console.log(pc18.green(`\u2713 Created skill template: ${skillDir}/SKILL.md`));
4031
+ console.log(pc18.dim("\nNext steps:"));
4032
+ console.log(pc18.dim(" 1. Edit SKILL.md with your instructions"));
4033
+ console.log(pc18.dim(` 2. Validate: caamp skills validate ${join5(skillDir, "SKILL.md")}`));
4034
+ console.log(pc18.dim(` 3. Install: caamp skills install ${skillDir}`));
3426
4035
  });
3427
4036
  }
3428
4037
 
3429
4038
  // src/commands/skills/audit.ts
3430
- import { existsSync as existsSync6, statSync } from "fs";
3431
- import pc18 from "picocolors";
4039
+ import { existsSync as existsSync7, statSync } from "fs";
4040
+ import pc19 from "picocolors";
3432
4041
  function registerSkillsAudit(parent) {
3433
4042
  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) => {
3434
4043
  const operation = "skills.audit";
3435
4044
  const mvi = "standard";
3436
- if (!existsSync6(path)) {
4045
+ if (!existsSync7(path)) {
3437
4046
  const message = `Path not found: ${path}`;
3438
4047
  if (opts.sarif) {
3439
4048
  console.error(JSON.stringify({
@@ -3517,7 +4126,7 @@ function registerSkillsAudit(parent) {
3517
4126
  outputSuccess(operation, mvi, summary2);
3518
4127
  return;
3519
4128
  }
3520
- console.log(pc18.dim("No SKILL.md files found to scan."));
4129
+ console.log(pc19.dim("No SKILL.md files found to scan."));
3521
4130
  return;
3522
4131
  }
3523
4132
  const summary = {
@@ -3551,21 +4160,21 @@ function registerSkillsAudit(parent) {
3551
4160
  }
3552
4161
  let totalFindings = 0;
3553
4162
  for (const result of results) {
3554
- const icon = result.passed ? pc18.green("\u2713") : pc18.red("\u2717");
4163
+ const icon = result.passed ? pc19.green("\u2713") : pc19.red("\u2717");
3555
4164
  console.log(`
3556
- ${icon} ${pc18.bold(result.file)} (score: ${result.score}/100)`);
4165
+ ${icon} ${pc19.bold(result.file)} (score: ${result.score}/100)`);
3557
4166
  if (result.findings.length === 0) {
3558
- console.log(pc18.dim(" No issues found."));
4167
+ console.log(pc19.dim(" No issues found."));
3559
4168
  continue;
3560
4169
  }
3561
4170
  totalFindings += result.findings.length;
3562
4171
  for (const f of result.findings) {
3563
- const sev = f.rule.severity === "critical" ? pc18.red(f.rule.severity) : f.rule.severity === "high" ? pc18.red(f.rule.severity) : f.rule.severity === "medium" ? pc18.yellow(f.rule.severity) : pc18.dim(f.rule.severity);
4172
+ const sev = f.rule.severity === "critical" ? pc19.red(f.rule.severity) : f.rule.severity === "high" ? pc19.red(f.rule.severity) : f.rule.severity === "medium" ? pc19.yellow(f.rule.severity) : pc19.dim(f.rule.severity);
3564
4173
  console.log(` ${sev.padEnd(20)} ${f.rule.id} ${f.rule.name}`);
3565
- console.log(` ${pc18.dim(`L${f.line}: ${f.context.slice(0, 80)}`)}`);
4174
+ console.log(` ${pc19.dim(`L${f.line}: ${f.context.slice(0, 80)}`)}`);
3566
4175
  }
3567
4176
  }
3568
- console.log(pc18.bold(`
4177
+ console.log(pc19.bold(`
3569
4178
  ${results.length} file(s) scanned, ${totalFindings} finding(s)`));
3570
4179
  if (!allPassed) {
3571
4180
  process.exit(1);
@@ -3575,7 +4184,7 @@ ${results.length} file(s) scanned, ${totalFindings} finding(s)`));
3575
4184
 
3576
4185
  // src/commands/skills/validate.ts
3577
4186
  import { resolveOutputFormat as resolveOutputFormat5 } from "@cleocode/lafs-protocol";
3578
- import pc19 from "picocolors";
4187
+ import pc20 from "picocolors";
3579
4188
  function registerSkillsValidate(parent) {
3580
4189
  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) => {
3581
4190
  const operation = "skills.validate";
@@ -3602,7 +4211,7 @@ function registerSkillsValidate(parent) {
3602
4211
  path
3603
4212
  });
3604
4213
  } else {
3605
- console.error(pc19.red(message));
4214
+ console.error(pc20.red(message));
3606
4215
  }
3607
4216
  process.exit(1);
3608
4217
  }
@@ -3624,12 +4233,12 @@ function registerSkillsValidate(parent) {
3624
4233
  console.log(JSON.stringify(envelope, null, 2));
3625
4234
  } else {
3626
4235
  if (result.valid) {
3627
- console.log(pc19.green(`\u2713 ${path} is valid`));
4236
+ console.log(pc20.green(`\u2713 ${path} is valid`));
3628
4237
  } else {
3629
- console.log(pc19.red(`\u2717 ${path} has validation errors`));
4238
+ console.log(pc20.red(`\u2717 ${path} has validation errors`));
3630
4239
  }
3631
4240
  for (const issue of result.issues) {
3632
- const icon = issue.level === "error" ? pc19.red("\u2717") : pc19.yellow("!");
4241
+ const icon = issue.level === "error" ? pc20.red("\u2717") : pc20.yellow("!");
3633
4242
  console.log(` ${icon} [${issue.field}] ${issue.message}`);
3634
4243
  }
3635
4244
  }