@ulpi/cli 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/LICENSE +21 -0
  2. package/dist/{auth-PN7TMQHV-2W4ICG64.js → auth-FWM7MM4Q-VZC3U2XZ.js} +1 -1
  3. package/dist/{auth-ECQ3IB4E.js → auth-HDK7ECJL.js} +2 -1
  4. package/dist/{chunk-3SBPZRB5.js → chunk-3BCW6ABU.js} +402 -142
  5. package/dist/{chunk-JGBXM5NC.js → chunk-3WB5CXH4.js} +180 -5
  6. package/dist/{chunk-2HEE5OKX.js → chunk-4UCJIAOU.js} +2 -2
  7. package/dist/chunk-4XTHZVDS.js +109 -0
  8. package/dist/chunk-4ZPOZULQ.js +6522 -0
  9. package/dist/{chunk-SIAQVRKG.js → chunk-5MI5GIXM.js} +48 -2
  10. package/dist/{chunk-KLEASXUR.js → chunk-6ZL6NXMV.js} +1 -1
  11. package/dist/chunk-76D3BYJD.js +221 -0
  12. package/dist/{chunk-ZLYRPD7I.js → chunk-AWOSRA5F.js} +1 -1
  13. package/dist/{chunk-PDR55ZNW.js → chunk-BFEKZZHM.js} +274 -57
  14. package/dist/chunk-C7CLUQI6.js +1286 -0
  15. package/dist/{chunk-7AL4DOEJ.js → chunk-E3B5NROU.js} +7 -7
  16. package/dist/chunk-EJ7TW77N.js +1418 -0
  17. package/dist/{chunk-5J6NLQUN.js → chunk-IV6MWETF.js} +383 -168
  18. package/dist/chunk-IZPJHSPX.js +1478 -0
  19. package/dist/chunk-JLHNLM3C.js +228 -0
  20. package/dist/{chunk-BZL5H4YQ.js → chunk-KYYI23AQ.js} +2 -2
  21. package/dist/{chunk-2CLNOKPA.js → chunk-RSFJ6QSR.js} +18 -0
  22. package/dist/chunk-S6ANCSYO.js +1271 -0
  23. package/dist/chunk-SEU7WWNQ.js +1251 -0
  24. package/dist/chunk-SNQ7NAIS.js +453 -0
  25. package/dist/{ulpi-RMMCUAGP-JCJ273T6.js → chunk-TSLDGT5O.js} +73 -35
  26. package/dist/{chunk-SPOI23SB.js → chunk-UXHCHOWQ.js} +83 -62
  27. package/dist/chunk-V2H5D6Y3.js +146 -0
  28. package/dist/{chunk-QJ5GSMEC.js → chunk-VVEDXI7E.js} +2 -1
  29. package/dist/chunk-VXH5Y4FO.js +6761 -0
  30. package/dist/chunk-WED4LM5N.js +322 -0
  31. package/dist/{chunk-74WVVWJ4.js → chunk-YOKL7RB5.js} +184 -15
  32. package/dist/chunk-Z53CAR7G.js +298 -0
  33. package/dist/ci-X3U2W4HC.js +854 -0
  34. package/dist/cloud-2F3NLVHN.js +274 -0
  35. package/dist/{codemap-RKSD4MIE.js → codemap-XNGMAF3F.js} +37 -37
  36. package/dist/codex-MB5YTMRT.js +132 -0
  37. package/dist/{config-EGAXXCGL.js → config-OOELBYTH.js} +1 -1
  38. package/dist/dist-2BJYR5EI.js +59 -0
  39. package/dist/dist-2K7IEVTA.js +43 -0
  40. package/dist/dist-3EIQTZHT.js +1380 -0
  41. package/dist/{dist-YA2BWZB2.js → dist-4U5L2X2C.js} +2 -2
  42. package/dist/{dist-UKMCJBB2.js → dist-54KAMNLO.js} +16 -15
  43. package/dist/dist-6M4MZWZW.js +58 -0
  44. package/dist/dist-6X576SU2.js +27 -0
  45. package/dist/dist-7QOEYLFX.js +103 -0
  46. package/dist/dist-AYBGHEDY.js +2541 -0
  47. package/dist/dist-EK45QNEM.js +45 -0
  48. package/dist/{dist-CS2VKNYS.js → dist-FKFEJRPX.js} +16 -15
  49. package/dist/dist-GTEJUBBT.js +66 -0
  50. package/dist/dist-HA74OKJZ.js +40 -0
  51. package/dist/dist-HU5RZAON.js +48 -0
  52. package/dist/dist-IYE3OBRB.js +374 -0
  53. package/dist/{dist-GJYT2OQV.js → dist-JLU26AB6.js} +12 -9
  54. package/dist/{dist-6G7JC2RA.js → dist-KUCI6JFE.js} +49 -9
  55. package/dist/dist-NUEMFZFL.js +33 -0
  56. package/dist/{dist-RKOGLK7R.js → dist-NUXMDXZ3.js} +31 -3
  57. package/dist/{dist-QAU3LGJN.js → dist-YCNWHSLN.js} +15 -5
  58. package/dist/{dist-CB5D5LMO.js → dist-YFFG2ZD6.js} +9 -16
  59. package/dist/dist-ZG4OKCSR.js +15 -0
  60. package/dist/doctor-SI4LLLDZ.js +345 -0
  61. package/dist/{export-import-4A5MWLIA.js → export-import-JFQH4KSJ.js} +1 -1
  62. package/dist/{history-3MOBX4MA.js → history-5NE46ZAH.js} +7 -7
  63. package/dist/hooks-installer-UN5JZLDQ.js +19 -0
  64. package/dist/index.js +395 -619
  65. package/dist/{init-6CH4HV5T.js → init-5FK3VKRT.js} +79 -13
  66. package/dist/job-HIDMAFW2.js +376 -0
  67. package/dist/jobs.memory-PLMMSFHB-VBECCTHN.js +33 -0
  68. package/dist/kiro-VMUHDFGK.js +153 -0
  69. package/dist/{launchd-LF2QMSKZ.js → launchd-6AWT54HR.js} +9 -17
  70. package/dist/mcp-PDUD7SGP.js +249 -0
  71. package/dist/mcp-installer-PQU3XOGO.js +259 -0
  72. package/dist/mcp-setup-OA7IB3H3.js +263 -0
  73. package/dist/{memory-Y6OZTXJ2.js → memory-ZNAEAK3B.js} +17 -17
  74. package/dist/{ollama-3XCUZMZT-FYKHW4TZ.js → ollama-3XCUZMZT-4JMH6B7P.js} +1 -1
  75. package/dist/{openai-E7G2YAHU-UYY4ZWON.js → openai-E7G2YAHU-T3HMBPH7.js} +2 -2
  76. package/dist/portal-JYWVHXDU.js +210 -0
  77. package/dist/prd-Q4J5NVAR.js +408 -0
  78. package/dist/repos-WWZXNN3P.js +271 -0
  79. package/dist/review-integration-5WHEJU2A.js +14 -0
  80. package/dist/{rules-E427DKYJ.js → rules-Y4VSOY5Y.js} +3 -3
  81. package/dist/run-VPNXEIBY.js +687 -0
  82. package/dist/server-COL4AXKU-P7S7NNF6.js +11 -0
  83. package/dist/server-KKSETHDV-XSSLEENT.js +20 -0
  84. package/dist/{skills-CX73O3IV.js → skills-QEYU2N27.js} +4 -2
  85. package/dist/start-JYOEL7AJ.js +303 -0
  86. package/dist/{status-4DFHDJMN.js → status-BHQYYGAL.js} +2 -2
  87. package/dist/{templates-U7T6MARD.js → templates-CBRUJ66V.js} +4 -3
  88. package/dist/tui-DP7736EX.js +61 -0
  89. package/dist/ulpi-5EN6JCAS-LFE3WSL4.js +10 -0
  90. package/dist/{uninstall-6SW35IK4.js → uninstall-ICUV6DDV.js} +3 -3
  91. package/dist/{update-M6IBJNYP.js → update-7ZMAYRBH.js} +3 -3
  92. package/dist/{version-checker-Q6YTYAGP.js → version-checker-4ZFMZA7Y.js} +2 -2
  93. package/package.json +39 -31
  94. package/dist/chunk-2MZER6ND.js +0 -415
  95. package/dist/chunk-2VYFVYJL.js +0 -4273
  96. package/dist/chunk-6OCEY7JY.js +0 -422
  97. package/dist/chunk-7LXY5UVC.js +0 -330
  98. package/dist/chunk-B55DDP24.js +0 -136
  99. package/dist/chunk-JWUUVXIV.js +0 -13694
  100. package/dist/chunk-MIAQVCFW.js +0 -39
  101. package/dist/chunk-YM2HV4IA.js +0 -505
  102. package/dist/ci-STSL2LSP.js +0 -370
  103. package/dist/mcp-installer-NQCGKQ23.js +0 -124
  104. package/dist/projects-ATHDD3D6.js +0 -271
  105. package/dist/review-ADUPV3PN.js +0 -152
  106. package/dist/server-USLHY6GH-AEOJC5ST.js +0 -18
  107. package/dist/server-X5P6WH2M-7K2RY34N.js +0 -11
  108. package/dist/skills/ulpi-generate-guardian/SKILL.md +0 -750
  109. package/dist/skills/ulpi-generate-guardian/references/framework-rules.md +0 -849
  110. package/dist/skills/ulpi-generate-guardian/references/language-rules.md +0 -591
  111. package/dist/ui-OWXZ3YSR.js +0 -167
  112. package/dist/ui.html +0 -698
