@recapt/mcp 0.0.5-beta → 0.0.7-beta

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.
@@ -3,13 +3,15 @@
3
3
  */
4
4
  const API_URL = process.env.EXTERNAL_API_URL || "https://api.recapt.app";
5
5
  const SECRET_KEY = process.env.RECAPT_SECRET_KEY;
6
+ const REQUEST_TIMEOUT_MS = 120_000;
6
7
  export function isApiConfigured() {
7
8
  return !!SECRET_KEY;
8
9
  }
9
10
  export function getApiUrl() {
10
11
  return API_URL;
11
12
  }
12
- export async function apiGet(path, params) {
13
+ async function request(options) {
14
+ const { method, path, params, body } = options;
13
15
  if (!SECRET_KEY) {
14
16
  return { error: "RECAPT_SECRET_KEY not configured" };
15
17
  }
@@ -21,96 +23,43 @@ export async function apiGet(path, params) {
21
23
  }
22
24
  }
23
25
  }
26
+ const controller = new AbortController();
27
+ const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
24
28
  try {
25
29
  const res = await fetch(url.toString(), {
26
- method: "GET",
30
+ method,
27
31
  headers: {
28
32
  "x-private-key": SECRET_KEY,
29
33
  "Content-Type": "application/json",
30
34
  },
35
+ body: body ? JSON.stringify(body) : undefined,
36
+ signal: controller.signal,
31
37
  });
38
+ clearTimeout(timeout);
32
39
  if (!res.ok) {
33
- const body = (await res.json().catch(() => ({})));
34
- return { error: body.error || `HTTP ${res.status}` };
40
+ const errorBody = (await res.json().catch(() => ({})));
41
+ return { error: errorBody.error || `HTTP ${res.status}` };
35
42
  }
36
43
  const data = (await res.json());
37
44
  return { data };
38
45
  }
