const require_chunk = require("./chunk-CZWwpsFl.cjs"); const require_skill = require("./skill-vpzqNCTw.cjs"); const require_to_error_message = require("./to-error-message-DMTSr_Bl.cjs"); const require_mcp = require("./mcp-Ccqdolho.cjs"); const require_agents_md = require("./agents-md-CdwuWt7C.cjs"); let node_fs = require("node:fs"); let node_os = require("node:os"); let node_path = require("node:path"); let node_fs_promises = require("node:fs/promises"); let commander = require("commander"); let picocolors = require("picocolors"); picocolors = require_chunk.__toESM(picocolors, 1); let prompts = require("prompts"); prompts = require_chunk.__toESM(prompts, 1); //#region src/cli/utils/logger.ts const logger = { info: (message) => { console.log(picocolors.default.cyan("ℹ"), message); }, success: (message) => { console.log(picocolors.default.green("✔"), message); }, warn: (message) => { console.log(picocolors.default.yellow("⚠"), message); }, error: (message) => { console.error(picocolors.default.red("✖"), message); } }; //#endregion //#region src/cli/commands/doc/resolve-agent.ts const knownAgents = new Set(require_agents_md.listAgentsMdDescriptors().map((descriptor) => descriptor.agent)); const isAgentsMdAgent = (value) => knownAgents.has(value); const resolveAgentsMdAgent = (value) => { if (value === void 0) return void 0; if (!isAgentsMdAgent(value)) throw new Error(`Unknown agent "${value}"`); return value; }; //#endregion //#region src/cli/commands/doc/init.ts const TEMPLATE = `# AGENTS.md This document is the source of truth for AI coding agents working in this repository. ## Project overview Short description of what this project does. ## Setup commands \`\`\`bash pnpm install pnpm dev \`\`\` ## Conventions - Describe coding style, framework, and patterns agents should follow. - Link to any other docs that are relevant. ## Testing \`\`\`bash pnpm test \`\`\` `; const docInitCommand = new commander.Command("init").description("Create an AGENTS.md (or agent-specific variant) in the current directory").option("-a, --agent ", "Agent to target (defaults to universal AGENTS.md)").action((options) => { try { const filePath = require_agents_md.resolveAgentsMdFilePath({ cwd: process.cwd(), agent: resolveAgentsMdAgent(options.agent) }); if ((0, node_fs.existsSync)(filePath)) { logger.warn(`${picocolors.default.cyan(filePath)} already exists`); return; } (0, node_fs.writeFileSync)(filePath, TEMPLATE, "utf-8"); logger.success(`Created ${picocolors.default.bold(filePath)}`); } catch (error) { logger.error(require_to_error_message.toErrorMessage(error)); process.exitCode = 1; } }); //#endregion //#region src/cli/commands/doc/read.ts const docReadCommand = new commander.Command("read").description("Read the current AGENTS.md (or agent-specific variant) and list its sections").option("-a, --agent ", "Agent variant to read (claude-code, cursor, codex, ...)").option("-f, --file ", "Explicit file path (overrides --agent)").option("--json", "Output as JSON").action((options) => { try { const document = require_agents_md.readAgentsMd({ agent: resolveAgentsMdAgent(options.agent), file: options.file, cwd: process.cwd() }); if (options.json) { console.log(JSON.stringify({ path: document.path, sections: document.sections.map((section) => ({ heading: section.heading, level: section.level, body: section.body })) }, null, 2)); return; } if (!document.content) { logger.warn(`No file at ${picocolors.default.cyan(document.path)}`); return; } logger.info(picocolors.default.bold(document.path)); for (const section of document.sections) { const prefix = "#".repeat(section.level); console.log(` ${picocolors.default.dim(prefix)} ${section.heading}`); } } catch (error) { logger.error(require_to_error_message.toErrorMessage(error)); process.exitCode = 1; } }); //#endregion //#region src/cli/commands/doc/remove-section.ts const docRemoveSectionCommand = new commander.Command("remove-section").alias("rm-section").description("Remove a section from an AGENTS.md file").argument("", "Section heading to remove").option("-a, --agent ", "Agent variant to target").option("-f, --file ", "Explicit file path (overrides --agent)").action((heading, options) => { try { if (require_agents_md.removeAgentsMdSection({ heading, agent: resolveAgentsMdAgent(options.agent), file: options.file, cwd: process.cwd() })) logger.success(`Removed ${picocolors.default.bold(heading)}`); else logger.warn(`Section ${picocolors.default.bold(heading)} not found`); } catch (error) { logger.error(require_to_error_message.toErrorMessage(error)); process.exitCode = 1; } }); //#endregion //#region src/cli/commands/doc/set-section.ts const MIN_HEADING_LEVEL = 1; const MAX_HEADING_LEVEL = 6; const isValidPlacement = (value) => value === "append" || value === "prepend" || value === "replace"; const docSetSectionCommand = new commander.Command("set-section").description("Create or replace a section in an AGENTS.md file").argument("", "Section heading (used as the Markdown heading)").option("-a, --agent ", "Agent variant to target").option("-f, --file ", "Explicit file path (overrides --agent)").option("--body ", "Inline body content").option("--body-file ", "Read body from a file").option("--placement ", "append, prepend, or replace (default: replace)").option("--level ", "Heading level (1-6, default: 2)").action((heading, options) => { try { const agent = resolveAgentsMdAgent(options.agent); const body = options.body ?? (options.bodyFile ? (0, node_fs.readFileSync)(options.bodyFile, "utf-8") : ""); if (!body.trim()) throw new Error("Body is empty. Provide --body or --body-file with content."); const placement = options.placement ?? "replace"; if (!isValidPlacement(placement)) throw new Error(`Invalid placement "${placement}" (expected: append, prepend, replace)`); const level = options.level ? Number.parseInt(options.level, 10) : 2; if (!Number.isInteger(level) || level < MIN_HEADING_LEVEL || level > MAX_HEADING_LEVEL) throw new Error(`Invalid heading level "${options.level}" (expected: ${MIN_HEADING_LEVEL}-${MAX_HEADING_LEVEL})`); const filePath = require_agents_md.upsertAgentsMdSection({ heading, body, agent, file: options.file, placement, level, cwd: process.cwd() }); logger.success(`Updated ${picocolors.default.bold(heading)} in ${picocolors.default.cyan(filePath)}`); } catch (error) { logger.error(require_to_error_message.toErrorMessage(error)); process.exitCode = 1; } }); //#endregion //#region src/cli/commands/doc/symlink-claude.ts const docSymlinkClaudeCommand = new commander.Command("symlink-claude").description("Create a CLAUDE.md → AGENTS.md symlink (migration helper)").option("--overwrite", "Replace an existing CLAUDE.md (backs it up first)").option("--backup ", "Backup filename if overwriting (default: CLAUDE.md.bak)").action(async (options) => { try { const result = await require_agents_md.symlinkClaudeToAgents({ cwd: process.cwd(), overwrite: Boolean(options.overwrite), backupName: options.backup }); if (result.alreadyLinked) { logger.info(`CLAUDE.md already points to AGENTS.md`); return; } if (result.created) { const suffix = result.backedUpTo ? ` (backed up existing to ${picocolors.default.dim(result.backedUpTo)})` : ""; logger.success(`Linked ${picocolors.default.cyan(result.claudePath)} → AGENTS.md${suffix}`); return; } logger.warn(`CLAUDE.md already exists at ${picocolors.default.cyan(result.claudePath)}. Pass --overwrite to replace it.`); process.exitCode = 1; } catch (error) { logger.error(require_to_error_message.toErrorMessage(error)); process.exitCode = 1; } }); //#endregion //#region src/cli/commands/doc/index.ts const docCommand = new commander.Command("agents-md").alias("doc").description("Manage AGENTS.md / CLAUDE.md / GEMINI.md / Cursor rules").addCommand(docInitCommand).addCommand(docReadCommand).addCommand(docSetSectionCommand).addCommand(docRemoveSectionCommand).addCommand(docSymlinkClaudeCommand); //#endregion //#region src/cli/utils/format-agent-list.ts const formatAgentList = (agentList, emptyLabel = "(none)") => agentList.length === 0 ? emptyLabel : agentList.join(", "); //#endregion //#region src/cli/utils/parse-mcp-agent-list.ts const parseMcpAgentList = (input) => { if (!input || input.length === 0) return void 0; if (input.includes("*")) return require_mcp.getMcpAgentTypes(); const resolved = []; for (const value of input) { const agentType = require_mcp.resolveMcpAgentAlias(value); if (!agentType) throw new Error(`Unknown MCP agent "${value}"`); resolved.push(agentType); } return resolved; }; //#endregion //#region src/cli/commands/mcp/add.ts const parseKeyValueList = (entries, separator) => { if (!entries || entries.length === 0) return {}; const result = {}; for (const entry of entries) { const splitIndex = entry.indexOf(separator); if (splitIndex === -1) throw new Error(`Invalid entry "${entry}": expected "${separator}" separator`); const key = entry.slice(0, splitIndex).trim(); const value = entry.slice(splitIndex + separator.length).trim(); if (!key) throw new Error(`Invalid entry "${entry}": empty key`); result[key] = value; } return result; }; const resolveTransport = (input) => { if (!input) return void 0; if (input === "http" || input === "sse") return input; throw new Error(`Unsupported transport "${input}" (expected: http, sse)`); }; const detectCandidateAgents = (cwd, isGlobal) => isGlobal ? require_mcp.detectGloballyInstalledMcpAgents() : require_mcp.detectProjectInstalledMcpAgents(cwd); const mcpAddCommand = new commander.Command("add").description("Add an MCP server to coding agents").argument("", "Remote URL, npm package, or command line").option("-a, --agent ", "Target specific agents (use '*' for all)").option("-g, --global", "Install to user-level config instead of project").option("-t, --transport ", "Transport type for remote servers (http or sse)").option("--header ", "HTTP header (Key: Value), repeatable").option("--env ", "Env var for stdio servers (KEY=VALUE), repeatable").option("-n, --name ", "Server name override").option("-y, --yes", "Skip all prompts").option("--all", "Install to all supported agents").action((source, options) => { try { const parsed = require_mcp.parseMcpSource(source); const cwd = process.cwd(); const isGlobal = Boolean(options.global); let agentTypes = options.all ? require_mcp.getMcpAgentTypes() : parseMcpAgentList(options.agent); if (!agentTypes) { const detected = detectCandidateAgents(cwd, isGlobal); if (detected.length === 0) { logger.warn(`No ${isGlobal ? "global" : "project"}-installed MCP agents detected. Pass ${picocolors.default.cyan("-a ")} (e.g. ${picocolors.default.cyan("-a cursor")}) or ${picocolors.default.cyan("--all")} to install.`); process.exitCode = 1; return; } agentTypes = detected; logger.info(`Detected ${isGlobal ? "global" : "project"} agents: ${picocolors.default.cyan(formatAgentList(detected, "(none detected)"))}`); } const result = require_mcp.installMcpServer({ source, name: options.name, agents: agentTypes, global: isGlobal, cwd, transport: resolveTransport(options.transport), headers: parseKeyValueList(options.header, ":"), env: parseKeyValueList(options.env, "=") }); logger.info(`Installing ${picocolors.default.bold(result.serverName)} (${picocolors.default.cyan(parsed.type)}) to ${picocolors.default.cyan(String(result.results.length))} agent(s)`); for (const record of result.results) if (record.success) logger.success(`${picocolors.default.cyan(record.agent)} ${picocolors.default.dim(record.path)}`); else logger.error(`${picocolors.default.cyan(record.agent)}: ${record.error}`); if (result.results.some((record) => !record.success)) process.exitCode = 1; } catch (error) { logger.error(require_to_error_message.toErrorMessage(error)); process.exitCode = 1; } }); //#endregion //#region src/cli/commands/mcp/list.ts const mcpListCommand = new commander.Command("list").alias("ls").description("List installed MCP servers across agents").option("-g, --global", "List global configs instead of project").option("-a, --agent ", "Filter by specific agents").option("--json", "Output as JSON").action((options) => { try { const entries = require_mcp.listInstalledMcpServers({ global: Boolean(options.global), cwd: process.cwd(), agents: parseMcpAgentList(options.agent) }); if (options.json) { console.log(JSON.stringify(entries, null, 2)); return; } if (entries.length === 0) { logger.warn("No MCP servers installed"); return; } const grouped = /* @__PURE__ */ new Map(); for (const entry of entries) { const existing = grouped.get(entry.serverName) ?? []; existing.push(entry); grouped.set(entry.serverName, existing); } for (const [serverName, group] of grouped) { const agentLabels = group.map((record) => record.agent).join(", "); console.log(` ${picocolors.default.bold(serverName)} ${picocolors.default.dim(`[${agentLabels}]`)}`); const firstPath = group[0]?.path; if (firstPath) console.log(` ${picocolors.default.dim(firstPath)}`); } } catch (error) { logger.error(require_to_error_message.toErrorMessage(error)); process.exitCode = 1; } }); //#endregion //#region src/cli/commands/mcp/remove.ts const mcpRemoveCommand = new commander.Command("remove").alias("rm").description("Remove an MCP server from agent configs").argument("", "Server name").option("-g, --global", "Remove from global scope").option("-a, --agent ", "Filter by specific agents (use '*' for all)").option("-y, --yes", "Skip confirmation prompts").action((name, options) => { try { const results = require_mcp.removeMcpServer({ name, agents: parseMcpAgentList(options.agent), global: Boolean(options.global), cwd: process.cwd() }); if (results.length === 0) { logger.warn(`No agent config contained ${picocolors.default.bold(name)}`); return; } for (const record of results) if (record.removed) logger.success(`${picocolors.default.cyan(record.agent)} removed ${picocolors.default.bold(name)} ${picocolors.default.dim(record.path)}`); else logger.error(`${picocolors.default.cyan(record.agent)}: ${record.error ?? "not found"}`); } catch (error) { logger.error(require_to_error_message.toErrorMessage(error)); process.exitCode = 1; } }); //#endregion //#region src/cli/commands/mcp/index.ts const mcpCommand = new commander.Command("mcp").description("Install, list, and remove MCP servers across coding agents").addCommand(mcpAddCommand).addCommand(mcpListCommand).addCommand(mcpRemoveCommand); //#endregion //#region src/cli/utils/parse-skill-agent-list.ts const parseSkillAgentList = (input) => { if (!input || input.length === 0) return void 0; if (input.includes("*")) return require_skill.getSkillAgentTypes(); const validated = []; for (const value of input) { if (!require_skill.isSkillAgentType(value)) throw new Error(`Unknown agent "${value}"`); validated.push(value); } return validated; }; //#endregion //#region src/cli/commands/skill/add.ts const resolveSkillFilter = (input) => { if (!input || input.length === 0) return void 0; if (input.includes("*")) return void 0; return input; }; const resolveTargetAgentsForPrompt = async (requested, yes) => { if (requested) return requested; const installed = await require_skill.detectInstalledSkillAgents(); const fallback = installed.length > 0 ? installed : require_skill.getUniversalSkillAgents(); if (yes || !process.stdin.isTTY) return fallback; const rawSelected = (await (0, prompts.default)({ type: "multiselect", name: "agents", message: "Install to which agents?", choices: Object.values(require_skill.skillAgents).map((agent) => ({ title: agent.displayName, value: agent.name, selected: fallback.includes(agent.name) })), min: 1 })).agents; if (!Array.isArray(rawSelected) || rawSelected.length === 0) { logger.warn("No agents selected, using detected defaults"); return fallback; } const selected = rawSelected.filter((value) => typeof value === "string" && require_skill.isSkillAgentType(value)); return selected.length > 0 ? selected : fallback; }; const listSkillsInSource = async (source) => { const parsed = require_skill.parseSkillSource(source); let basePath = ""; let subpath; let cleanup; try { if (parsed.type === "local") basePath = parsed.localPath ?? parsed.url; else if (parsed.type === "url") { basePath = await require_skill.fetchSkillManifestFromUrl(parsed.url); cleanup = () => require_skill.cleanupTempDir(basePath); } else if (parsed.type === "well-known") { basePath = await require_skill.fetchWellKnownSkills(parsed.url); cleanup = () => require_skill.cleanupTempDir(basePath); } else { basePath = await require_skill.cloneRepo(parsed.url, parsed.ref); subpath = parsed.subpath; cleanup = () => require_skill.cleanupTempDir(basePath); } const skills = await require_skill.discoverSkills(basePath, subpath); const visible = parsed.skillFilter ? require_skill.filterSkillsByName(skills, [parsed.skillFilter]) : skills; if (visible.length === 0) { logger.warn("No SKILL.md files found in source"); return; } logger.info(`Found ${visible.length} skill${visible.length === 1 ? "" : "s"}`); for (const skill of visible) console.log(` ${picocolors.default.bold(skill.name)} ${picocolors.default.dim("-")} ${skill.description}`); } finally { await cleanup?.().catch(() => {}); } }; const skillAddCommand = new commander.Command("add").description("Install skills from a source (local path, GitHub, or URL)").argument("", "Source to install skills from").option("-a, --agent ", "Target specific agents (use '*' for all)").option("-s, --skill ", "Install specific skills by name").option("-g, --global", "Install to ~/.agents/skills instead of the project").option("--copy", "Copy files instead of symlinking").option("-y, --yes", "Skip all prompts").option("-l, --list", "List available skills in the source without installing").action(async (source, options) => { try { if (options.list) { await listSkillsInSource(source); return; } const targetAgents = await resolveTargetAgentsForPrompt(parseSkillAgentList(options.agent), Boolean(options.yes)); const skillFilter = resolveSkillFilter(options.skill); const mode = options.copy ? "copy" : "symlink"; logger.info(`Installing from ${picocolors.default.cyan(source)} to ${picocolors.default.cyan(formatAgentList(targetAgents))}`); const result = await require_skill.installSkillsFromSource({ source, agents: targetAgents, skills: skillFilter, global: options.global, mode, cwd: process.cwd() }); if (result.skills.length === 0) { logger.warn("No SKILL.md files found in source"); return; } for (const record of result.installed) { const fallbackSuffix = record.symlinkFailed ? picocolors.default.dim(" (copied: symlink fallback)") : ""; logger.success(`${picocolors.default.bold(record.skill)} → ${picocolors.default.cyan(record.agent)}${fallbackSuffix} ${picocolors.default.dim(record.path)}`); } for (const record of result.failed) logger.error(`${picocolors.default.bold(record.skill)} → ${picocolors.default.cyan(record.agent)}: ${record.error}`); if (result.failed.length > 0) process.exitCode = 1; } catch (error) { logger.error(require_to_error_message.toErrorMessage(error)); process.exitCode = 1; } }); //#endregion //#region src/cli/commands/skill/init.ts const renderTemplate = (skillName) => `--- name: ${skillName} description: A brief description of what this skill does and when to use it. --- # ${skillName} Describe what this skill does, when the agent should use it, and the instructions the agent should follow when activated. ## When to use Describe the trigger conditions (e.g. "after finishing a feature", "when the user asks about X", "before committing React code"). ## Instructions 1. First step 2. Second step 3. Additional steps as needed `; const skillInitCommand = new commander.Command("init").description("Create a new SKILL.md in the current directory").argument("[name]", "Skill name (defaults to current directory name)").action(async (nameArg) => { try { const cwd = process.cwd(); const skillName = nameArg || (0, node_path.basename)(cwd); const hasExplicitName = nameArg !== void 0; const skillDir = hasExplicitName ? (0, node_path.join)(cwd, skillName) : cwd; const skillFile = (0, node_path.join)(skillDir, "SKILL.md"); const displayPath = hasExplicitName ? `${skillName}/SKILL.md` : "SKILL.md"; if ((0, node_fs.existsSync)(skillFile)) { logger.warn(`Skill already exists at ${picocolors.default.cyan(displayPath)}`); return; } if (hasExplicitName) await (0, node_fs_promises.mkdir)(skillDir, { recursive: true }); await (0, node_fs_promises.writeFile)(skillFile, renderTemplate(skillName), "utf-8"); logger.success(`Initialized skill ${picocolors.default.bold(skillName)}`); console.log(` ${picocolors.default.dim("Created:")} ${displayPath}`); console.log(); console.log(picocolors.default.dim("Next steps:")); console.log(` 1. Edit ${picocolors.default.cyan(displayPath)} to define your skill instructions`); console.log(` 2. Update the ${picocolors.default.cyan("name")} and ${picocolors.default.cyan("description")} frontmatter`); console.log(` 3. Install it locally with ${picocolors.default.cyan(`agent-install skill add ./${hasExplicitName ? skillName : "."}`)}`); } catch (error) { logger.error(require_to_error_message.toErrorMessage(error)); process.exitCode = 1; } }); //#endregion //#region src/cli/commands/skill/list.ts const isUsableEntry = async (entry, fullPath) => { if (entry.isDirectory()) return true; if (!entry.isSymbolicLink()) return false; try { return (await (0, node_fs_promises.stat)(fullPath)).isDirectory(); } catch { return false; } }; const scanSkillsInDir = async (baseDir, agentType) => { const entries = await (0, node_fs_promises.readdir)(baseDir, { withFileTypes: true }).catch(() => []); const results = []; for (const entry of entries) { const skillDir = (0, node_path.join)(baseDir, entry.name); if (!await isUsableEntry(entry, skillDir)) continue; const skills = await require_skill.discoverSkills(skillDir); for (const skill of skills) results.push({ skill: skill.name, agent: agentType, description: skill.description, path: skill.path }); } return results; }; const dirExists = (path) => { try { return (0, node_fs.existsSync)(path); } catch { return false; } }; const getCanonicalDir = (isGlobal, cwd) => isGlobal ? (0, node_path.join)((0, node_os.homedir)(), require_skill.CANONICAL_SKILLS_DIR) : (0, node_path.join)(cwd, require_skill.CANONICAL_SKILLS_DIR); const collectListEntries = async (options) => { const { isGlobal, cwd, filter } = options; const allEntries = []; const visitedDirs = /* @__PURE__ */ new Set(); const visit = async (dir, agent) => { if (visitedDirs.has(dir)) return; visitedDirs.add(dir); allEntries.push(...await scanSkillsInDir(dir, agent)); }; if (filter) { for (const agentType of filter) await visit(require_skill.getSkillAgentDir(agentType, { global: isGlobal, cwd }), agentType); return allEntries; } await visit(getCanonicalDir(isGlobal, cwd), "universal"); const installedAgents = new Set(await require_skill.detectInstalledSkillAgents()); for (const agentType of require_skill.getSkillAgentTypes()) { if (agentType === "universal") continue; if (require_skill.isUniversalSkillAgent(agentType)) continue; const baseDir = require_skill.getSkillAgentDir(agentType, { global: isGlobal, cwd }); if (!installedAgents.has(agentType) && !dirExists(baseDir)) continue; await visit(baseDir, agentType); } return allEntries; }; const skillListCommand = new commander.Command("list").alias("ls").description("List installed skills").option("-g, --global", "List global skills instead of project skills").option("-a, --agent ", "Filter by specific agents").option("--json", "Output as JSON").action(async (options) => { try { const cwd = process.cwd(); const allEntries = await collectListEntries({ isGlobal: Boolean(options.global), cwd, filter: parseSkillAgentList(options.agent) }); if (options.json) { console.log(JSON.stringify(allEntries, null, 2)); return; } if (allEntries.length === 0) { logger.warn("No installed skills found"); return; } const bySkill = /* @__PURE__ */ new Map(); for (const entry of allEntries) { const existing = bySkill.get(entry.skill) ?? []; existing.push(entry); bySkill.set(entry.skill, existing); } const formatAgent = (agent) => agent === "universal" ? "canonical" : require_skill.skillAgents[agent].displayName; for (const [skillName, entries] of bySkill) { const first = entries[0]; if (!first) continue; const agentLabels = Array.from(new Set(entries.map((entry) => formatAgent(entry.agent)))); const description = first.description || (0, node_path.basename)(first.path); console.log(` ${picocolors.default.bold(skillName)} ${picocolors.default.dim(`[${agentLabels.join(", ")}]`)}\n ${picocolors.default.dim(description)}`); } } catch (error) { logger.error(require_to_error_message.toErrorMessage(error)); process.exitCode = 1; } }); //#endregion //#region src/cli/commands/skill/remove.ts const skillRemoveCommand = new commander.Command("remove").alias("rm").description("Remove installed skills").argument("[skills...]", "Skills to remove (omit for interactive selection)").option("-g, --global", "Remove from global scope").option("-a, --agent ", "Remove from specific agents (use '*' for all)").option("-y, --yes", "Skip confirmation prompts").action(async (skillArgs, options) => { try { const cwd = process.cwd(); const isGlobal = Boolean(options.global); const agentFilter = parseSkillAgentList(options.agent) ?? require_skill.getSkillAgentTypes(); let skillNames = skillArgs; if (skillNames.length === 0) { if (options.yes || !process.stdin.isTTY) { logger.warn("No skill names provided"); return; } const response = await (0, prompts.default)({ type: "text", name: "skill", message: "Skill name to remove" }); if (!response.skill) return; skillNames = [response.skill]; } const canonicalBase = isGlobal ? (0, node_path.join)((0, node_os.homedir)(), require_skill.CANONICAL_SKILLS_DIR) : (0, node_path.join)(cwd, require_skill.CANONICAL_SKILLS_DIR); for (const rawName of skillNames) { const sanitized = require_skill.sanitizeName(rawName); await (0, node_fs_promises.rm)((0, node_path.join)(canonicalBase, sanitized), { recursive: true, force: true }).catch(() => {}); for (const agentType of agentFilter) { if (agentType === "universal") continue; await (0, node_fs_promises.rm)((0, node_path.join)(require_skill.getSkillAgentDir(agentType, { global: isGlobal, cwd }), sanitized), { recursive: true, force: true }).catch(() => {}); } logger.success(`Removed ${picocolors.default.bold(rawName)}`); } } catch (error) { logger.error(require_to_error_message.toErrorMessage(error)); process.exitCode = 1; } }); //#endregion //#region src/cli/commands/skill/index.ts const skillCommand = new commander.Command("skill").description("Manage SKILL.md files").addCommand(skillAddCommand).addCommand(skillInitCommand).addCommand(skillListCommand).addCommand(skillRemoveCommand); //#endregion //#region src/cli.ts const VERSION = "0.0.6"; process.on("SIGINT", () => process.exit(0)); process.on("SIGTERM", () => process.exit(0)); const program = new commander.Command().name("agent-install").description("Install SKILL.md files, MCP servers, and AGENTS.md guidance for any coding agent").version(VERSION, "-v, --version", "display the version number"); program.addCommand(skillCommand); program.addCommand(mcpCommand); program.addCommand(docCommand); const main = async () => { await program.parseAsync(); }; main(); //#endregion