@@ -0,0 +1,153 @@
1
+ import {
2
+ getKiroStatus,
3
+ installKiroHooks,
4
+ installKiroSkills,
5
+ uninstallKiro
6
+ } from "./chunk-WED4LM5N.js";
7
+ import "./chunk-IZPJHSPX.js";
8
+ import {
9
+ convertClaudeAgentsToKiro,
10
+ convertClaudeSkillsToKiro
11
+ } from "./chunk-SNQ7NAIS.js";
12
+ import "./chunk-4ZPOZULQ.js";
13
+ import "./chunk-5MI5GIXM.js";
14
+ import "./chunk-C7CLUQI6.js";
15
+ import "./chunk-YOKL7RB5.js";
16
+ import "./chunk-KIKPIH6N.js";
17
+ import "./chunk-4VNS5WPM.js";
18
+
19
+ // src/commands/kiro.ts
20
+ import chalk from "chalk";
21
+ function runKiro(args, projectDir) {
22
+ const subcommand = args[0];
23
+ switch (subcommand) {
24
+ case "install":
25
+ return handleInstall(args.slice(1), projectDir);
26
+ case "convert":
27
+ return handleConvert(args.slice(1), projectDir);
28
+ case "uninstall":
29
+ return handleUninstall(projectDir);
30
+ case "status":
31
+ return handleStatus(projectDir);
32
+ default:
33
+ printUsage();
34
+ }
35
+ }
36
+ function handleInstall(args, projectDir) {
37
+ const mode = args.includes("--patch-default") ? "default" : "agent";
38
+ const skipConvert = args.includes("--no-convert");
39
+ console.log(chalk.bold("\nInstalling ULPI for Kiro CLI\n"));
40
+ const { file, agent } = installKiroHooks(mode);
41
+ console.log(chalk.green(`\u2713 Agent config: ${agent}`));
42
+ console.log(chalk.dim(` ${file}`));
43
+ const skillCount = installKiroSkills(projectDir);
44
+ if (skillCount > 0) {
45
+ console.log(chalk.green(`\u2713 Installed ${skillCount} bundled skill(s) to .kiro/skills/`));
46
+ } else {
47
+ console.log(chalk.dim(" Bundled skills already installed"));
48
+ }
49
+ if (!skipConvert) {
50
+ const converted = convertClaudeSkillsToKiro(projectDir);
51
+ if (converted > 0) {
52
+ console.log(chalk.green(`\u2713 Converted ${converted} Claude Code skill(s) to .kiro/skills/`));
53
+ } else {
54
+ console.log(chalk.dim(" No new Claude Code skills to convert"));
55
+ }
56
+ }
57
+ if (!skipConvert) {
58
+ const agentCount = convertClaudeAgentsToKiro(projectDir);
59
+ if (agentCount > 0) {
60
+ console.log(chalk.green(`\u2713 Converted ${agentCount} Claude Code agent(s) to .kiro/agents/`));
61
+ } else {
62
+ console.log(chalk.dim(" No new Claude Code agents to convert"));
63
+ }
64
+ }
65
+ console.log();
66
+ if (mode === "agent") {
67
+ console.log(chalk.cyan("Start Kiro with the ULPI agent:"));
68
+ console.log(chalk.dim(" kiro-cli --agent ulpi-governance"));
69
+ } else {
70
+ console.log(chalk.cyan("ULPI hooks added to default Kiro agent."));
71
+ console.log(chalk.dim(" kiro-cli"));
72
+ }
73
+ console.log();
74
+ }
75
+ function handleConvert(args, projectDir) {
76
+ const skipAgents = args.includes("--no-agents");
77
+ const skipSkills = args.includes("--no-skills");
78
+ console.log(chalk.bold("\nConverting Claude Code assets to Kiro format\n"));
79
+ if (!skipSkills) {
80
+ const skillCount = convertClaudeSkillsToKiro(projectDir);
81
+ if (skillCount > 0) {
82
+ console.log(chalk.green(`\u2713 Converted ${skillCount} Claude Code skill(s) to .kiro/skills/`));
83
+ } else {
84
+ console.log(chalk.dim(" No new Claude Code skills to convert"));
85
+ }
86
+ }
87
+ if (!skipAgents) {
88
+ const agentCount = convertClaudeAgentsToKiro(projectDir);
89
+ if (agentCount > 0) {
90
+ console.log(chalk.green(`\u2713 Converted ${agentCount} Claude Code agent(s) to .kiro/agents/`));
91
+ } else {
92
+ console.log(chalk.dim(" No new Claude Code agents to convert"));
93
+ }
94
+ }
95
+ console.log();
96
+ }
97
+ function handleUninstall(projectDir) {
98
+ console.log(chalk.bold("\nUninstalling ULPI from Kiro CLI\n"));
99
+ const { agentRemoved, skillsRemoved, agentsRemoved } = uninstallKiro(projectDir);
100
+ if (agentRemoved) {
101
+ console.log(chalk.green("\u2713 Removed ulpi-governance agent config"));
102
+ } else {
103
+ console.log(chalk.dim(" Agent config not found"));
104
+ }
105
+ if (skillsRemoved > 0) {
106
+ console.log(chalk.green(`\u2713 Removed ${skillsRemoved} skill(s) from .kiro/skills/`));
107
+ } else {
108
+ console.log(chalk.dim(" No ULPI skills found"));
109
+ }
110
+ if (agentsRemoved > 0) {
111
+ console.log(chalk.green(`\u2713 Removed ${agentsRemoved} converted agent(s) from .kiro/agents/`));
112
+ } else {
113
+ console.log(chalk.dim(" No converted agents found"));
114
+ }
115
+ console.log();
116
+ }
117
+ function handleStatus(projectDir) {
118
+ const status = getKiroStatus(projectDir);
119
+ console.log(chalk.bold("\nKiro CLI Integration Status\n"));
120
+ console.log(` Agent: ${status.agentInstalled ? chalk.green("installed") : chalk.dim("not installed")}`);
121
+ if (status.agentInstalled) {
122
+ console.log(chalk.dim(` ${status.agentPath}`));
123
+ }
124
+ const bundledLabel = status.skillCount > 0 ? chalk.green(`${status.skillCount} bundled`) : chalk.dim("0 bundled");
125
+ const convertedLabel = status.convertedSkillCount > 0 ? chalk.green(`${status.convertedSkillCount} converted`) : chalk.dim("0 converted");
126
+ console.log(` Skills: ${bundledLabel}, ${convertedLabel}`);
127
+ const agentsLabel = status.convertedAgentCount > 0 ? chalk.green(`${status.convertedAgentCount} converted`) : chalk.dim("0 converted");
128
+ console.log(` Agents: ${agentsLabel}`);
129
+ console.log(` MCP: ${status.mcpConfigured ? chalk.green("configured") : chalk.dim("not configured")}`);
130
+ console.log();
131
+ }
132
+ function printUsage() {
133
+ console.log(`
134
+ Usage: ulpi kiro <subcommand> [options]
135
+
136
+ Subcommands:
137
+ install Install ULPI hooks, skills, agent config, and convert Claude Code skills + agents
138
+ convert Convert Claude Code skills and agents to Kiro format (no hooks)
139
+ uninstall Remove ULPI agent config, skills, and converted agents
140
+ status Show Kiro integration status
141
+
142
+ Install options:
143
+ --patch-default Patch the default Kiro agent instead of creating ulpi-governance
144
+ --no-convert Skip converting Claude Code skills and agents
145
+
146
+ Convert options:
147
+ --no-agents Skip agent conversion
148
+ --no-skills Skip skill conversion
149
+ `.trim());
150
+ }
151
+ export {
152
+ runKiro
153
+ };
@@ -1,10 +1,10 @@
1
- import "./chunk-QJ5GSMEC.js";
1
+ import "./chunk-VVEDXI7E.js";
2
2
  import {
3
3
  LAUNCHD_LABEL,
4
4
  LOGS_DIR,
5
5
  getApiPort,
6
6
  getBinaryPath
7
- } from "./chunk-7LXY5UVC.js";
7
+ } from "./chunk-C7CLUQI6.js";
8
8
  import "./chunk-4VNS5WPM.js";