39
46
  catch (err) {
40
- return { error: err instanceof Error ? err.message : String(err) };
41
- }
42
- }
43
- export async function apiPost(path, body = {}) {
44
- if (!SECRET_KEY) {
45
- return { error: "RECAPT_SECRET_KEY not configured" };
46
- }
47
- const url = `${API_URL}/v1beta/query${path}`;
48
- try {
49
- const res = await fetch(url, {
50
- method: "POST",
51
- headers: {
52
- "x-private-key": SECRET_KEY,
53
- "Content-Type": "application/json",
54
- },
55
- body: JSON.stringify(body),
56
- });
57
- if (!res.ok) {
58
- const responseData = (await res.json().catch(() => ({})));
59
- return { error: responseData.error || `HTTP ${res.status}` };
47
+ clearTimeout(timeout);
48
+ if (err instanceof Error && err.name === "AbortError") {
49
+ return { error: `Request timed out after ${REQUEST_TIMEOUT_MS / 1000}s` };
60
50
  }
61
- const data = (await res.json());
62
- return { data };
63
- }
64
- catch (err) {
65
51
  return { error: err instanceof Error ? err.message : String(err) };
66
52
  }
67
53
  }
68
- export async function apiPatch(path, body = {}) {
69
- if (!SECRET_KEY) {
70
- return { error: "RECAPT_SECRET_KEY not configured" };
71
- }
72
- const url = `${API_URL}/v1beta/query${path}`;
73
- try {
74
- const res = await fetch(url, {
75
- method: "PATCH",
76
- headers: {
77
- "x-private-key": SECRET_KEY,
78
- "Content-Type": "application/json",
79
- },
80
- body: JSON.stringify(body),
81
- });
82
- if (!res.ok) {
83
- const responseData = (await res.json().catch(() => ({})));
84
- return { error: responseData.error || `HTTP ${res.status}` };
85
- }
86
- const data = (await res.json());
87
- return { data };
88
- }
89
- catch (err) {
90
- return { error: err instanceof Error ? err.message : String(err) };
91
- }
54
+ export function apiGet(path, params) {
55
+ return request({ method: "GET", path, params });
92
56
  }
93
- export async function apiDelete(path) {
94
- if (!SECRET_KEY) {
95
- return { error: "RECAPT_SECRET_KEY not configured" };
96
- }
97
- const url = `${API_URL}/v1beta/query${path}`;
98
- try {
99
- const res = await fetch(url, {
100
- method: "DELETE",
101
- headers: {
102
- "x-private-key": SECRET_KEY,
103
- "Content-Type": "application/json",
104
- },
105
- });
106
- if (!res.ok) {
107
- const responseData = (await res.json().catch(() => ({})));
108
- return { error: responseData.error || `HTTP ${res.status}` };
109
- }
110
- const data = (await res.json());
111
- return { data };
112
- }
113
- catch (err) {
114
- return { error: err instanceof Error ? err.message : String(err) };
115
- }
57
+ export function apiPost(path, body = {}) {
58
+ return request({ method: "POST", path, body });
59
+ }
60
+ export function apiPatch(path, body = {}) {
61
+ return request({ method: "PATCH", path, body });
62
+ }
63
+ export function apiDelete(path) {
64
+ return request({ method: "DELETE", path });
116
65
  }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Setup Command
3
+ *
4
+ * Interactive wizard to configure recapt MCP server across AI IDEs.
5
+ */
6
+ import { Command } from "commander";
7
+ export declare const setupCommand: Command;
@@ -0,0 +1,178 @@
1
+ /**
2
+ * Setup Command
3
+ *
4
+ * Interactive wizard to configure recapt MCP server across AI IDEs.
5
+ */
6
+ import { Command } from "commander";
7
+ import { exec } from "child_process";
8
+ import { detectInstalledIdes, addRecaptToIdeConfig, } from "../utils/ide-config.js";
9
+ import { confirm, secret, multiSelect, header, print, success, error, info, warn, newline, } from "../utils/prompts.js";
10
+ import { installAllSkills, installSelectedSkills, getAvailableSkills, } from "./skill.js";
11
+ const SETTINGS_URL = "https://dash.recapt.app/settings";
12
+ const MCP_KEY_PREFIX = "mcp_sk_";
13
+ function openBrowser(url) {
14
+ const platform = process.platform;
15
+ let command;
16
+ switch (platform) {
17
+ case "darwin":
18
+ command = `open "${url}"`;
19
+ break;
20
+ case "win32":
21
+ command = `start "" "${url}"`;
22
+ break;
23
+ default:
24
+ command = `xdg-open "${url}"`;
25
+ }
26
+ exec(command, (err) => {
27
+ if (err) {
28
+ info(`Could not open browser automatically. Please visit: ${url}`);
29
+ }
30
+ });
31
+ }
32
+ function validateMcpKey(key) {
33
+ return (key.startsWith(MCP_KEY_PREFIX) && key.length > MCP_KEY_PREFIX.length + 10);
34
+ }
35
+ async function promptForKey() {
36
+ const hasKey = await confirm("Do you have a Recapt MCP key?", false);
37
+ if (!hasKey) {
38
+ newline();
39
+ info(`Opening ${SETTINGS_URL} (MCP Keys tab)...`);
40
+ info("Create a new MCP key and copy it.");
41
+ newline();
42
+ openBrowser(SETTINGS_URL);
43
+ await new Promise((resolve) => setTimeout(resolve, 2000));
44
+ }
45
+ const key = await secret("Paste your MCP key");
46
+ if (!key) {
47
+ error("No key provided.");
48
+ return null;
49
+ }
50
+ if (!validateMcpKey(key)) {
51
+ error(`Invalid MCP key format. Keys should start with "${MCP_KEY_PREFIX}".`);
52
+ return null;
53
+ }
54
+ return key;
55
+ }
56
+ async function runSetup() {
57
+ header("Recapt MCP Setup");
58
+ const detectedIdes = detectInstalledIdes();
59
+ const installedIdes = detectedIdes.filter((ide) => ide.detected);
60
+ print("Detected AI IDEs:");
61
+ newline();
62
+ for (const ide of detectedIdes) {
63
+ const marker = ide.detected ? "[x]" : "[ ]";
64
+ const status = ide.detected ? `(${ide.globalPathResolved})` : "(not found)";
65
+ print(` ${marker} ${ide.config.name} ${status}`);
66
+ }
67
+ newline();
68
+ if (installedIdes.length === 0) {
69
+ error("No supported AI IDEs detected.");
70
+ info("Supported IDEs: Cursor, Claude Code, Windsurf, VS Code");
71
+ info("Make sure at least one is installed before running setup.");
72
+ process.exit(1);
73
+ }
74
+ const options = installedIdes.map((ide) => ({
75
+ label: ide.config.name,
76
+ value: ide.config,
77
+ selected: true,
78
+ }));
79
+ const selectedIdes = await multiSelect("Which IDE(s) do you want to configure?", options);
80
+ if (selectedIdes.length === 0) {
81
+ info("No IDEs selected. Exiting.");
82
+ return;
83
+ }
84
+ newline();
85
+ const mcpKey = await promptForKey();
86
+ if (!mcpKey) {
87
+ process.exit(1);
88
+ }
89
+ newline();
90
+ print("Writing configuration...");
91
+ newline();
92
+ const configuredPaths = [];
93
+ for (const ide of selectedIdes) {
94
+ try {
95
+ const configPath = addRecaptToIdeConfig(ide, mcpKey, true);
96
+ success(`${ide.name}: ${configPath}`);
97
+ configuredPaths.push(configPath);
98
+ }
99
+ catch (err) {
100
+ error(`${ide.name}: Failed to write config - ${err}`);
101
+ }
102
+ }
103
+ if (configuredPaths.length === 0) {
104
+ error("Failed to configure any IDEs.");
105
+ process.exit(1);
106
+ }
107
+ newline();
108
+ const shouldInstallSkills = await confirm("Install recapt skills?", true);
109
+ if (shouldInstallSkills) {
110
+ newline();
111
+ let availableSkills;
112
+ try {
113
+ availableSkills = getAvailableSkills();
114
+ }
115
+ catch (err) {
116
+ error(`Failed to load skills: ${err instanceof Error ? err.message : err}`);
117
+ availableSkills = [];
118
+ }
119
+ if (availableSkills.length > 0) {
120
+ const skillOptions = [
121
+ { label: "Install all skills", value: "__all__", selected: true },
122
+ ...availableSkills.map((skill) => ({
123
+ label: `${skill.name} - ${skill.description}`,
124
+ value: skill.name,
125
+ selected: false,
126
+ })),
127
+ ];
128
+ const selectedSkills = await multiSelect("Which skills do you want to install?", skillOptions);
129
+ if (selectedSkills.length > 0) {
130
+ newline();
131
+ print("Installing skills...");
132
+ newline();
133
+ const cwd = process.cwd();
134
+ let result;
135
+ if (selectedSkills.includes("__all__")) {
136
+ result = installAllSkills(cwd);
137
+ }
138
+ else {
139
+ result = installSelectedSkills(cwd, selectedSkills);
140
+ }
141
+ if (result.error) {
142
+ error(`Failed to load skills: ${result.error}`);
143
+ }
144
+ else if (result.installed.length > 0) {
145
+ success(`Installed ${result.installed.length} skill(s): ${result.installed.join(", ")}`);
146
+ if (result.failed.length > 0) {
147
+ warn(`Failed to install: ${result.failed.join(", ")}`);
148
+ }
149
+ }
150
+ else if (result.failed.length > 0) {
151
+ error(`Failed to install skills: ${result.failed.join(", ")}`);
152
+ }
153
+ else {
154
+ info("No skills were installed.");
155
+ }
156
+ }
157
+ else {
158
+ info("No skills selected.");
159
+ }
160
+ }
161
+ }
162
+ newline();
163
+ success("Setup complete!");
164
+ newline();
165
+ info("Restart your IDE(s) to activate the MCP server.");
166
+ newline();
167
+ }
168
+ export const setupCommand = new Command("setup")
169
+ .description("Configure recapt MCP server for your AI IDE(s)")
170
+ .action(async () => {
171
+ try {
172
+ await runSetup();
173
+ }
174
+ catch (err) {
175
+ error(`Setup failed: ${err}`);
176
+ process.exit(1);
177
+ }
178
+ });
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Skill Command
3
+ *
4
+ * Manages recapt workflow skills installation to .agents/recapt/.
5
+ * Works across all AI IDEs that support the AGENTS.md standard.
6
+ */
7
+ import { Command } from "commander";
8
+ interface SkillInfo {
9
+ name: string;
10
+ file: string;
11
+ description: string;
12
+ }
13
+ export type { SkillInfo };
14
+ export declare function getAvailableSkills(): SkillInfo[];
15
+ export interface InstallResult {
16
+ success: boolean;
17
+ installed: string[];
18
+ failed: string[];
19
+ error?: string;
20
+ }
21
+ export declare function installAllSkills(cwd: string): InstallResult;
22
+ export declare function installSelectedSkills(cwd: string, skillNames: string[]): InstallResult;
23
+ export declare const skillCommand: Command;
@@ -0,0 +1,251 @@
1
+ /**
2
+ * Skill Command
3
+ *
4
+ * Manages recapt workflow skills installation to .agents/recapt/.
5
+ * Works across all AI IDEs that support the AGENTS.md standard.
6
+ */
7
+ import { Command } from "commander";
8
+ import fs from "fs";
9
+ import path from "path";
10
+ import { fileURLToPath } from "url";
11
+ const __filename = fileURLToPath(import.meta.url);
12
+ const __dirname = path.dirname(__filename);
13
+ const SKILLS_DIR = path.resolve(__dirname, "../../../skills");
14
+ const AGENTS_DIR = ".agents/recapt";
15
+ const AGENTS_MD = "AGENTS.md";
16
+ const MARKER_START = "<!-- recapt:skills -->";
17
+ const MARKER_END = "<!-- /recapt:skills -->";
18
+ export function getAvailableSkills() {
19
+ if (!fs.existsSync(SKILLS_DIR)) {
20
+ throw new Error(`Skills directory not found: ${SKILLS_DIR}`);
21
+ }
22
+ const files = fs.readdirSync(SKILLS_DIR).filter((f) => f.endsWith(".md"));
23
+ if (files.length === 0) {
24
+ throw new Error(`No skill files found in: ${SKILLS_DIR}`);
25
+ }
26
+ return files.map((file) => {
27
+ const content = fs.readFileSync(path.join(SKILLS_DIR, file), "utf-8");
28
+ const firstLine = content.split("\n")[0];
29
+ const description = firstLine.startsWith("# ")
30
+ ? firstLine.slice(2).trim()
31
+ : file.replace(".md", "");
32
+ return {
33
+ name: file.replace(".md", ""),
34
+ file,
35
+ description,
36
+ };
37
+ });
38
+ }
39
+ function getInstalledSkills(cwd) {
40
+ const agentsDir = path.join(cwd, AGENTS_DIR);
41
+ if (!fs.existsSync(agentsDir)) {
42
+ return [];
43
+ }
44
+ return fs
45
+ .readdirSync(agentsDir)
46
+ .filter((f) => f.endsWith(".md"))
47
+ .map((f) => f.replace(".md", ""));
48
+ }
49
+ function ensureAgentsDir(cwd) {
50
+ const agentsDir = path.join(cwd, AGENTS_DIR);
51
+ if (!fs.existsSync(agentsDir)) {
52
+ fs.mkdirSync(agentsDir, { recursive: true });
53
+ console.log(`Created ${AGENTS_DIR}/`);
54
+ }
55
+ }
56
+ function readAgentsMd(cwd) {
57
+ const agentsMdPath = path.join(cwd, AGENTS_MD);
58
+ if (!fs.existsSync(agentsMdPath)) {
59
+ return "";
60
+ }
61
+ return fs.readFileSync(agentsMdPath, "utf-8");
62
+ }
63
+ function writeAgentsMd(cwd, content) {
64
+ const agentsMdPath = path.join(cwd, AGENTS_MD);
65
+ fs.writeFileSync(agentsMdPath, content);
66
+ }
67
+ function getSkillDisplayName(skillName) {
68
+ try {
69
+ const skills = getAvailableSkills();
70
+ const skill = skills.find((s) => s.name === skillName);
71
+ return skill?.description ?? skillName;
72
+ }
73
+ catch {
74
+ return skillName;
75
+ }
76
+ }
77
+ function updateAgentsMdReferences(cwd) {
78
+ const installed = getInstalledSkills(cwd);
79
+ let content = readAgentsMd(cwd);
80
+ if (installed.length === 0) {
81
+ if (content.includes(MARKER_START)) {
82
+ const regex = new RegExp(`\\n?${MARKER_START}[\\s\\S]*?${MARKER_END}\\n?`, "g");
83
+ content = content.replace(regex, "").trim();
84
+ if (content) {
85
+ writeAgentsMd(cwd, content + "\n");
86
+ }
87
+ else {
88
+ const agentsMdPath = path.join(cwd, AGENTS_MD);
89
+ if (fs.existsSync(agentsMdPath)) {
90
+ fs.unlinkSync(agentsMdPath);
91
+ console.log(`Removed empty ${AGENTS_MD}`);
92
+ }
93
+ }
94
+ }
95
+ return;
96
+ }
97
+ const skillLinks = installed
98
+ .map((name) => `- [${getSkillDisplayName(name)}](${AGENTS_DIR}/${name}.md)`)
99
+ .join("\n");
100
+ const newBlock = `${MARKER_START}
101
+ For recapt behavioral intelligence workflows, see:
102
+ ${skillLinks}
103
+ ${MARKER_END}`;
104
+ if (content.includes(MARKER_START)) {
105
+ const regex = new RegExp(`${MARKER_START}[\\s\\S]*?${MARKER_END}`, "g");
106
+ content = content.replace(regex, newBlock);
107
+ }
108
+ else {
109
+ if (content.trim()) {
110
+ content = content.trim() + "\n\n" + newBlock;
111
+ }
112
+ else {
113
+ content = `# Project Agent Instructions\n\n${newBlock}`;
114
+ }
115
+ }
116
+ writeAgentsMd(cwd, content + "\n");
117
+ }
118
+ function installSkill(cwd, skillName) {
119
+ let skills;
120
+ try {
121
+ skills = getAvailableSkills();
122
+ }
123
+ catch (err) {
124
+ console.error(`Failed to load skills: ${err instanceof Error ? err.message : err}`);
125
+ return false;
126
+ }
127
+ const skill = skills.find((s) => s.name === skillName);
128
+ if (!skill) {
129
+ console.error(`Unknown skill: ${skillName}`);
130
+ console.error(`Available skills: ${skills.map((s) => s.name).join(", ")}`);
131
+ return false;
132
+ }
133
+ ensureAgentsDir(cwd);
134
+ const sourcePath = path.join(SKILLS_DIR, skill.file);
135
+ const destPath = path.join(cwd, AGENTS_DIR, skill.file);
136
+ if (fs.existsSync(destPath)) {
137
+ console.log(`Skill already installed: ${skillName}`);
138
+ return true;
139
+ }
140
+ fs.copyFileSync(sourcePath, destPath);
141
+ console.log(`Installed: ${skillName} → ${AGENTS_DIR}/${skill.file}`);
142
+ updateAgentsMdReferences(cwd);
143
+ return true;
144
+ }
145
+ function uninstallSkill(cwd, skillName) {
146
+ const skillPath = path.join(cwd, AGENTS_DIR, `${skillName}.md`);
147
+ if (!fs.existsSync(skillPath)) {
148
+ console.error(`Skill not installed: ${skillName}`);
149
+ return false;
150
+ }
151
+ fs.unlinkSync(skillPath);
152
+ console.log(`Uninstalled: ${skillName}`);
153
+ updateAgentsMdReferences(cwd);
154
+ const agentsDir = path.join(cwd, AGENTS_DIR);
155
+ const remaining = fs.readdirSync(agentsDir);
156
+ if (remaining.length === 0) {
157
+ fs.rmdirSync(agentsDir);
158
+ const parentDir = path.dirname(agentsDir);
159
+ if (fs.existsSync(parentDir) && fs.readdirSync(parentDir).length === 0) {
160
+ fs.rmdirSync(parentDir);
161
+ }
162
+ console.log(`Removed empty ${AGENTS_DIR}/`);
163
+ }
164
+ return true;
165
+ }
166
+ function listSkills(cwd) {
167
+ let available;
168
+ try {
169
+ available = getAvailableSkills();
170
+ }
171
+ catch (err) {
172
+ console.error(`Failed to load skills: ${err instanceof Error ? err.message : err}`);
173
+ process.exit(1);
174
+ }
175
+ const installed = new Set(getInstalledSkills(cwd));
176
+ console.log("\nAvailable recapt skills:\n");
177
+ for (const skill of available) {
178
+ const status = installed.has(skill.name) ? "[installed]" : "";
179
+ console.log(` ${skill.name.padEnd(20)} ${skill.description} ${status}`);
180
+ }
181
+ console.log();
182
+ }
183
+ export function installAllSkills(cwd) {
184
+ let skills;
185
+ try {
186
+ skills = getAvailableSkills();
187
+ }
188
+ catch (err) {
189
+ const message = err instanceof Error ? err.message : String(err);
190
+ console.error(`Failed to load skills: ${message}`);
191
+ return { success: false, installed: [], failed: [], error: message };
192
+ }
193
+ return installSelectedSkills(cwd, skills.map((s) => s.name));
194
+ }
195
+ export function installSelectedSkills(cwd, skillNames) {
196
+ const installed = [];
197
+ const failed = [];
198
+ for (const skillName of skillNames) {
199
+ try {
200
+ if (installSkill(cwd, skillName)) {
201
+ installed.push(skillName);
202
+ }
203
+ else {
204
+ failed.push(skillName);
205
+ }
206
+ }
207
+ catch (err) {
208
+ console.error(`Failed to install ${skillName}: ${err}`);
209
+ failed.push(skillName);
210
+ }
211
+ }
212
+ const success = failed.length === 0 && installed.length > 0;
213
+ if (success && installed.length > 1) {
214
+ console.log(`\nAll skills installed. See ${AGENTS_MD} for references.`);
215
+ }
216
+ return { success, installed, failed };
217
+ }
218
+ const listCommand = new Command("list")
219
+ .description("Show available skills")
220
+ .action(() => {
221
+ listSkills(process.cwd());
222
+ });
223
+ const installCommand = new Command("install")
224
+ .description("Install a skill")
225
+ .argument("[name]", "Skill name to install")
226
+ .option("-a, --all", "Install all skills")
227
+ .action((name, options) => {
228
+ const cwd = process.cwd();
229
+ if (options.all) {
230
+ installAllSkills(cwd);
231
+ return;
232
+ }
233
+ if (!name) {
234
+ console.error("Usage: recapt skill install <name> or recapt skill install --all");
235
+ process.exit(1);
236
+ }
237
+ if (installSkill(cwd, name)) {
238
+ console.log(`\nSkill reference added to ${AGENTS_MD}`);
239
+ }
240
+ });
241
+ const uninstallCommand = new Command("uninstall")
242
+ .description("Remove a skill")
243
+ .argument("<name>", "Skill name to uninstall")
244
+ .action((name) => {
245
+ uninstallSkill(process.cwd(), name);
246
+ });
247
+ export const skillCommand = new Command("skill")
248
+ .description("Manage recapt workflow skills")
249
+ .addCommand(listCommand)
250
+ .addCommand(installCommand)
251
+ .addCommand(uninstallCommand);
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Recapt MCP CLI
4
+ *
5
+ * Unified command-line interface for recapt MCP server management.
6
+ *
7
+ * Commands:
8
+ * setup - Configure recapt MCP server for your AI IDE(s)
9
+ * skill - Manage recapt workflow skills
10
+ */
11
+ export {};
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Recapt MCP CLI
4
+ *
5
+ * Unified command-line interface for recapt MCP server management.
6
+ *
7
+ * Commands:
8
+ * setup - Configure recapt MCP server for your AI IDE(s)
9
+ * skill - Manage recapt workflow skills
10
+ */
11
+ import { Command } from "commander";
12
+ import { createRequire } from "module";
13
+ import { skillCommand } from "./commands/skill.js";
14
+ import { setupCommand } from "./commands/setup.js";
15
+ const require = createRequire(import.meta.url);
16
+ const pkg = require("../../package.json");
17
+ const program = new Command();
18
+ program
19
+ .name("recapt")
20
+ .description("Recapt MCP CLI - Configure and manage recapt for AI IDEs")
21
+ .version(pkg.version);
22
+ program.addCommand(setupCommand);
23
+ program.addCommand(skillCommand);
24
+ program.parse();
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Recapt Skills CLI
4
+ *
5
+ * Installs recapt workflow skills to .agents/recapt/ and manages AGENTS.md references.
6
+ * Works across all AI IDEs that support the AGENTS.md standard.
7
+ *
8
+ * Usage:
9
+ * npx @recapt/mcp skill list
10
+ * npx @recapt/mcp skill install self-healing
11
+ * npx @recapt/mcp skill install --all
12
+ * npx @recapt/mcp skill uninstall self-healing
13
+ */
14
+ export {};