9
9
 
10
10
  // src/launchd.ts
@@ -30,23 +30,15 @@ function needsLegacyMigration() {
30
30
  function generatePlist(options = {}) {
31
31
  const port = options.port ?? getApiPort();
32
32
  const binary = getBinaryPath();
33
- const firstSpace = binary.indexOf(" ");
34
- const parts = firstSpace === -1 ? [binary] : [binary.slice(0, firstSpace), binary.slice(firstSpace + 1)];
35
- for (let i = 0; i < parts.length; i++) {
36
- const p = parts[i].replace(/^"|"$/g, "");
37
- if (p && !p.startsWith("/")) {
38
- try {
39
- const resolved = execFileSync("which", [p], { encoding: "utf-8", timeout: 3e3 }).trim();
40
- if (resolved) parts[i] = resolved;
41
- else parts[i] = p;
42
- } catch {
43
- parts[i] = p;
44
- }
45
- } else {
46
- parts[i] = p;
33
+ let resolvedBinary = binary;
34
+ if (!binary.startsWith("/")) {
35
+ try {
36
+ const resolved = execFileSync("which", [binary], { encoding: "utf-8", timeout: 3e3 }).trim();
37
+ if (resolved) resolvedBinary = resolved;
38
+ } catch {
47
39
  }
48
40
  }
49
- const programArgs = parts.map((p) => ` <string>${escapeXml(p)}</string>`).join("\n");
41
+ const programArgs = ` <string>${escapeXml(resolvedBinary)}</string>`;
50
42
  return `<?xml version="1.0" encoding="UTF-8"?>
51
43
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
52
44
  <plist version="1.0">
@@ -0,0 +1,249 @@
1
+ import "./chunk-4VNS5WPM.js";
2
+
3
+ // src/commands/mcp.ts
4
+ import chalk from "chalk";
5
+ async function runMcp(args, projectDir) {
6
+ const sub = args[0];
7
+ switch (sub) {
8
+ case "gateway":
9
+ return runGateway(projectDir);
10
+ case "list":
11
+ return runList();
12
+ case "add":
13
+ return runAdd(args.slice(1));
14
+ case "remove":
15
+ return runRemove(args.slice(1));
16
+ case "enable":
17
+ return runEnable(args.slice(1), projectDir);
18
+ case "disable":
19
+ return runDisable(args.slice(1), projectDir);
20
+ case "status":
21
+ return runStatus(projectDir);
22
+ case "catalog":
23
+ return runCatalogList(args.slice(1));
24
+ case "cloud-connect":
25
+ return runCloudConnect(projectDir);
26
+ default:
27
+ printUsage();
28
+ }
29
+ }
30
+ function printUsage() {
31
+ console.log(`
32
+ Usage: ulpi mcp <subcommand>
33
+
34
+ Gateway:
35
+ gateway Start the MCP gateway (stdio, blocks until closed)
36
+
37
+ Library:
38
+ list List global MCP library entries
39
+ add <name> Add MCP to library (--from-catalog to use bundled definition)
40
+ remove <name> Remove MCP from library
41
+
42
+ Per-Repo:
43
+ enable <name> Enable MCP for current repo
44
+ disable <name> Disable MCP for current repo
45
+ status Show enabled MCPs for current repo
46
+
47
+ Catalog:
48
+ catalog [--search=<q>] List available catalog entries
49
+
50
+ Cloud:
51
+ cloud-connect Configure .mcp.json to connect to Cloud MCP Gateway
52
+ `.trim());
53
+ }
54
+ async function runGateway(projectDir) {
55
+ const { startGateway } = await import("./dist-IYE3OBRB.js");
56
+ await startGateway({ projectDir });
57
+ }
58
+ async function runList() {
59
+ const { listLibrary } = await import("./dist-EK45QNEM.js");
60
+ const entries = listLibrary();
61
+ if (entries.length === 0) {
62
+ console.log(chalk.dim("No MCPs in library. Run 'ulpi mcp add <name> --from-catalog' to add one."));
63
+ return;
64
+ }
65
+ console.log(chalk.bold(`MCP Library (${entries.length} entries)
66
+ `));
67
+ for (const entry of entries) {
68
+ const name = chalk.cyan(entry.name);
69
+ const display = entry.display_name ? ` (${entry.display_name})` : "";
70
+ const cat = chalk.dim(`[${entry.category}]`);
71
+ const desc = entry.description ? chalk.dim(` \u2014 ${entry.description}`) : "";
72
+ console.log(` ${name}${display} ${cat}${desc}`);
73
+ console.log(` ${chalk.dim(`${entry.command} ${entry.args.join(" ")}`)}`);
74
+ }
75
+ }
76
+ async function runAdd(args) {
77
+ const name = args.find((a) => !a.startsWith("-"));
78
+ const fromCatalog = args.includes("--from-catalog");
79
+ if (!name) {
80
+ console.error(chalk.red("Usage: ulpi mcp add <name> [--from-catalog]"));
81
+ return;
82
+ }
83
+ if (!/^[a-z0-9][a-z0-9_-]*$/.test(name) || name.length > 128) {
84
+ console.error(chalk.red("Name must be lowercase alphanumeric with hyphens/underscores, max 128 chars."));
85
+ return;
86
+ }
87
+ const { addToLibrary, getLibraryEntry } = await import("./dist-EK45QNEM.js");
88
+ if (getLibraryEntry(name)) {
89
+ console.log(chalk.yellow(`MCP "${name}" already exists in library. Use 'ulpi mcp remove ${name}' first.`));
90
+ return;
91
+ }
92
+ const projectDir = process.cwd();
93
+ if (fromCatalog) {
94
+ const { getCatalogEntry, enableMcp } = await import("./dist-EK45QNEM.js");
95
+ const entry = getCatalogEntry(name);
96
+ if (!entry) {
97
+ console.error(chalk.red(`"${name}" not found in catalog. Run 'ulpi mcp catalog' to see available entries.`));
98
+ return;
99
+ }
100
+ addToLibrary(name, {
101
+ name: entry.name,
102
+ display_name: entry.display_name,
103
+ description: entry.description,
104
+ command: entry.command,
105
+ args: entry.args,
106
+ transport: entry.transport,
107
+ category: entry.category,
108
+ config_schema: entry.config_schema,
109
+ tags: entry.tags,
110
+ source: "catalog"
111
+ });
112
+ enableMcp(projectDir, name);
113
+ console.log(chalk.green(`Added "${name}" to library and enabled for this repo.`));
114
+ } else {
115
+ const commandIdx = args.indexOf("--command");
116
+ const command = commandIdx !== -1 ? args[commandIdx + 1] : void 0;
117
+ if (!command) {
118
+ console.error(chalk.red("For manual add, provide --command: ulpi mcp add <name> --command npx --args '-y,@scope/pkg'"));
119
+ console.error(chalk.dim("Or use --from-catalog to add from the bundled catalog."));
120
+ return;
121
+ }
122
+ const argsIdx = args.indexOf("--args");
123
+ const mcpArgs = argsIdx !== -1 ? args[argsIdx + 1]?.split(",") ?? [] : [];
124
+ const { enableMcp: enableManual } = await import("./dist-EK45QNEM.js");
125
+ addToLibrary(name, {
126
+ name,
127
+ command,
128
+ args: mcpArgs,
129
+ transport: "stdio",
130
+ category: "custom",
131
+ tags: [],
132
+ source: "manual"
133
+ });
134
+ enableManual(projectDir, name);
135
+ console.log(chalk.green(`Added "${name}" to library and enabled for this repo.`));
136
+ }
137
+ }
138
+ async function runRemove(args) {
139
+ const name = args[0];
140
+ if (!name) {
141
+ console.error(chalk.red("Usage: ulpi mcp remove <name>"));
142
+ return;
143
+ }
144
+ const { removeFromLibrary, disableMcp } = await import("./dist-EK45QNEM.js");
145
+ const removed = removeFromLibrary(name);
146
+ if (removed) {
147
+ disableMcp(process.cwd(), name);
148
+ console.log(chalk.green(`Removed "${name}" from library and disabled for this repo.`));
149
+ } else {
150
+ console.log(chalk.yellow(`"${name}" not found in library.`));
151
+ }
152
+ }
153
+ async function runEnable(args, projectDir) {
154
+ const name = args[0];
155
+ if (!name) {
156
+ console.error(chalk.red("Usage: ulpi mcp enable <name>"));
157
+ return;
158
+ }
159
+ const { getLibraryEntry, enableMcp } = await import("./dist-EK45QNEM.js");
160
+ if (!getLibraryEntry(name)) {
161
+ console.error(chalk.red(`"${name}" not in library. Run 'ulpi mcp add ${name} --from-catalog' first.`));
162
+ return;
163
+ }
164
+ const config = {};
165
+ for (let i = 1; i < args.length; i++) {
166
+ if (args[i]?.includes("=")) {
167
+ const [key, ...rest] = args[i].split("=");
168
+ if (key) config[key] = rest.join("=");
169
+ }
170
+ }
171
+ enableMcp(projectDir, name, Object.keys(config).length > 0 ? config : void 0);
172
+ console.log(chalk.green(`Enabled "${name}" for this repo.`));
173
+ if (Object.keys(config).length > 0) {
174
+ console.log(chalk.dim(` Config: ${Object.entries(config).map(([k, v]) => `${k}=${v}`).join(", ")}`));
175
+ }
176
+ }
177
+ async function runDisable(args, projectDir) {
178
+ const name = args[0];
179
+ if (!name) {
180
+ console.error(chalk.red("Usage: ulpi mcp disable <name>"));
181
+ return;
182
+ }
183
+ const { disableMcp } = await import("./dist-EK45QNEM.js");
184
+ const disabled = disableMcp(projectDir, name);
185
+ if (disabled) {
186
+ console.log(chalk.green(`Disabled "${name}" for this repo.`));
187
+ } else {
188
+ console.log(chalk.yellow(`"${name}" not enabled for this repo.`));
189
+ }
190
+ }
191
+ async function runStatus(projectDir) {
192
+ const { listActivations, getLibraryEntry } = await import("./dist-EK45QNEM.js");
193
+ const activations = listActivations(projectDir);
194
+ if (activations.length === 0) {
195
+ console.log(chalk.dim("No MCPs configured for this repo. Run 'ulpi mcp enable <name>' to add one."));
196
+ return;
197
+ }
198
+ console.log(chalk.bold(`MCPs for this repo (${activations.length})
199
+ `));
200
+ for (const { name, activation } of activations) {
201
+ const status = activation.enabled ? chalk.green("ON") : chalk.red("OFF");
202
+ const def = getLibraryEntry(name);
203
+ const display = def?.display_name ? ` (${def.display_name})` : "";
204
+ const missing = !def ? chalk.yellow(" [not in library]") : "";
205
+ console.log(` ${status} ${chalk.cyan(name)}${display}${missing}`);
206
+ const configEntries = Object.entries(activation.config);
207
+ if (configEntries.length > 0) {
208
+ for (const [key, value] of configEntries) {
209
+ const displayValue = typeof value === "string" && value.startsWith("env:") ? chalk.dim(value) : chalk.dim(String(value));
210
+ console.log(` ${chalk.dim(key)} = ${displayValue}`);
211
+ }
212
+ }
213
+ }
214
+ }
215
+ async function runCatalogList(args) {
216
+ const searchFlag = args.find((a) => a.startsWith("--search="));
217
+ const query = searchFlag ? searchFlag.slice("--search=".length) : void 0;
218
+ const { loadCatalog, searchCatalog } = await import("./dist-EK45QNEM.js");
219
+ const entries = query ? searchCatalog(query) : loadCatalog();
220
+ if (entries.length === 0) {
221
+ console.log(chalk.dim(query ? `No catalog entries matching "${query}".` : "Catalog is empty."));
222
+ return;
223
+ }
224
+ console.log(chalk.bold(`MCP Catalog (${entries.length} entries)${query ? ` \u2014 search: "${query}"` : ""}
225
+ `));
226
+ const byCategory = /* @__PURE__ */ new Map();
227
+ for (const entry of entries) {
228
+ const cat = entry.category ?? "custom";
229
+ if (!byCategory.has(cat)) byCategory.set(cat, []);
230
+ byCategory.get(cat).push(entry);
231
+ }
232
+ for (const [category, items] of byCategory) {
233
+ console.log(chalk.bold(` ${category.charAt(0).toUpperCase() + category.slice(1)}`));
234
+ for (const item of items) {
235
+ const name = chalk.cyan(item.name);
236
+ const desc = item.description ? chalk.dim(` \u2014 ${item.description}`) : "";
237
+ console.log(` ${name}${desc}`);
238
+ }
239
+ console.log("");
240
+ }
241
+ console.log(chalk.dim(`Add to library: ulpi mcp add <name> --from-catalog`));
242
+ }
243
+ async function runCloudConnect(projectDir) {
244
+ const { runCloud } = await import("./cloud-2F3NLVHN.js");
245
+ await runCloud(["connect"], projectDir);
246
+ }
247
+ export {
248
+ runMcp
249
+ };