@cleocode/caamp 0.2.0 → 0.4.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/registry/providers.ts","../src/core/logger.ts","../src/core/registry/detection.ts","../src/core/sources/parser.ts","../src/core/skills/installer.ts","../src/core/lock-utils.ts","../src/core/skills/lock.ts","../src/core/network/fetch.ts","../src/core/marketplace/skillsmp.ts","../src/core/marketplace/skillssh.ts","../src/core/marketplace/client.ts","../src/core/skills/discovery.ts","../src/core/skills/recommendation.ts","../src/core/skills/recommendation-api.ts","../src/core/skills/audit/scanner.ts","../src/core/skills/audit/rules.ts","../src/core/skills/validator.ts","../src/core/formats/utils.ts","../src/core/formats/json.ts","../src/core/formats/yaml.ts","../src/core/formats/toml.ts","../src/core/formats/index.ts","../src/core/mcp/transforms.ts","../src/core/mcp/reader.ts","../src/core/mcp/installer.ts","../src/core/mcp/lock.ts","../src/core/instructions/injector.ts","../src/core/instructions/templates.ts","../src/core/advanced/orchestration.ts"],"sourcesContent":["/**\n * Provider registry loader\n *\n * Loads providers from providers/registry.json and resolves\n * platform-specific paths at runtime.\n */\n\nimport { readFileSync, existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { Provider, ConfigFormat, TransportType, ProviderPriority, ProviderStatus, DetectionMethod } from \"../../types.js\";\nimport type { ProviderRegistry, RegistryProvider } from \"./types.js\";\n\nfunction findRegistryPath(): string {\n const thisDir = dirname(fileURLToPath(import.meta.url));\n\n // Development: src/core/registry/ -> ../../.. -> providers/registry.json\n const devPath = join(thisDir, \"..\", \"..\", \"..\", \"providers\", \"registry.json\");\n if (existsSync(devPath)) return devPath;\n\n // Bundled: dist/ -> .. -> providers/registry.json\n const distPath = join(thisDir, \"..\", \"providers\", \"registry.json\");\n if (existsSync(distPath)) return distPath;\n\n // Fallback: traverse up until we find it\n let dir = thisDir;\n for (let i = 0; i < 5; i++) {\n const candidate = join(dir, \"providers\", \"registry.json\");\n if (existsSync(candidate)) return candidate;\n dir = dirname(dir);\n }\n\n throw new Error(`Cannot find providers/registry.json (searched from ${thisDir})`);\n}\n\nlet _registry: ProviderRegistry | null = null;\nlet _providers: Map<string, Provider> | null = null;\nlet _aliasMap: Map<string, string> | null = null;\n\nfunction getPlatformPaths(): {\n config: string;\n vscodeConfig: string;\n zedConfig: string;\n claudeDesktopConfig: string;\n} {\n const home = homedir();\n const platform = process.platform;\n\n if (platform === \"win32\") {\n const appData = process.env[\"APPDATA\"] ?? join(home, \"AppData\", \"Roaming\");\n return {\n config: appData,\n vscodeConfig: join(appData, \"Code\", \"User\"),\n zedConfig: join(appData, \"Zed\"),\n claudeDesktopConfig: join(appData, \"Claude\"),\n };\n } else if (platform === \"darwin\") {\n return {\n config: process.env[\"XDG_CONFIG_HOME\"] ?? join(home, \".config\"),\n vscodeConfig: join(home, \"Library\", \"Application Support\", \"Code\", \"User\"),\n zedConfig: join(home, \"Library\", \"Application Support\", \"Zed\"),\n claudeDesktopConfig: join(home, \"Library\", \"Application Support\", \"Claude\"),\n };\n } else {\n const config = process.env[\"XDG_CONFIG_HOME\"] ?? join(home, \".config\");\n return {\n config,\n vscodeConfig: join(config, \"Code\", \"User\"),\n zedConfig: join(config, \"zed\"),\n claudeDesktopConfig: join(config, \"Claude\"),\n };\n }\n}\n\nfunction resolvePath(template: string): string {\n const home = homedir();\n const paths = getPlatformPaths();\n\n return template\n .replace(/\\$HOME/g, home)\n .replace(/\\$CONFIG/g, paths.config)\n .replace(/\\$VSCODE_CONFIG/g, paths.vscodeConfig)\n .replace(/\\$ZED_CONFIG/g, paths.zedConfig)\n .replace(/\\$CLAUDE_DESKTOP_CONFIG/g, paths.claudeDesktopConfig);\n}\n\nfunction resolveProvider(raw: RegistryProvider): Provider {\n return {\n id: raw.id,\n toolName: raw.toolName,\n vendor: raw.vendor,\n agentFlag: raw.agentFlag,\n aliases: raw.aliases,\n pathGlobal: resolvePath(raw.pathGlobal),\n pathProject: raw.pathProject,\n instructFile: raw.instructFile,\n configKey: raw.configKey,\n configFormat: raw.configFormat as ConfigFormat,\n configPathGlobal: resolvePath(raw.configPathGlobal),\n configPathProject: raw.configPathProject,\n pathSkills: resolvePath(raw.pathSkills),\n pathProjectSkills: raw.pathProjectSkills,\n detection: {\n methods: raw.detection.methods as DetectionMethod[],\n binary: raw.detection.binary,\n directories: raw.detection.directories?.map(resolvePath),\n appBundle: raw.detection.appBundle,\n flatpakId: raw.detection.flatpakId,\n },\n supportedTransports: raw.supportedTransports as TransportType[],\n supportsHeaders: raw.supportsHeaders,\n priority: raw.priority as ProviderPriority,\n status: raw.status as ProviderStatus,\n agentSkillsCompatible: raw.agentSkillsCompatible,\n };\n}\n\nfunction loadRegistry(): ProviderRegistry {\n if (_registry) return _registry;\n\n const registryPath = findRegistryPath();\n const raw = readFileSync(registryPath, \"utf-8\");\n _registry = JSON.parse(raw) as ProviderRegistry;\n return _registry;\n}\n\nfunction ensureProviders(): void {\n if (_providers) return;\n\n const registry = loadRegistry();\n _providers = new Map<string, Provider>();\n _aliasMap = new Map<string, string>();\n\n for (const [id, raw] of Object.entries(registry.providers)) {\n const provider = resolveProvider(raw);\n _providers.set(id, provider);\n\n // Build alias map\n for (const alias of provider.aliases) {\n _aliasMap.set(alias, id);\n }\n }\n}\n\n/**\n * Retrieve all registered providers with resolved platform paths.\n *\n * Providers are lazily loaded from `providers/registry.json` on first call\n * and cached for subsequent calls.\n *\n * @returns Array of all provider definitions\n *\n * @example\n * ```typescript\n * const providers = getAllProviders();\n * console.log(`${providers.length} providers registered`);\n * ```\n */\nexport function getAllProviders(): Provider[] {\n ensureProviders();\n return Array.from(_providers!.values());\n}\n\n/**\n * Look up a provider by its ID or any of its aliases.\n *\n * @param idOrAlias - Provider ID (e.g. `\"claude-code\"`) or alias (e.g. `\"claude\"`)\n * @returns The matching provider, or `undefined` if not found\n *\n * @example\n * ```typescript\n * const provider = getProvider(\"claude\");\n * // Returns the claude-code provider via alias resolution\n * ```\n */\nexport function getProvider(idOrAlias: string): Provider | undefined {\n ensureProviders();\n const resolved = _aliasMap!.get(idOrAlias) ?? idOrAlias;\n return _providers!.get(resolved);\n}\n\n/**\n * Resolve an alias to its canonical provider ID.\n *\n * If the input is already a canonical ID (or unrecognized), it is returned as-is.\n *\n * @param idOrAlias - Provider ID or alias to resolve\n * @returns The canonical provider ID\n *\n * @example\n * ```typescript\n * resolveAlias(\"claude\"); // \"claude-code\"\n * resolveAlias(\"claude-code\"); // \"claude-code\"\n * resolveAlias(\"unknown\"); // \"unknown\"\n * ```\n */\nexport function resolveAlias(idOrAlias: string): string {\n ensureProviders();\n return _aliasMap!.get(idOrAlias) ?? idOrAlias;\n}\n\n/**\n * Filter providers by their priority tier.\n *\n * @param priority - Priority level to filter by (`\"high\"`, `\"medium\"`, or `\"low\"`)\n * @returns Array of providers matching the given priority\n *\n * @example\n * ```typescript\n * const highPriority = getProvidersByPriority(\"high\");\n * ```\n */\nexport function getProvidersByPriority(priority: ProviderPriority): Provider[] {\n return getAllProviders().filter((p) => p.priority === priority);\n}\n\n/**\n * Filter providers by their lifecycle status.\n *\n * @param status - Status to filter by (`\"active\"`, `\"beta\"`, `\"deprecated\"`, or `\"planned\"`)\n * @returns Array of providers matching the given status\n *\n * @example\n * ```typescript\n * const active = getProvidersByStatus(\"active\");\n * ```\n */\nexport function getProvidersByStatus(status: ProviderStatus): Provider[] {\n return getAllProviders().filter((p) => p.status === status);\n}\n\n/**\n * Filter providers that use a specific instruction file.\n *\n * Multiple providers often share the same instruction file (e.g. many use `\"AGENTS.md\"`).\n *\n * @param file - Instruction file name (e.g. `\"CLAUDE.md\"`, `\"AGENTS.md\"`)\n * @returns Array of providers that use the given instruction file\n *\n * @example\n * ```typescript\n * const claudeProviders = getProvidersByInstructFile(\"CLAUDE.md\");\n * ```\n */\nexport function getProvidersByInstructFile(file: string): Provider[] {\n return getAllProviders().filter((p) => p.instructFile === file);\n}\n\n/**\n * Get the set of all unique instruction file names across all providers.\n *\n * @returns Array of unique instruction file names (e.g. `[\"CLAUDE.md\", \"AGENTS.md\", \"GEMINI.md\"]`)\n *\n * @example\n * ```typescript\n * const files = getInstructionFiles();\n * // [\"CLAUDE.md\", \"AGENTS.md\", \"GEMINI.md\"]\n * ```\n */\nexport function getInstructionFiles(): string[] {\n const files = new Set<string>();\n for (const p of getAllProviders()) {\n files.add(p.instructFile);\n }\n return Array.from(files);\n}\n\n/**\n * Get the total number of registered providers.\n *\n * @returns Count of providers in the registry\n *\n * @example\n * ```typescript\n * console.log(`Registry has ${getProviderCount()} providers`);\n * ```\n */\nexport function getProviderCount(): number {\n ensureProviders();\n return _providers!.size;\n}\n\n/**\n * Get the semantic version string of the provider registry.\n *\n * @returns Version string from `providers/registry.json` (e.g. `\"1.0.0\"`)\n *\n * @example\n * ```typescript\n * console.log(`Registry version: ${getRegistryVersion()}`);\n * ```\n */\nexport function getRegistryVersion(): string {\n return loadRegistry().version;\n}\n\n/** Reset cached data (for testing) */\nexport function resetRegistry(): void {\n _registry = null;\n _providers = null;\n _aliasMap = null;\n}\n","/**\n * Simple logger with verbose/quiet mode support.\n *\n * - verbose: enables debug output to stderr\n * - quiet: suppresses info and warn output (errors always shown)\n */\n\nlet verboseMode = false;\nlet quietMode = false;\n\n/**\n * Enable or disable verbose (debug) logging mode.\n *\n * When enabled, debug messages are written to stderr.\n *\n * @param v - `true` to enable verbose mode, `false` to disable\n *\n * @example\n * ```typescript\n * setVerbose(true);\n * ```\n */\nexport function setVerbose(v: boolean): void {\n verboseMode = v;\n}\n\n/**\n * Enable or disable quiet mode.\n *\n * When enabled, info and warning messages are suppressed. Errors are always shown.\n *\n * @param q - `true` to enable quiet mode, `false` to disable\n *\n * @example\n * ```typescript\n * setQuiet(true);\n * ```\n */\nexport function setQuiet(q: boolean): void {\n quietMode = q;\n}\n\nexport function debug(...args: unknown[]): void {\n if (verboseMode) console.error(\"[debug]\", ...args);\n}\n\nexport function info(...args: unknown[]): void {\n if (!quietMode) console.log(...args);\n}\n\nexport function warn(...args: unknown[]): void {\n if (!quietMode) console.warn(...args);\n}\n\nexport function error(...args: unknown[]): void {\n console.error(...args);\n}\n\n/**\n * Check if verbose (debug) logging is currently enabled.\n *\n * @returns `true` if verbose mode is active\n *\n * @example\n * ```typescript\n * if (isVerbose()) {\n * console.error(\"Extra debug info\");\n * }\n * ```\n */\nexport function isVerbose(): boolean {\n return verboseMode;\n}\n\n/**\n * Check if quiet mode is currently enabled.\n *\n * @returns `true` if quiet mode is active\n *\n * @example\n * ```typescript\n * if (!isQuiet()) {\n * console.log(\"Status message\");\n * }\n * ```\n */\nexport function isQuiet(): boolean {\n return quietMode;\n}\n","/**\n * Provider auto-detection engine\n *\n * Detects which AI coding agents are installed on the system\n * by checking binaries, directories, app bundles, and flatpak.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { execFileSync } from \"node:child_process\";\nimport { join } from \"node:path\";\nimport type { Provider } from \"../../types.js\";\nimport { getAllProviders } from \"./providers.js\";\nimport { debug } from \"../logger.js\";\n\n/**\n * Result of detecting whether a provider is installed on the system.\n *\n * @example\n * ```typescript\n * const result = detectProvider(provider);\n * if (result.installed) {\n * console.log(`Found via: ${result.methods.join(\", \")}`);\n * }\n * ```\n */\nexport interface DetectionResult {\n /** The provider that was checked. */\n provider: Provider;\n /** Whether the provider was detected as installed. */\n installed: boolean;\n /** Detection methods that matched (e.g. `[\"binary\", \"directory\"]`). */\n methods: string[];\n /** Whether the provider has project-level config in the current directory. */\n projectDetected: boolean;\n}\n\nfunction checkBinary(binary: string): boolean {\n try {\n const cmd = process.platform === \"win32\" ? \"where\" : \"which\";\n execFileSync(cmd, [binary], { stdio: \"pipe\" });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction checkDirectory(dir: string): boolean {\n return existsSync(dir);\n}\n\nfunction checkAppBundle(appName: string): boolean {\n if (process.platform !== \"darwin\") return false;\n return existsSync(join(\"/Applications\", appName));\n}\n\nfunction checkFlatpak(flatpakId: string): boolean {\n if (process.platform !== \"linux\") return false;\n try {\n execFileSync(\"flatpak\", [\"info\", flatpakId], { stdio: \"pipe\" });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Detect if a single provider is installed on the system.\n *\n * Checks each detection method configured for the provider (binary, directory,\n * appBundle, flatpak) and returns which methods matched.\n *\n * @param provider - The provider to detect\n * @returns Detection result with installation status and matched methods\n *\n * @example\n * ```typescript\n * const provider = getProvider(\"claude-code\")!;\n * const result = detectProvider(provider);\n * if (result.installed) {\n * console.log(`Claude Code found via: ${result.methods.join(\", \")}`);\n * }\n * ```\n */\nexport function detectProvider(provider: Provider): DetectionResult {\n const matchedMethods: string[] = [];\n const detection = provider.detection;\n\n debug(`detecting provider ${provider.id} via methods: ${detection.methods.join(\", \")}`);\n\n for (const method of detection.methods) {\n switch (method) {\n case \"binary\":\n if (detection.binary && checkBinary(detection.binary)) {\n debug(` ${provider.id}: binary \"${detection.binary}\" found`);\n matchedMethods.push(\"binary\");\n }\n break;\n case \"directory\":\n if (detection.directories) {\n for (const dir of detection.directories) {\n if (checkDirectory(dir)) {\n matchedMethods.push(\"directory\");\n break;\n }\n }\n }\n break;\n case \"appBundle\":\n if (detection.appBundle && checkAppBundle(detection.appBundle)) {\n matchedMethods.push(\"appBundle\");\n }\n break;\n case \"flatpak\":\n if (detection.flatpakId && checkFlatpak(detection.flatpakId)) {\n matchedMethods.push(\"flatpak\");\n }\n break;\n }\n }\n\n return {\n provider,\n installed: matchedMethods.length > 0,\n methods: matchedMethods,\n projectDetected: false,\n };\n}\n\n/** Detect if a provider has project-level config in the given directory */\nexport function detectProjectProvider(provider: Provider, projectDir: string): boolean {\n if (!provider.pathProject) return false;\n return existsSync(join(projectDir, provider.pathProject));\n}\n\n/**\n * Detect all registered providers and return their installation status.\n *\n * Runs detection for every provider in the registry.\n *\n * @returns Array of detection results for all providers\n *\n * @example\n * ```typescript\n * const results = detectAllProviders();\n * const installed = results.filter(r => r.installed);\n * console.log(`${installed.length} agents detected`);\n * ```\n */\nexport function detectAllProviders(): DetectionResult[] {\n const providers = getAllProviders();\n return providers.map(detectProvider);\n}\n\n/**\n * Get only providers that are currently installed on the system.\n *\n * Convenience wrapper that filters {@link detectAllProviders} results to only\n * those with `installed === true`.\n *\n * @returns Array of installed provider definitions\n *\n * @example\n * ```typescript\n * const installed = getInstalledProviders();\n * console.log(installed.map(p => p.toolName).join(\", \"));\n * ```\n */\nexport function getInstalledProviders(): Provider[] {\n return detectAllProviders()\n .filter((r) => r.installed)\n .map((r) => r.provider);\n}\n\n/**\n * Detect all providers and enrich results with project-level presence.\n *\n * Extends {@link detectAllProviders} by also checking whether each provider\n * has a project-level config file in the given directory.\n *\n * @param projectDir - Absolute path to the project directory to check\n * @returns Array of detection results with `projectDetected` populated\n *\n * @example\n * ```typescript\n * const results = detectProjectProviders(\"/home/user/my-project\");\n * for (const r of results) {\n * if (r.projectDetected) {\n * console.log(`${r.provider.toolName} has project config`);\n * }\n * }\n * ```\n */\nexport function detectProjectProviders(projectDir: string): DetectionResult[] {\n const results = detectAllProviders();\n return results.map((r) => ({\n ...r,\n projectDetected: detectProjectProvider(r.provider, projectDir),\n }));\n}\n","/**\n * Source URL/path classifier\n *\n * Classifies inputs as remote URLs, npm packages, GitHub shorthand,\n * GitLab URLs, local paths, or shell commands.\n */\n\nimport type { ParsedSource, SourceType } from \"../../types.js\";\n\nconst GITHUB_SHORTHAND = /^([a-zA-Z0-9_.-]+)\\/([a-zA-Z0-9_.-]+)(?:\\/(.+))?$/;\nconst GITHUB_URL = /^https?:\\/\\/(?:www\\.)?github\\.com\\/([^/]+)\\/([^/]+)(?:\\/tree\\/([^/]+)(?:\\/(.+))?)?/;\nconst GITLAB_URL = /^https?:\\/\\/(?:www\\.)?gitlab\\.com\\/([^/]+)\\/([^/]+)(?:\\/-\\/tree\\/([^/]+)(?:\\/(.+))?)?/;\nconst HTTP_URL = /^https?:\\/\\//;\nconst NPM_SCOPED = /^@[a-zA-Z0-9_.-]+\\/[a-zA-Z0-9_.-]+$/;\nconst NPM_PACKAGE = /^[a-zA-Z0-9_.-]+$/;\n\n/** Infer a display name from a source */\nfunction inferName(source: string, type: SourceType): string {\n if (type === \"remote\") {\n try {\n const url = new URL(source);\n // Extract brand from hostname: mcp.neon.tech -> neon\n const parts = url.hostname.split(\".\");\n if (parts.length >= 2) {\n const brand = parts.length === 3 ? parts[parts.length - 2]! : parts[0]!;\n if (brand !== \"www\" && brand !== \"api\" && brand !== \"mcp\") {\n return brand;\n }\n // Fall back to second-level domain\n return parts[parts.length - 2] ?? parts[0]!;\n }\n return parts[0]!;\n } catch {\n return source;\n }\n }\n\n if (type === \"package\") {\n // Strip common MCP prefixes/suffixes\n let name = source.replace(/^@[^/]+\\//, \"\"); // Remove scope\n name = name.replace(/^mcp-server-/, \"\");\n name = name.replace(/^server-/, \"\");\n name = name.replace(/-mcp$/, \"\");\n name = name.replace(/-server$/, \"\");\n return name;\n }\n\n if (type === \"github\" || type === \"gitlab\") {\n // Use repo name\n const match = source.match(/\\/([^/]+?)(?:\\.git)?$/);\n return match?.[1] ?? source;\n }\n\n if (type === \"command\") {\n // Extract first meaningful word\n const parts = source.split(/\\s+/);\n const command = parts.find((p) => !p.startsWith(\"-\") && p !== \"npx\" && p !== \"node\" && p !== \"python\" && p !== \"python3\");\n return command ?? parts[0] ?? source;\n }\n\n return source;\n}\n\n/**\n * Parse and classify a source string into a typed {@link ParsedSource}.\n *\n * Supports GitHub URLs, GitLab URLs, GitHub shorthand (`owner/repo`),\n * HTTP URLs (remote MCP servers), npm package names, local paths, and\n * shell commands as a fallback.\n *\n * @param input - Raw source string to classify\n * @returns Parsed source with type, value, and inferred name\n *\n * @example\n * ```typescript\n * parseSource(\"owner/repo\");\n * // { type: \"github\", value: \"https://github.com/owner/repo\", inferredName: \"repo\", ... }\n *\n * parseSource(\"https://mcp.example.com/sse\");\n * // { type: \"remote\", value: \"https://mcp.example.com/sse\", inferredName: \"example\" }\n *\n * parseSource(\"@modelcontextprotocol/server-filesystem\");\n * // { type: \"package\", value: \"@modelcontextprotocol/server-filesystem\", inferredName: \"filesystem\" }\n * ```\n */\nexport function parseSource(input: string): ParsedSource {\n // GitHub URL\n const ghUrlMatch = input.match(GITHUB_URL);\n if (ghUrlMatch) {\n return {\n type: \"github\",\n value: input,\n inferredName: ghUrlMatch[2]!,\n owner: ghUrlMatch[1],\n repo: ghUrlMatch[2],\n ref: ghUrlMatch[3],\n path: ghUrlMatch[4],\n };\n }\n\n // GitLab URL\n const glUrlMatch = input.match(GITLAB_URL);\n if (glUrlMatch) {\n return {\n type: \"gitlab\",\n value: input,\n inferredName: glUrlMatch[2]!,\n owner: glUrlMatch[1],\n repo: glUrlMatch[2],\n ref: glUrlMatch[3],\n path: glUrlMatch[4],\n };\n }\n\n // HTTP URL (non-GitHub/GitLab = remote MCP server)\n if (HTTP_URL.test(input)) {\n return {\n type: \"remote\",\n value: input,\n inferredName: inferName(input, \"remote\"),\n };\n }\n\n // Local path (check before GitHub shorthand since ./ and ../ match shorthand regex)\n if (input.startsWith(\"/\") || input.startsWith(\"./\") || input.startsWith(\"../\") || input.startsWith(\"~\")) {\n return {\n type: \"local\",\n value: input,\n inferredName: inferName(input, \"local\"),\n };\n }\n\n // GitHub shorthand: owner/repo or owner/repo/path\n const ghShorthand = input.match(GITHUB_SHORTHAND);\n if (ghShorthand && !NPM_SCOPED.test(input)) {\n return {\n type: \"github\",\n value: `https://github.com/${ghShorthand[1]}/${ghShorthand[2]}`,\n inferredName: ghShorthand[2]!,\n owner: ghShorthand[1],\n repo: ghShorthand[2],\n path: ghShorthand[3],\n };\n }\n\n // Scoped npm package: @scope/name\n if (NPM_SCOPED.test(input)) {\n return {\n type: \"package\",\n value: input,\n inferredName: inferName(input, \"package\"),\n };\n }\n\n // Simple npm package name (no spaces, no slashes)\n if (NPM_PACKAGE.test(input) && !input.includes(\" \")) {\n return {\n type: \"package\",\n value: input,\n inferredName: inferName(input, \"package\"),\n };\n }\n\n // Default: treat as command\n return {\n type: \"command\",\n value: input,\n inferredName: inferName(input, \"command\"),\n };\n}\n\n/**\n * Check if a source string looks like a marketplace scoped name (`@author/name`).\n *\n * @param input - Source string to check\n * @returns `true` if the input matches the `@scope/name` pattern\n *\n * @example\n * ```typescript\n * isMarketplaceScoped(\"@anthropic/my-skill\"); // true\n * isMarketplaceScoped(\"my-skill\"); // false\n * isMarketplaceScoped(\"owner/repo\"); // false\n * ```\n */\nexport function isMarketplaceScoped(input: string): boolean {\n return /^@[a-zA-Z0-9_.-]+\\/[a-zA-Z0-9_.-]+$/.test(input);\n}\n","/**\n * Skill installer - canonical + symlink model\n *\n * Skills are stored once in a canonical location (.agents/skills/<name>/)\n * and symlinked to each target agent's skills directory.\n */\n\nimport { readFile, writeFile, mkdir, symlink, readlink, rm, cp } from \"node:fs/promises\";\nimport { existsSync, lstatSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join, relative, resolve } from \"node:path\";\nimport type { Provider, SkillMetadata, ParsedSource } from \"../../types.js\";\nimport { discoverSkill } from \"./discovery.js\";\n\nconst CANONICAL_DIR = join(homedir(), \".agents\", \"skills\");\n\n/**\n * Result of installing a skill to the canonical location and linking to agents.\n *\n * @example\n * ```typescript\n * const result = await installSkill(sourcePath, \"my-skill\", providers, true);\n * if (result.success) {\n * console.log(`Installed to ${result.canonicalPath}`);\n * console.log(`Linked to: ${result.linkedAgents.join(\", \")}`);\n * }\n * ```\n */\nexport interface SkillInstallResult {\n /** Skill name. */\n name: string;\n /** Absolute path to the canonical installation directory. */\n canonicalPath: string;\n /** Provider IDs that were successfully linked. */\n linkedAgents: string[];\n /** Error messages from failed link operations. */\n errors: string[];\n /** Whether at least one agent was successfully linked. */\n success: boolean;\n}\n\n/** Ensure canonical skills directory exists */\nasync function ensureCanonicalDir(): Promise<void> {\n await mkdir(CANONICAL_DIR, { recursive: true });\n}\n\n/** Copy skill files to the canonical location */\nexport async function installToCanonical(\n sourcePath: string,\n skillName: string,\n): Promise<string> {\n await ensureCanonicalDir();\n\n const targetDir = join(CANONICAL_DIR, skillName);\n\n // Remove existing if it exists\n if (existsSync(targetDir)) {\n await rm(targetDir, { recursive: true });\n }\n\n await cp(sourcePath, targetDir, { recursive: true });\n\n return targetDir;\n}\n\n/** Create a symlink from an agent's skills directory to the canonical location */\nasync function linkToAgent(\n canonicalPath: string,\n provider: Provider,\n skillName: string,\n isGlobal: boolean,\n projectDir?: string,\n): Promise<{ success: boolean; error?: string }> {\n const targetSkillsDir = isGlobal\n ? provider.pathSkills\n : join(projectDir ?? process.cwd(), provider.pathProjectSkills);\n\n if (!targetSkillsDir) {\n return { success: false, error: `Provider ${provider.id} has no skills directory` };\n }\n\n try {\n await mkdir(targetSkillsDir, { recursive: true });\n\n const linkPath = join(targetSkillsDir, skillName);\n\n // Remove existing link/directory\n if (existsSync(linkPath)) {\n const stat = lstatSync(linkPath);\n if (stat.isSymbolicLink()) {\n await rm(linkPath);\n } else {\n await rm(linkPath, { recursive: true });\n }\n }\n\n // Create symlink (junction on Windows for compat)\n const symlinkType = process.platform === \"win32\" ? \"junction\" : \"dir\";\n try {\n await symlink(canonicalPath, linkPath, symlinkType);\n } catch {\n // Fallback to copy if symlinks not supported\n await cp(canonicalPath, linkPath, { recursive: true });\n }\n\n return { success: true };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\n/**\n * Install a skill from a local path to the canonical location and link to agents.\n *\n * Copies the skill directory to `~/.agents/skills/<name>/` and creates symlinks\n * (or copies on Windows) from each provider's skills directory to the canonical path.\n *\n * @param sourcePath - Local path to the skill directory to install\n * @param skillName - Name for the installed skill\n * @param providers - Target providers to link the skill to\n * @param isGlobal - Whether to link to global or project skill directories\n * @param projectDir - Project directory (defaults to `process.cwd()`)\n * @returns Install result with linked agents and any errors\n *\n * @example\n * ```typescript\n * const result = await installSkill(\"/tmp/my-skill\", \"my-skill\", providers, true);\n * ```\n */\nexport async function installSkill(\n sourcePath: string,\n skillName: string,\n providers: Provider[],\n isGlobal: boolean,\n projectDir?: string,\n): Promise<SkillInstallResult> {\n const errors: string[] = [];\n const linkedAgents: string[] = [];\n\n // Step 1: Install to canonical location\n const canonicalPath = await installToCanonical(sourcePath, skillName);\n\n // Step 2: Link to each agent\n for (const provider of providers) {\n const result = await linkToAgent(canonicalPath, provider, skillName, isGlobal, projectDir);\n if (result.success) {\n linkedAgents.push(provider.id);\n } else if (result.error) {\n errors.push(`${provider.id}: ${result.error}`);\n }\n }\n\n return {\n name: skillName,\n canonicalPath,\n linkedAgents,\n errors,\n success: linkedAgents.length > 0,\n };\n}\n\n/**\n * Remove a skill from the canonical location and all agent symlinks.\n *\n * Removes symlinks from each provider's skills directory and then removes the\n * canonical copy from `~/.agents/skills/<name>/`.\n *\n * @param skillName - Name of the skill to remove\n * @param providers - Providers to unlink the skill from\n * @param isGlobal - Whether to target global or project skill directories\n * @param projectDir - Project directory (defaults to `process.cwd()`)\n * @returns Object with arrays of successfully removed provider IDs and error messages\n *\n * @example\n * ```typescript\n * const { removed, errors } = await removeSkill(\"my-skill\", providers, true);\n * ```\n */\nexport async function removeSkill(\n skillName: string,\n providers: Provider[],\n isGlobal: boolean,\n projectDir?: string,\n): Promise<{ removed: string[]; errors: string[] }> {\n const removed: string[] = [];\n const errors: string[] = [];\n\n // Remove symlinks from each agent\n for (const provider of providers) {\n const skillsDir = isGlobal\n ? provider.pathSkills\n : join(projectDir ?? process.cwd(), provider.pathProjectSkills);\n\n if (!skillsDir) continue;\n\n const linkPath = join(skillsDir, skillName);\n if (existsSync(linkPath)) {\n try {\n await rm(linkPath, { recursive: true });\n removed.push(provider.id);\n } catch (err) {\n errors.push(`${provider.id}: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n }\n\n // Remove canonical copy\n const canonicalPath = join(CANONICAL_DIR, skillName);\n if (existsSync(canonicalPath)) {\n try {\n await rm(canonicalPath, { recursive: true });\n } catch (err) {\n errors.push(`canonical: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n return { removed, errors };\n}\n\n/**\n * List all skills installed in the canonical directory (`~/.agents/skills/`).\n *\n * Returns the directory names of all skills, which correspond to skill names.\n *\n * @returns Array of skill names\n *\n * @example\n * ```typescript\n * const skills = await listCanonicalSkills();\n * // [\"my-skill\", \"another-skill\"]\n * ```\n */\nexport async function listCanonicalSkills(): Promise<string[]> {\n if (!existsSync(CANONICAL_DIR)) return [];\n\n const { readdir } = await import(\"node:fs/promises\");\n const entries = await readdir(CANONICAL_DIR, { withFileTypes: true });\n return entries\n .filter((e) => e.isDirectory() || e.isSymbolicLink())\n .map((e) => e.name);\n}\n","/**\n * Shared lock file utilities\n *\n * Single source of truth for reading/writing ~/.agents/.caamp-lock.json.\n * Both MCP and skills lock modules import from here.\n */\n\nimport { readFile, writeFile, mkdir } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { CaampLockFile } from \"../types.js\";\n\nconst LOCK_DIR = join(homedir(), \".agents\");\nconst LOCK_FILE = join(LOCK_DIR, \".caamp-lock.json\");\n\n/** Read the lock file */\nexport async function readLockFile(): Promise<CaampLockFile> {\n try {\n if (!existsSync(LOCK_FILE)) {\n return { version: 1, skills: {}, mcpServers: {} };\n }\n const content = await readFile(LOCK_FILE, \"utf-8\");\n return JSON.parse(content) as CaampLockFile;\n } catch {\n return { version: 1, skills: {}, mcpServers: {} };\n }\n}\n\n/** Write the lock file */\nexport async function writeLockFile(lock: CaampLockFile): Promise<void> {\n await mkdir(LOCK_DIR, { recursive: true });\n await writeFile(LOCK_FILE, JSON.stringify(lock, null, 2) + \"\\n\", \"utf-8\");\n}\n","/**\n * Skills lock file management\n *\n * Shares the same lock file as MCP (~/.agents/.caamp-lock.json).\n */\n\nimport type { LockEntry, SourceType } from \"../../types.js\";\nimport { readLockFile, writeLockFile } from \"../lock-utils.js\";\nimport { parseSource } from \"../sources/parser.js\";\nimport { simpleGit } from \"simple-git\";\n\n/**\n * Record a skill installation in the lock file.\n *\n * Creates or updates an entry in `lock.skills`. If the skill already exists,\n * the agent list is merged and `updatedAt` is refreshed while `installedAt` is preserved.\n *\n * @param skillName - Skill name\n * @param scopedName - Scoped name (may include marketplace scope)\n * @param source - Original source string\n * @param sourceType - Classified source type\n * @param agents - Provider IDs the skill was linked to\n * @param canonicalPath - Absolute path to the canonical installation\n * @param isGlobal - Whether this is a global installation\n * @param projectDir - Project directory (for project-scoped installs)\n * @param version - Version string or commit SHA\n *\n * @example\n * ```typescript\n * await recordSkillInstall(\n * \"my-skill\", \"my-skill\", \"owner/repo\", \"github\",\n * [\"claude-code\"], \"/home/user/.agents/skills/my-skill\", true,\n * );\n * ```\n */\nexport async function recordSkillInstall(\n skillName: string,\n scopedName: string,\n source: string,\n sourceType: SourceType,\n agents: string[],\n canonicalPath: string,\n isGlobal: boolean,\n projectDir?: string,\n version?: string,\n): Promise<void> {\n const lock = await readLockFile();\n const now = new Date().toISOString();\n\n const existing = lock.skills[skillName];\n\n lock.skills[skillName] = {\n name: skillName,\n scopedName,\n source,\n sourceType,\n version,\n installedAt: existing?.installedAt ?? now,\n updatedAt: now,\n agents: [...new Set([...(existing?.agents ?? []), ...agents])],\n canonicalPath,\n isGlobal,\n projectDir,\n };\n\n await writeLockFile(lock);\n}\n\n/**\n * Remove a skill entry from the lock file.\n *\n * @param skillName - Name of the skill to remove\n * @returns `true` if the entry was found and removed, `false` if not found\n *\n * @example\n * ```typescript\n * const removed = await removeSkillFromLock(\"my-skill\");\n * ```\n */\nexport async function removeSkillFromLock(skillName: string): Promise<boolean> {\n const lock = await readLockFile();\n if (!(skillName in lock.skills)) return false;\n\n delete lock.skills[skillName];\n await writeLockFile(lock);\n return true;\n}\n\n/**\n * Get all skills tracked in the lock file.\n *\n * @returns Record of skill name to lock entry\n *\n * @example\n * ```typescript\n * const skills = await getTrackedSkills();\n * for (const [name, entry] of Object.entries(skills)) {\n * console.log(`${name}: ${entry.source}`);\n * }\n * ```\n */\nexport async function getTrackedSkills(): Promise<Record<string, LockEntry>> {\n const lock = await readLockFile();\n return lock.skills;\n}\n\n/** Fetch the latest commit SHA for a GitHub/GitLab repo via ls-remote */\nasync function fetchLatestSha(\n repoUrl: string,\n ref?: string,\n): Promise<string | null> {\n try {\n const git = simpleGit();\n const target = ref ?? \"HEAD\";\n // Use --refs only for named refs (branches/tags), not for HEAD\n const args = target === \"HEAD\"\n ? [repoUrl, \"HEAD\"]\n : [\"--refs\", repoUrl, target];\n const result = await git.listRemote(args);\n const firstLine = result.trim().split(\"\\n\")[0];\n if (!firstLine) return null;\n const sha = firstLine.split(\"\\t\")[0];\n return sha ?? null;\n } catch {\n return null;\n }\n}\n\n/**\n * Check if a skill has updates available by comparing the installed version\n * against the latest remote commit SHA.\n *\n * Only supports GitHub and GitLab sources. Returns `\"unknown\"` for local,\n * package, or other source types.\n *\n * @param skillName - Name of the installed skill to check\n * @returns Object with update status, current version, and latest version\n *\n * @example\n * ```typescript\n * const update = await checkSkillUpdate(\"my-skill\");\n * if (update.hasUpdate) {\n * console.log(`Update available: ${update.currentVersion} -> ${update.latestVersion}`);\n * }\n * ```\n */\nexport async function checkSkillUpdate(skillName: string): Promise<{\n hasUpdate: boolean;\n currentVersion?: string;\n latestVersion?: string;\n status: \"up-to-date\" | \"update-available\" | \"unknown\";\n}> {\n const lock = await readLockFile();\n const entry = lock.skills[skillName];\n if (!entry) {\n return { hasUpdate: false, status: \"unknown\" };\n }\n\n // Only GitHub and GitLab sources support remote checking\n if (entry.sourceType !== \"github\" && entry.sourceType !== \"gitlab\") {\n return {\n hasUpdate: false,\n currentVersion: entry.version,\n status: \"unknown\",\n };\n }\n\n const parsed = parseSource(entry.source);\n if (!parsed.owner || !parsed.repo) {\n return {\n hasUpdate: false,\n currentVersion: entry.version,\n status: \"unknown\",\n };\n }\n\n const host = parsed.type === \"gitlab\" ? \"gitlab.com\" : \"github.com\";\n const repoUrl = `https://${host}/${parsed.owner}/${parsed.repo}.git`;\n const latestSha = await fetchLatestSha(repoUrl, parsed.ref);\n\n if (!latestSha) {\n return {\n hasUpdate: false,\n currentVersion: entry.version,\n status: \"unknown\",\n };\n }\n\n const currentVersion = entry.version;\n const hasUpdate = !currentVersion || !latestSha.startsWith(currentVersion.slice(0, 7));\n\n return {\n hasUpdate,\n currentVersion: currentVersion ?? \"unknown\",\n latestVersion: latestSha.slice(0, 12),\n status: hasUpdate ? \"update-available\" : \"up-to-date\",\n };\n}\n","export const DEFAULT_FETCH_TIMEOUT_MS = 10_000;\n\ntype NetworkErrorKind = \"timeout\" | \"http\" | \"network\";\n\nexport class NetworkError extends Error {\n kind: NetworkErrorKind;\n url: string;\n status?: number;\n\n constructor(message: string, kind: NetworkErrorKind, url: string, status?: number) {\n super(message);\n this.name = \"NetworkError\";\n this.kind = kind;\n this.url = url;\n this.status = status;\n }\n}\n\nfunction isAbortError(error: unknown): boolean {\n return error instanceof Error && error.name === \"AbortError\";\n}\n\nexport async function fetchWithTimeout(\n url: string,\n init?: RequestInit,\n timeoutMs = DEFAULT_FETCH_TIMEOUT_MS,\n): Promise<Response> {\n try {\n return await fetch(url, {\n ...init,\n signal: AbortSignal.timeout(timeoutMs),\n });\n } catch (error) {\n if (isAbortError(error)) {\n throw new NetworkError(`Request timed out after ${timeoutMs}ms`, \"timeout\", url);\n }\n throw new NetworkError(\"Network request failed\", \"network\", url);\n }\n}\n\nexport function ensureOkResponse(response: Response, url: string): Response {\n if (!response.ok) {\n throw new NetworkError(`Request failed with status ${response.status}`, \"http\", url, response.status);\n }\n return response;\n}\n\nexport function formatNetworkError(error: unknown): string {\n if (error instanceof NetworkError) {\n if (error.kind === \"timeout\") {\n return \"Network request timed out. Please check your connection and try again.\";\n }\n if (error.kind === \"http\") {\n return `Marketplace request failed with HTTP ${error.status ?? \"unknown\"}. Please try again shortly.`;\n }\n return \"Network request failed. Please check your connection and try again.\";\n }\n\n if (error instanceof Error) return error.message;\n return String(error);\n}\n","/**\n * agentskills.in marketplace adapter\n *\n * Connects to the SkillsMP API for skill discovery.\n * GitHub is always the actual source for installation.\n */\n\nimport type { MarketplaceAdapter, MarketplaceResult, SearchOptions } from \"./types.js\";\nimport { ensureOkResponse, fetchWithTimeout } from \"../network/fetch.js\";\n\nconst API_BASE = \"https://www.agentskills.in/api/skills\";\n\ninterface ApiSkill {\n id: string;\n name: string;\n description: string;\n author: string;\n scopedName: string;\n stars: number;\n forks: number;\n githubUrl: string;\n repoFullName: string;\n path: string;\n category?: string;\n hasContent: boolean;\n}\n\ninterface ApiResponse {\n skills: ApiSkill[];\n total: number;\n limit: number;\n offset: number;\n}\n\ninterface ScopedNameParts {\n author: string;\n name: string;\n}\n\nfunction parseScopedName(value: string): ScopedNameParts | null {\n const match = value.match(/^@([^/]+)\\/([^/]+)$/);\n if (!match) return null;\n return {\n author: match[1]!,\n name: match[2]!,\n };\n}\n\nfunction toResult(skill: ApiSkill): MarketplaceResult {\n return {\n name: skill.name,\n scopedName: skill.scopedName,\n description: skill.description,\n author: skill.author,\n stars: skill.stars,\n githubUrl: skill.githubUrl,\n repoFullName: skill.repoFullName,\n path: skill.path,\n source: \"agentskills.in\",\n };\n}\n\nexport class SkillsMPAdapter implements MarketplaceAdapter {\n name = \"agentskills.in\";\n\n async search(query: string, limit = 20): Promise<MarketplaceResult[]> {\n const params = new URLSearchParams({\n search: query,\n limit: String(limit),\n sortBy: \"stars\",\n });\n\n const url = `${API_BASE}?${params}`;\n const response = ensureOkResponse(await fetchWithTimeout(url), url);\n const data = (await response.json()) as ApiResponse;\n return data.skills.map(toResult);\n }\n\n async getSkill(scopedName: string): Promise<MarketplaceResult | null> {\n const parts = parseScopedName(scopedName);\n const searchTerms = parts\n ? [parts.name, `${parts.author} ${parts.name}`, scopedName]\n : [scopedName];\n\n const seen = new Set<string>();\n for (const term of searchTerms) {\n if (seen.has(term)) continue;\n seen.add(term);\n\n const params = new URLSearchParams({\n search: term,\n limit: \"50\",\n sortBy: \"stars\",\n });\n\n const url = `${API_BASE}?${params}`;\n const response = ensureOkResponse(await fetchWithTimeout(url), url);\n const data = (await response.json()) as ApiResponse;\n const match = data.skills.find(\n (s) => s.scopedName === scopedName || `@${s.author}/${s.name}` === scopedName,\n );\n if (match) {\n return toResult(match);\n }\n }\n\n return null;\n }\n}\n","/**\n * skills.sh marketplace adapter\n *\n * Connects to the skills.sh API for skill discovery.\n * Uses the Vercel Skills model where GitHub is the actual source.\n */\n\nimport type { MarketplaceAdapter, MarketplaceResult } from \"./types.js\";\nimport { ensureOkResponse, fetchWithTimeout } from \"../network/fetch.js\";\n\nconst API_BASE = \"https://skills.sh/api\";\n\ninterface SkillsShResult {\n name: string;\n author: string;\n description: string;\n repo: string;\n stars?: number;\n url: string;\n}\n\ninterface SkillsShResponse {\n results: SkillsShResult[];\n total: number;\n}\n\nfunction toResult(skill: SkillsShResult): MarketplaceResult {\n return {\n name: skill.name,\n scopedName: `@${skill.author}/${skill.name}`,\n description: skill.description,\n author: skill.author,\n stars: skill.stars ?? 0,\n githubUrl: skill.url,\n repoFullName: skill.repo,\n path: \"\",\n source: \"skills.sh\",\n };\n}\n\nexport class SkillsShAdapter implements MarketplaceAdapter {\n name = \"skills.sh\";\n\n async search(query: string, limit = 20): Promise<MarketplaceResult[]> {\n const params = new URLSearchParams({\n q: query,\n limit: String(limit),\n });\n\n const url = `${API_BASE}/search?${params}`;\n const response = ensureOkResponse(await fetchWithTimeout(url), url);\n const data = (await response.json()) as SkillsShResponse;\n return data.results.map(toResult);\n }\n\n async getSkill(scopedName: string): Promise<MarketplaceResult | null> {\n const results = await this.search(scopedName, 5);\n return results.find((r) => r.scopedName === scopedName) ?? null;\n }\n}\n","/**\n * Unified marketplace client\n *\n * Aggregates results from multiple marketplace adapters,\n * deduplicates, and sorts by relevance.\n */\n\nimport type { MarketplaceAdapter, MarketplaceResult } from \"./types.js\";\nimport { SkillsMPAdapter } from \"./skillsmp.js\";\nimport { SkillsShAdapter } from \"./skillssh.js\";\n\nexport class MarketplaceUnavailableError extends Error {\n details: string[];\n\n constructor(message: string, details: string[]) {\n super(message);\n this.name = \"MarketplaceUnavailableError\";\n this.details = details;\n }\n}\n\n/**\n * Unified marketplace client that aggregates results from multiple marketplace adapters.\n *\n * Queries all configured marketplaces in parallel, deduplicates results by scoped name,\n * and sorts by star count.\n *\n * @example\n * ```typescript\n * const client = new MarketplaceClient();\n * const results = await client.search(\"filesystem\");\n * for (const r of results) {\n * console.log(`${r.scopedName} (${r.stars} stars)`);\n * }\n * ```\n */\nexport class MarketplaceClient {\n private adapters: MarketplaceAdapter[];\n\n /**\n * Create a new marketplace client.\n *\n * @param adapters - Custom marketplace adapters (defaults to agentskills.in and skills.sh)\n *\n * @example\n * ```typescript\n * // Use default adapters\n * const client = new MarketplaceClient();\n *\n * // Use custom adapters\n * const client = new MarketplaceClient([myAdapter]);\n * ```\n */\n constructor(adapters?: MarketplaceAdapter[]) {\n this.adapters = adapters ?? [\n new SkillsMPAdapter(),\n new SkillsShAdapter(),\n ];\n }\n\n /**\n * Search all marketplaces and return deduplicated, sorted results.\n *\n * Queries all adapters in parallel and deduplicates by `scopedName`,\n * keeping the entry with the highest star count. Results are sorted by\n * stars descending.\n *\n * @param query - Search query string\n * @param limit - Maximum number of results to return (default: 20)\n * @returns Deduplicated and sorted marketplace results\n *\n * @example\n * ```typescript\n * const results = await client.search(\"code review\", 10);\n * ```\n */\n async search(query: string, limit = 20): Promise<MarketplaceResult[]> {\n const settled = await Promise.allSettled(this.adapters.map((adapter) => adapter.search(query, limit)));\n\n const flat: MarketplaceResult[] = [];\n const failures: string[] = [];\n\n for (const [index, result] of settled.entries()) {\n const adapterName = this.adapters[index]?.name ?? \"unknown\";\n\n if (result.status === \"fulfilled\") {\n flat.push(...result.value);\n } else {\n const reason = result.reason instanceof Error ? result.reason.message : String(result.reason);\n failures.push(`${adapterName}: ${reason}`);\n }\n }\n\n if (flat.length === 0 && failures.length > 0) {\n throw new MarketplaceUnavailableError(\"All marketplace sources failed.\", failures);\n }\n\n // Deduplicate by scopedName, keeping higher star count\n const seen = new Map<string, MarketplaceResult>();\n for (const result of flat) {\n const existing = seen.get(result.scopedName);\n if (!existing || result.stars > existing.stars) {\n seen.set(result.scopedName, result);\n }\n }\n\n // Sort by stars descending\n const deduplicated = Array.from(seen.values());\n deduplicated.sort((a, b) => b.stars - a.stars);\n\n return deduplicated.slice(0, limit);\n }\n\n /**\n * Get a specific skill by its scoped name from any marketplace.\n *\n * Tries each adapter in order and returns the first match.\n *\n * @param scopedName - Scoped skill name (e.g. `\"@author/my-skill\"`)\n * @returns The marketplace result, or `null` if not found in any marketplace\n *\n * @example\n * ```typescript\n * const skill = await client.getSkill(\"@anthropic/memory\");\n * ```\n */\n async getSkill(scopedName: string): Promise<MarketplaceResult | null> {\n const failures: string[] = [];\n\n for (const adapter of this.adapters) {\n try {\n const result = await adapter.getSkill(scopedName);\n if (result) return result;\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n failures.push(`${adapter.name}: ${reason}`);\n }\n }\n\n if (failures.length === this.adapters.length && this.adapters.length > 0) {\n throw new MarketplaceUnavailableError(\"All marketplace sources failed.\", failures);\n }\n\n return null;\n }\n}\n","/**\n * Local skill discovery\n *\n * Scans directories for SKILL.md files and parses their frontmatter.\n */\n\nimport { readFile, readdir } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { join, dirname, basename } from \"node:path\";\nimport matter from \"gray-matter\";\nimport type { SkillEntry, SkillMetadata } from \"../../types.js\";\n\n/**\n * Parse a SKILL.md file and extract its frontmatter metadata.\n *\n * Reads the file, parses YAML frontmatter via `gray-matter`, and maps the\n * fields to a {@link SkillMetadata} object. Returns `null` if the file cannot\n * be read or lacks required `name` and `description` fields.\n *\n * @param filePath - Absolute path to the SKILL.md file\n * @returns Parsed metadata, or `null` if invalid\n *\n * @example\n * ```typescript\n * const meta = await parseSkillFile(\"/path/to/SKILL.md\");\n * if (meta) {\n * console.log(`${meta.name}: ${meta.description}`);\n * }\n * ```\n */\nexport async function parseSkillFile(filePath: string): Promise<SkillMetadata | null> {\n try {\n const content = await readFile(filePath, \"utf-8\");\n const { data } = matter(content);\n\n if (!data[\"name\"] || !data[\"description\"]) {\n return null;\n }\n\n const allowedTools = data[\"allowed-tools\"] ?? data[\"allowedTools\"];\n\n return {\n name: String(data[\"name\"]),\n description: String(data[\"description\"]),\n license: data[\"license\"] ? String(data[\"license\"]) : undefined,\n compatibility: data[\"compatibility\"] ? String(data[\"compatibility\"]) : undefined,\n metadata: data[\"metadata\"] as Record<string, string> | undefined,\n allowedTools: typeof allowedTools === \"string\"\n ? allowedTools.split(/\\s+/)\n : Array.isArray(allowedTools)\n ? allowedTools.map(String)\n : undefined,\n version: data[\"version\"] ? String(data[\"version\"]) : undefined,\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Discover a single skill at a given directory path.\n *\n * Checks for a `SKILL.md` file in the directory and parses its metadata.\n *\n * @param skillDir - Absolute path to a skill directory (containing SKILL.md)\n * @returns Skill entry with metadata, or `null` if no valid SKILL.md exists\n *\n * @example\n * ```typescript\n * const skill = await discoverSkill(\"/home/user/.agents/skills/my-skill\");\n * if (skill) {\n * console.log(`Found: ${skill.name}`);\n * }\n * ```\n */\nexport async function discoverSkill(skillDir: string): Promise<SkillEntry | null> {\n const skillFile = join(skillDir, \"SKILL.md\");\n if (!existsSync(skillFile)) return null;\n\n const metadata = await parseSkillFile(skillFile);\n if (!metadata) return null;\n\n return {\n name: metadata.name,\n scopedName: metadata.name,\n path: skillDir,\n metadata,\n };\n}\n\n/**\n * Scan a directory for skill subdirectories, each containing a SKILL.md file.\n *\n * Iterates over directories and symlinks in `rootDir` and calls\n * {@link discoverSkill} on each.\n *\n * @param rootDir - Absolute path to a skills root directory to scan\n * @returns Array of discovered skill entries\n *\n * @example\n * ```typescript\n * const skills = await discoverSkills(\"/home/user/.agents/skills\");\n * console.log(`Found ${skills.length} skills`);\n * ```\n */\nexport async function discoverSkills(rootDir: string): Promise<SkillEntry[]> {\n if (!existsSync(rootDir)) return [];\n\n const entries = await readdir(rootDir, { withFileTypes: true });\n const skills: SkillEntry[] = [];\n\n for (const entry of entries) {\n if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;\n\n const skillDir = join(rootDir, entry.name);\n const skill = await discoverSkill(skillDir);\n if (skill) {\n skills.push(skill);\n }\n }\n\n return skills;\n}\n\n/** Discover skills across multiple directories */\nexport async function discoverSkillsMulti(dirs: string[]): Promise<SkillEntry[]> {\n const all: SkillEntry[] = [];\n const seen = new Set<string>();\n\n for (const dir of dirs) {\n const skills = await discoverSkills(dir);\n for (const skill of skills) {\n if (!seen.has(skill.name)) {\n seen.add(skill.name);\n all.push(skill);\n }\n }\n }\n\n return all;\n}\n","import type { MarketplaceResult } from \"../marketplace/types.js\";\n\nexport const RECOMMENDATION_ERROR_CODES = {\n QUERY_INVALID: \"E_SKILLS_QUERY_INVALID\",\n NO_MATCHES: \"E_SKILLS_NO_MATCHES\",\n SOURCE_UNAVAILABLE: \"E_SKILLS_SOURCE_UNAVAILABLE\",\n CRITERIA_CONFLICT: \"E_SKILLS_CRITERIA_CONFLICT\",\n} as const;\n\nexport type RecommendationErrorCode = (typeof RECOMMENDATION_ERROR_CODES)[keyof typeof RECOMMENDATION_ERROR_CODES];\n\nexport interface RecommendationValidationIssue {\n code: RecommendationErrorCode;\n field: \"query\" | \"mustHave\" | \"prefer\" | \"exclude\";\n message: string;\n}\n\nexport interface RecommendationValidationResult {\n valid: boolean;\n issues: RecommendationValidationIssue[];\n}\n\nexport interface RecommendationCriteriaInput {\n query?: string;\n mustHave?: string | string[];\n prefer?: string | string[];\n exclude?: string | string[];\n}\n\nexport interface NormalizedRecommendationCriteria {\n query: string;\n queryTokens: string[];\n mustHave: string[];\n prefer: string[];\n exclude: string[];\n}\n\nexport type RecommendationReasonCode =\n | \"MATCH_TOPIC_GITBOOK\"\n | \"HAS_GIT_SYNC\"\n | \"HAS_API_WORKFLOW\"\n | \"PENALTY_LEGACY_CLI\"\n | \"MUST_HAVE_MATCH\"\n | \"MISSING_MUST_HAVE\"\n | \"PREFER_MATCH\"\n | \"QUERY_MATCH\"\n | \"STAR_SIGNAL\"\n | \"METADATA_SIGNAL\"\n | \"MODERN_MARKER\"\n | \"LEGACY_MARKER\"\n | \"EXCLUDE_MATCH\";\n\nexport interface RecommendationReason {\n code: RecommendationReasonCode;\n detail?: string;\n}\n\nexport interface RecommendationScoreBreakdown {\n mustHave: number;\n prefer: number;\n query: number;\n stars: number;\n metadata: number;\n modernity: number;\n exclusionPenalty: number;\n total: number;\n}\n\nexport interface RankedSkillRecommendation {\n skill: MarketplaceResult;\n score: number;\n reasons: RecommendationReason[];\n tradeoffs: string[];\n excluded: boolean;\n breakdown?: RecommendationScoreBreakdown;\n}\n\nexport interface RecommendationOptions {\n top?: number;\n includeDetails?: boolean;\n weights?: Partial<RecommendationWeights>;\n modernMarkers?: string[];\n legacyMarkers?: string[];\n}\n\nexport interface RecommendationWeights {\n mustHaveMatch: number;\n preferMatch: number;\n queryTokenMatch: number;\n starsFactor: number;\n metadataBoost: number;\n modernMarkerBoost: number;\n legacyMarkerPenalty: number;\n excludePenalty: number;\n missingMustHavePenalty: number;\n}\n\nexport interface RecommendSkillsResult {\n criteria: NormalizedRecommendationCriteria;\n ranking: RankedSkillRecommendation[];\n}\n\nconst DEFAULT_WEIGHTS: RecommendationWeights = {\n mustHaveMatch: 10,\n preferMatch: 4,\n queryTokenMatch: 3,\n starsFactor: 2,\n metadataBoost: 2,\n modernMarkerBoost: 3,\n legacyMarkerPenalty: 3,\n excludePenalty: 25,\n missingMustHavePenalty: 20,\n};\n\nconst DEFAULT_MODERN_MARKERS = [\"svelte 5\", \"runes\", \"lafs\", \"slsa\", \"drizzle\", \"better-auth\"];\nconst DEFAULT_LEGACY_MARKERS = [\"svelte 3\", \"jquery\", \"bower\", \"legacy\", \"book.json\", \"gitbook-cli\"];\n\nexport function tokenizeCriteriaValue(value: string): string[] {\n return value\n .split(\",\")\n .map((part) => part.trim().toLowerCase())\n .filter(Boolean);\n}\n\nfunction normalizeList(value: unknown): string[] {\n if (value === undefined) return [];\n\n if (!(typeof value === \"string\" || Array.isArray(value))) return [];\n\n const source = Array.isArray(value) ? value : [value];\n const flattened = source.flatMap((item) => (typeof item === \"string\" ? tokenizeCriteriaValue(item) : []));\n return Array.from(new Set(flattened)).sort((a, b) => a.localeCompare(b));\n}\n\nfunction hasAnyCriteriaInput(input: RecommendationCriteriaInput): boolean {\n const query = typeof input.query === \"string\" ? input.query.trim() : \"\";\n if (query.length > 0) return true;\n\n const lists = [input.mustHave, input.prefer, input.exclude];\n return lists.some((list) => normalizeList(list).length > 0);\n}\n\nexport function validateRecommendationCriteria(input: RecommendationCriteriaInput): RecommendationValidationResult {\n const issues: RecommendationValidationIssue[] = [];\n\n if (input.query !== undefined && typeof input.query !== \"string\") {\n issues.push({\n code: RECOMMENDATION_ERROR_CODES.QUERY_INVALID,\n field: \"query\",\n message: \"query must be a string\",\n });\n }\n\n if (input.mustHave !== undefined && !(typeof input.mustHave === \"string\" || Array.isArray(input.mustHave))) {\n issues.push({\n code: RECOMMENDATION_ERROR_CODES.QUERY_INVALID,\n field: \"mustHave\",\n message: \"mustHave must be a string or string[]\",\n });\n }\n\n if (input.prefer !== undefined && !(typeof input.prefer === \"string\" || Array.isArray(input.prefer))) {\n issues.push({\n code: RECOMMENDATION_ERROR_CODES.QUERY_INVALID,\n field: \"prefer\",\n message: \"prefer must be a string or string[]\",\n });\n }\n\n if (input.exclude !== undefined && !(typeof input.exclude === \"string\" || Array.isArray(input.exclude))) {\n issues.push({\n code: RECOMMENDATION_ERROR_CODES.QUERY_INVALID,\n field: \"exclude\",\n message: \"exclude must be a string or string[]\",\n });\n }\n\n const mustHave = normalizeList(input.mustHave);\n const prefer = normalizeList(input.prefer);\n const exclude = normalizeList(input.exclude);\n const conflict = mustHave.some((term) => exclude.includes(term)) || prefer.some((term) => exclude.includes(term));\n if (conflict) {\n issues.push({\n code: RECOMMENDATION_ERROR_CODES.CRITERIA_CONFLICT,\n field: \"exclude\",\n message: \"criteria terms cannot appear in both prefer/must-have and exclude\",\n });\n }\n\n if (issues.length === 0 && !hasAnyCriteriaInput(input)) {\n issues.push({\n code: RECOMMENDATION_ERROR_CODES.QUERY_INVALID,\n field: \"query\",\n message: \"at least one criteria value is required\",\n });\n }\n\n return {\n valid: issues.length === 0,\n issues,\n };\n}\n\nexport function normalizeRecommendationCriteria(input: RecommendationCriteriaInput): NormalizedRecommendationCriteria {\n const query = (input.query ?? \"\").trim().toLowerCase();\n return {\n query,\n queryTokens: query ? Array.from(new Set(tokenizeCriteriaValue(query.replace(/\\s+/g, \",\")))).sort((a, b) => a.localeCompare(b)) : [],\n mustHave: normalizeList(input.mustHave),\n prefer: normalizeList(input.prefer),\n exclude: normalizeList(input.exclude),\n };\n}\n\nfunction countMatches(haystack: string, needles: string[]): number {\n let count = 0;\n for (const needle of needles) {\n if (haystack.includes(needle)) {\n count += 1;\n }\n }\n return count;\n}\n\nfunction clampScore(value: number): number {\n return Number(value.toFixed(6));\n}\n\nfunction buildSearchText(skill: MarketplaceResult): string {\n return `${skill.name} ${skill.scopedName} ${skill.description} ${skill.author}`.toLowerCase();\n}\n\nexport function scoreSkillRecommendation(\n skill: MarketplaceResult,\n criteria: NormalizedRecommendationCriteria,\n options: RecommendationOptions = {},\n): RankedSkillRecommendation {\n const weights = { ...DEFAULT_WEIGHTS, ...options.weights };\n const modernMarkers = (options.modernMarkers ?? DEFAULT_MODERN_MARKERS).map((marker) => marker.toLowerCase());\n const legacyMarkers = (options.legacyMarkers ?? DEFAULT_LEGACY_MARKERS).map((marker) => marker.toLowerCase());\n const text = buildSearchText(skill);\n const reasons: RecommendationReason[] = [];\n const tradeoffs: string[] = [];\n\n const mustHaveMatches = countMatches(text, criteria.mustHave);\n const missingMustHave = Math.max(criteria.mustHave.length - mustHaveMatches, 0);\n const preferMatches = countMatches(text, criteria.prefer);\n const queryMatches = countMatches(text, criteria.queryTokens);\n const excludeMatches = countMatches(text, criteria.exclude);\n const modernMatches = countMatches(text, modernMarkers);\n const legacyMatches = countMatches(text, legacyMarkers);\n const metadataSignal = skill.description.trim().length >= 80 ? 1 : 0;\n const starsSignal = Math.log10(skill.stars + 1);\n const sourceConfidence = skill.source === \"agentskills.in\"\n ? 1\n : skill.source === \"skills.sh\"\n ? 0.8\n : 0.6;\n\n const mustHaveScore = (mustHaveMatches * weights.mustHaveMatch) - (missingMustHave * weights.missingMustHavePenalty);\n const preferScore = preferMatches * weights.preferMatch;\n const queryScore = queryMatches * weights.queryTokenMatch;\n const starsScore = starsSignal * weights.starsFactor;\n const metadataScore = (metadataSignal + sourceConfidence) * weights.metadataBoost;\n const modernityScore =\n (modernMatches * weights.modernMarkerBoost) - (legacyMatches * weights.legacyMarkerPenalty);\n const exclusionPenalty = excludeMatches * weights.excludePenalty;\n\n const hasGitbookTopic = text.includes(\"gitbook\");\n const hasGitSync = text.includes(\"git sync\") || (text.includes(\"git\") && text.includes(\"sync\"));\n const hasApiWorkflow = text.includes(\"api\") && (text.includes(\"workflow\") || text.includes(\"sync\"));\n const hasLegacyCli = text.includes(\"gitbook-cli\") || text.includes(\"book.json\");\n\n const topicScore = (hasGitbookTopic ? 3 : 0) + (hasGitSync ? 2 : 0) + (hasApiWorkflow ? 2 : 0) - (hasLegacyCli ? 4 : 0);\n\n const total = clampScore(\n mustHaveScore + preferScore + queryScore + starsScore + metadataScore + modernityScore + topicScore - exclusionPenalty,\n );\n\n if (hasGitbookTopic) reasons.push({ code: \"MATCH_TOPIC_GITBOOK\" });\n if (hasGitSync) reasons.push({ code: \"HAS_GIT_SYNC\" });\n if (hasApiWorkflow) reasons.push({ code: \"HAS_API_WORKFLOW\" });\n if (hasLegacyCli) reasons.push({ code: \"PENALTY_LEGACY_CLI\" });\n\n if (mustHaveMatches > 0) reasons.push({ code: \"MUST_HAVE_MATCH\", detail: String(mustHaveMatches) });\n if (missingMustHave > 0) reasons.push({ code: \"MISSING_MUST_HAVE\", detail: String(missingMustHave) });\n if (preferMatches > 0) reasons.push({ code: \"PREFER_MATCH\", detail: String(preferMatches) });\n if (queryMatches > 0) reasons.push({ code: \"QUERY_MATCH\", detail: String(queryMatches) });\n if (starsSignal > 0) reasons.push({ code: \"STAR_SIGNAL\" });\n if (metadataSignal > 0) reasons.push({ code: \"METADATA_SIGNAL\" });\n if (modernMatches > 0) reasons.push({ code: \"MODERN_MARKER\", detail: String(modernMatches) });\n if (legacyMatches > 0) reasons.push({ code: \"LEGACY_MARKER\", detail: String(legacyMatches) });\n if (excludeMatches > 0) reasons.push({ code: \"EXCLUDE_MATCH\", detail: String(excludeMatches) });\n\n if (missingMustHave > 0) tradeoffs.push(\"Missing one or more required criteria terms.\");\n if (excludeMatches > 0) tradeoffs.push(\"Matches one or more excluded terms.\");\n if (skill.stars < 10) tradeoffs.push(\"Low quality signal from repository stars.\");\n if (hasLegacyCli) tradeoffs.push(\"Contains legacy GitBook CLI markers.\");\n\n const result: RankedSkillRecommendation = {\n skill,\n score: total,\n reasons,\n tradeoffs,\n excluded: excludeMatches > 0,\n };\n\n if (options.includeDetails) {\n result.breakdown = {\n mustHave: clampScore(mustHaveScore),\n prefer: clampScore(preferScore),\n query: clampScore(queryScore),\n stars: clampScore(starsScore),\n metadata: clampScore(metadataScore),\n modernity: clampScore(modernityScore),\n exclusionPenalty: clampScore(exclusionPenalty),\n total,\n };\n }\n\n return result;\n}\n\nexport function recommendSkills(\n skills: MarketplaceResult[],\n criteriaInput: RecommendationCriteriaInput,\n options: RecommendationOptions = {},\n): RecommendSkillsResult {\n const validation = validateRecommendationCriteria(criteriaInput);\n if (!validation.valid) {\n const first = validation.issues[0];\n const error = new Error(first?.message ?? \"Invalid recommendation criteria\") as Error & {\n code?: RecommendationErrorCode;\n issues?: RecommendationValidationIssue[];\n };\n error.code = first?.code;\n error.issues = validation.issues;\n throw error;\n }\n\n const criteria = normalizeRecommendationCriteria(criteriaInput);\n const ranking = skills\n .map((skill) => scoreSkillRecommendation(skill, criteria, options))\n .sort((a, b) => {\n if (b.score !== a.score) return b.score - a.score;\n if (b.skill.stars !== a.skill.stars) return b.skill.stars - a.skill.stars;\n return a.skill.scopedName.localeCompare(b.skill.scopedName);\n });\n\n return {\n criteria,\n ranking: typeof options.top === \"number\" ? ranking.slice(0, Math.max(0, options.top)) : ranking,\n };\n}\n\nexport const rankSkills = recommendSkills;\n","import { MarketplaceClient } from \"../marketplace/client.js\";\nimport {\n RECOMMENDATION_ERROR_CODES,\n recommendSkills as rankSkills,\n type RecommendationCriteriaInput,\n type RecommendationOptions,\n type RecommendSkillsResult,\n} from \"./recommendation.js\";\n\nexport interface SearchSkillsOptions {\n limit?: number;\n}\n\nexport interface RecommendSkillsQueryOptions extends RecommendationOptions {\n limit?: number;\n}\n\nexport function formatSkillRecommendations(\n result: RecommendSkillsResult,\n opts: { mode: \"human\" | \"json\"; details?: boolean },\n): string | Record<string, unknown> {\n const top = result.ranking;\n\n if (opts.mode === \"human\") {\n if (top.length === 0) return \"No recommendations found.\";\n const lines: string[] = [\"Recommended skills:\", \"\"];\n for (const [index, entry] of top.entries()) {\n const marker = index === 0 ? \" (Recommended)\" : \"\";\n lines.push(`${index + 1}) ${entry.skill.scopedName}${marker}`);\n lines.push(` why: ${entry.reasons.map((reason) => reason.code).join(\", \") || \"score-based match\"}`);\n lines.push(` tradeoff: ${entry.tradeoffs[0] ?? \"none\"}`);\n }\n lines.push(\"\");\n lines.push(`CHOOSE: ${top.map((_, index) => index + 1).join(\",\")}`);\n return lines.join(\"\\n\");\n }\n\n const options = top.map((entry, index) => ({\n rank: index + 1,\n scopedName: entry.skill.scopedName,\n score: entry.score,\n reasons: entry.reasons,\n tradeoffs: entry.tradeoffs,\n ...(opts.details\n ? {\n description: entry.skill.description,\n source: entry.skill.source,\n evidence: entry.breakdown ?? null,\n }\n : {}),\n }));\n\n return {\n query: result.criteria.query,\n recommended: options[0] ?? null,\n options,\n };\n}\n\nexport async function searchSkills(query: string, options: SearchSkillsOptions = {}) {\n const trimmed = query.trim();\n if (!trimmed) {\n const error = new Error(\"query must be non-empty\") as Error & { code?: string };\n error.code = RECOMMENDATION_ERROR_CODES.QUERY_INVALID;\n throw error;\n }\n\n const client = new MarketplaceClient();\n try {\n return await client.search(trimmed, options.limit ?? 20);\n } catch (error) {\n const wrapped = new Error(error instanceof Error ? error.message : String(error)) as Error & { code?: string };\n wrapped.code = RECOMMENDATION_ERROR_CODES.SOURCE_UNAVAILABLE;\n throw wrapped;\n }\n}\n\nexport async function recommendSkills(\n query: string,\n criteria: Omit<RecommendationCriteriaInput, \"query\">,\n options: RecommendSkillsQueryOptions = {},\n): Promise<RecommendSkillsResult> {\n const hits = await searchSkills(query, { limit: options.limit ?? Math.max((options.top ?? 3) * 5, 20) });\n const ranked = rankSkills(hits, { ...criteria, query }, options);\n\n if (ranked.ranking.length === 0) {\n const error = new Error(\"no matches found\") as Error & { code?: string };\n error.code = RECOMMENDATION_ERROR_CODES.NO_MATCHES;\n throw error;\n }\n\n return ranked;\n}\n","/**\n * Security scanning engine for SKILL.md files\n *\n * Scans skill content against 46+ security rules\n * and produces findings with line-level precision.\n */\n\nimport { readFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport type { AuditResult, AuditFinding, AuditRule, AuditSeverity } from \"../../../types.js\";\nimport { AUDIT_RULES } from \"./rules.js\";\n\nconst SEVERITY_WEIGHTS: Record<AuditSeverity, number> = {\n critical: 25,\n high: 15,\n medium: 8,\n low: 3,\n info: 0,\n};\n\n/**\n * Scan a single file against security audit rules.\n *\n * Checks each line of the file against all active rules and produces findings\n * with line-level precision. Calculates a security score (100 = clean, 0 = dangerous)\n * based on severity-weighted penalties.\n *\n * @param filePath - Absolute path to the file to scan\n * @param rules - Custom rules to scan against (defaults to the built-in 46+ rules)\n * @returns Audit result with findings, score, and pass/fail status\n *\n * @example\n * ```typescript\n * const result = await scanFile(\"/path/to/SKILL.md\");\n * console.log(`Score: ${result.score}/100, Passed: ${result.passed}`);\n * ```\n */\nexport async function scanFile(\n filePath: string,\n rules?: AuditRule[],\n): Promise<AuditResult> {\n if (!existsSync(filePath)) {\n return { file: filePath, findings: [], score: 100, passed: true };\n }\n\n const content = await readFile(filePath, \"utf-8\");\n const lines = content.split(\"\\n\");\n const activeRules = rules ?? AUDIT_RULES;\n const findings: AuditFinding[] = [];\n\n for (const rule of activeRules) {\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]!;\n const match = line.match(rule.pattern);\n if (match) {\n findings.push({\n rule,\n line: i + 1,\n column: (match.index ?? 0) + 1,\n match: match[0],\n context: line.trim(),\n });\n }\n }\n }\n\n // Calculate score (100 = clean, 0 = very dangerous)\n const totalPenalty = findings.reduce(\n (sum, f) => sum + (SEVERITY_WEIGHTS[f.rule.severity] ?? 0),\n 0,\n );\n const score = Math.max(0, 100 - totalPenalty);\n const passed = !findings.some((f) => f.rule.severity === \"critical\" || f.rule.severity === \"high\");\n\n return { file: filePath, findings, score, passed };\n}\n\n/**\n * Scan a directory of skills for security issues.\n *\n * Iterates over skill subdirectories and scans each `SKILL.md` file found.\n *\n * @param dirPath - Absolute path to the skills directory to scan\n * @returns Array of audit results, one per scanned SKILL.md\n *\n * @example\n * ```typescript\n * const results = await scanDirectory(\"/home/user/.agents/skills\");\n * const failing = results.filter(r => !r.passed);\n * ```\n */\nexport async function scanDirectory(dirPath: string): Promise<AuditResult[]> {\n const { readdir } = await import(\"node:fs/promises\");\n const { join } = await import(\"node:path\");\n\n if (!existsSync(dirPath)) return [];\n\n const entries = await readdir(dirPath, { withFileTypes: true });\n const results: AuditResult[] = [];\n\n for (const entry of entries) {\n if (entry.isDirectory() || entry.isSymbolicLink()) {\n const skillFile = join(dirPath, entry.name, \"SKILL.md\");\n if (existsSync(skillFile)) {\n results.push(await scanFile(skillFile));\n }\n }\n }\n\n return results;\n}\n\n/**\n * Convert audit results to SARIF 2.1.0 format (Static Analysis Results Interchange Format).\n *\n * Produces a standards-compliant SARIF document suitable for CI/CD integration\n * and code scanning tools (e.g. GitHub Code Scanning).\n *\n * @param results - Array of audit results to convert\n * @returns SARIF 2.1.0 JSON object\n *\n * @example\n * ```typescript\n * const results = await scanDirectory(\"/path/to/skills\");\n * const sarif = toSarif(results);\n * writeFileSync(\"audit.sarif\", JSON.stringify(sarif, null, 2));\n * ```\n */\nexport function toSarif(results: AuditResult[]): object {\n return {\n $schema: \"https://raw.githubusercontent.com/oasis-tcs/sarif-spec/main/sarif-2.1/schema/sarif-schema-2.1.0.json\",\n version: \"2.1.0\",\n runs: [\n {\n tool: {\n driver: {\n name: \"caamp-audit\",\n version: \"0.1.0\",\n rules: AUDIT_RULES.map((r) => ({\n id: r.id,\n name: r.name,\n shortDescription: { text: r.description },\n defaultConfiguration: {\n level: r.severity === \"critical\" || r.severity === \"high\" ? \"error\" : \"warning\",\n },\n properties: { category: r.category },\n })),\n },\n },\n results: results.flatMap((result) =>\n result.findings.map((f) => ({\n ruleId: f.rule.id,\n level: f.rule.severity === \"critical\" || f.rule.severity === \"high\" ? \"error\" : \"warning\",\n message: { text: `${f.rule.description}: ${f.match}` },\n locations: [\n {\n physicalLocation: {\n artifactLocation: { uri: result.file },\n region: {\n startLine: f.line,\n startColumn: f.column,\n },\n },\n },\n ],\n })),\n ),\n },\n ],\n };\n}\n","/**\n * Security audit rules for SKILL.md scanning\n *\n * 46+ rules across categories: prompt injection, command injection,\n * data exfiltration, privilege escalation, obfuscation, and more.\n */\n\nimport type { AuditRule, AuditSeverity } from \"../../../types.js\";\n\nfunction rule(\n id: string,\n name: string,\n description: string,\n severity: AuditSeverity,\n category: string,\n pattern: RegExp,\n): AuditRule {\n return { id, name, description, severity, category, pattern };\n}\n\nexport const AUDIT_RULES: AuditRule[] = [\n // ── Prompt Injection ────────────────────────────────────────\n rule(\"PI001\", \"System prompt override\", \"Attempts to override system instructions\", \"critical\", \"prompt-injection\",\n /(?:ignore|forget|disregard)\\s+(?:all\\s+)?(?:previous|prior|above|system)\\s+(?:instructions|prompts|rules)/i),\n rule(\"PI002\", \"Role manipulation\", \"Attempts to assume a different role\", \"critical\", \"prompt-injection\",\n /(?:you\\s+are\\s+now|act\\s+as|pretend\\s+(?:to\\s+be|you're)|your\\s+new\\s+role\\s+is)/i),\n rule(\"PI003\", \"Jailbreak attempt\", \"Common jailbreak patterns\", \"critical\", \"prompt-injection\",\n /(?:DAN|Do\\s+Anything\\s+Now|developer\\s+mode|god\\s+mode|unrestricted\\s+mode)/i),\n rule(\"PI004\", \"Instruction override\", \"Direct instruction override attempt\", \"high\", \"prompt-injection\",\n /(?:new\\s+instructions?:|updated?\\s+instructions?:|override\\s+instructions?:)/i),\n rule(\"PI005\", \"Hidden instructions\", \"Instructions hidden in comments or whitespace\", \"high\", \"prompt-injection\",\n /<!--[\\s\\S]*?(?:execute|run|ignore|override)[\\s\\S]*?-->/i),\n rule(\"PI006\", \"Encoding bypass\", \"Base64 or encoded content\", \"medium\", \"prompt-injection\",\n /(?:base64|atob|btoa|decodeURI|unescape)\\s*\\(/i),\n rule(\"PI007\", \"Context manipulation\", \"Fake conversation context\", \"high\", \"prompt-injection\",\n /(?:Human:|Assistant:|User:|System:)\\s*(?:ignore|execute|run)/i),\n rule(\"PI008\", \"Token smuggling\", \"Invisible characters or zero-width spaces\", \"medium\", \"prompt-injection\",\n /[\\u200B\\u200C\\u200D\\u2060\\uFEFF]/),\n\n // ── Command Injection ───────────────────────────────────────\n rule(\"CI001\", \"Destructive command\", \"File deletion or system modification\", \"critical\", \"command-injection\",\n /(?:rm\\s+-rf|rmdir\\s+\\/s|del\\s+\\/f|format\\s+[a-z]:|mkfs|dd\\s+if=)/i),\n rule(\"CI002\", \"Remote code execution\", \"Downloading and executing remote code\", \"critical\", \"command-injection\",\n /(?:curl|wget|fetch)\\s+.*\\|\\s*(?:sh|bash|zsh|python|node|eval)/i),\n rule(\"CI003\", \"Eval usage\", \"Dynamic code execution\", \"high\", \"command-injection\",\n /\\beval\\s*\\(/),\n rule(\"CI004\", \"Shell spawn\", \"Spawning shell processes\", \"high\", \"command-injection\",\n /(?:exec|spawn|system|popen)\\s*\\(\\s*['\"`]/),\n rule(\"CI005\", \"Sudo escalation\", \"Privilege escalation via sudo\", \"critical\", \"command-injection\",\n /sudo\\s+(?:rm|chmod|chown|mv|cp|dd|mkfs|format)/i),\n rule(\"CI006\", \"Environment manipulation\", \"Modifying PATH or critical env vars\", \"high\", \"command-injection\",\n /(?:export\\s+PATH|setx?\\s+PATH|PATH=.*:)/i),\n rule(\"CI007\", \"Cron/scheduled task\", \"Installing scheduled tasks\", \"high\", \"command-injection\",\n /(?:crontab|at\\s+\\d|schtasks|launchctl\\s+load)/i),\n rule(\"CI008\", \"Network listener\", \"Starting network services\", \"high\", \"command-injection\",\n /(?:nc\\s+-l|ncat\\s+-l|socat\\s+|python.*SimpleHTTPServer|php\\s+-S)/i),\n\n // ── Data Exfiltration ───────────────────────────────────────\n rule(\"DE001\", \"Credential access\", \"Reading credential files\", \"critical\", \"data-exfiltration\",\n /(?:\\.env|\\.aws\\/credentials|\\.ssh\\/|\\.gnupg|\\.netrc|credentials\\.json|token\\.json)/i),\n rule(\"DE002\", \"API key extraction\", \"Patterns matching API key theft\", \"critical\", \"data-exfiltration\",\n /(?:API[_-]?KEY|SECRET[_-]?KEY|ACCESS[_-]?TOKEN|PRIVATE[_-]?KEY)\\s*[=:]/i),\n rule(\"DE003\", \"Data upload\", \"Uploading data to external services\", \"high\", \"data-exfiltration\",\n /(?:curl|wget|fetch).*(?:POST|PUT|PATCH).*(?:pastebin|gist|transfer\\.sh|requestbin|webhook)/i),\n rule(\"DE004\", \"Browser data theft\", \"Accessing browser profiles or cookies\", \"critical\", \"data-exfiltration\",\n /(?:\\.mozilla|\\.chrome|\\.config\\/google-chrome|Cookies|Login\\s+Data|Local\\s+State)/i),\n rule(\"DE005\", \"Git credential theft\", \"Accessing git credentials\", \"high\", \"data-exfiltration\",\n /(?:git\\s+credential|\\.git-credentials|\\.gitconfig\\s+credential)/i),\n rule(\"DE006\", \"Keychain access\", \"Accessing system keychain\", \"critical\", \"data-exfiltration\",\n /(?:security\\s+find-generic-password|security\\s+find-internet-password|keyring\\s+get)/i),\n\n // ── Privilege Escalation ────────────────────────────────────\n rule(\"PE001\", \"Chmod dangerous\", \"Setting dangerous file permissions\", \"high\", \"privilege-escalation\",\n /chmod\\s+(?:777|666|a\\+[rwx]|o\\+[rwx])/i),\n rule(\"PE002\", \"SUID/SGID\", \"Setting SUID or SGID bits\", \"critical\", \"privilege-escalation\",\n /chmod\\s+[ug]\\+s/i),\n rule(\"PE003\", \"Docker escape\", \"Container escape patterns\", \"critical\", \"privilege-escalation\",\n /(?:--privileged|--cap-add\\s+SYS_ADMIN|--pid=host|nsenter)/i),\n rule(\"PE004\", \"Kernel module\", \"Loading kernel modules\", \"critical\", \"privilege-escalation\",\n /(?:insmod|modprobe|rmmod)\\s+/i),\n\n // ── Filesystem Abuse ────────────────────────────────────────\n rule(\"FS001\", \"System directory write\", \"Writing to system directories\", \"critical\", \"filesystem\",\n /(?:\\/etc\\/|\\/usr\\/|\\/bin\\/|\\/sbin\\/|C:\\\\Windows\\\\|C:\\\\Program Files)/i),\n rule(\"FS002\", \"Hidden file creation\", \"Creating hidden files\", \"medium\", \"filesystem\",\n /(?:touch|mkdir|cp|mv)\\s+\\.[a-zA-Z]/),\n rule(\"FS003\", \"Symlink attack\", \"Creating symlinks to sensitive files\", \"high\", \"filesystem\",\n /ln\\s+-s.*(?:\\/etc\\/passwd|\\/etc\\/shadow|\\.ssh|\\.env)/i),\n rule(\"FS004\", \"Mass file operation\", \"Recursive operations on broad paths\", \"medium\", \"filesystem\",\n /(?:find|xargs|rm|chmod|chown)\\s+.*(?:\\/\\s|\\/\\*|-R\\s+\\/)/i),\n\n // ── Network Abuse ──────────────────────────────────────────\n rule(\"NA001\", \"DNS exfiltration\", \"Data exfiltration via DNS\", \"high\", \"network\",\n /(?:dig|nslookup|host)\\s+.*\\$\\{?[A-Z_]+/i),\n rule(\"NA002\", \"Reverse shell\", \"Reverse shell patterns\", \"critical\", \"network\",\n /(?:bash\\s+-i|\\/dev\\/tcp\\/|mkfifo|nc\\s+.*-e)/i),\n rule(\"NA003\", \"Port scanning\", \"Network scanning\", \"medium\", \"network\",\n /(?:nmap|masscan|zmap)\\s+/i),\n rule(\"NA004\", \"Proxy/tunnel\", \"Creating network tunnels\", \"high\", \"network\",\n /(?:ssh\\s+-[DRLW]|ngrok|chisel|bore)/i),\n\n // ── Obfuscation ─────────────────────────────────────────────\n rule(\"OB001\", \"Hex encoding\", \"Hex-encoded commands\", \"medium\", \"obfuscation\",\n /\\\\x[0-9a-fA-F]{2}(?:\\\\x[0-9a-fA-F]{2}){3,}/),\n rule(\"OB002\", \"String concatenation\", \"Building commands via concatenation\", \"medium\", \"obfuscation\",\n /(?:\\$\\{[A-Z]+\\}\\$\\{[A-Z]+\\}|['\"][a-z]+['\"]\\.['\"][a-z]+['\"])/i),\n rule(\"OB003\", \"Unicode escape\", \"Unicode-escaped commands\", \"medium\", \"obfuscation\",\n /\\\\u[0-9a-fA-F]{4}(?:\\\\u[0-9a-fA-F]{4}){3,}/),\n\n // ── Supply Chain ────────────────────────────────────────────\n rule(\"SC001\", \"Package install\", \"Installing packages at runtime\", \"medium\", \"supply-chain\",\n /(?:npm\\s+install|pip\\s+install|gem\\s+install|cargo\\s+install)\\s+(?!-)/),\n rule(\"SC002\", \"Typosquatting patterns\", \"Packages with suspicious names\", \"low\", \"supply-chain\",\n /(?:npm\\s+install|pip\\s+install)\\s+(?:reqeusts|requets|reqests|lodahs|lodashe)/i),\n rule(\"SC003\", \"Postinstall script\", \"npm lifecycle scripts\", \"medium\", \"supply-chain\",\n /(?:preinstall|postinstall|preuninstall|postuninstall)\\s*[\":]/i),\n rule(\"SC004\", \"Registry override\", \"Changing package registry\", \"high\", \"supply-chain\",\n /(?:registry\\s*=|--registry\\s+)(?!https:\\/\\/registry\\.npmjs\\.org)/i),\n\n // ── Information Disclosure ──────────────────────────────────\n rule(\"ID001\", \"Process listing\", \"Listing running processes\", \"low\", \"info-disclosure\",\n /(?:ps\\s+aux|top\\s+-b|tasklist)/i),\n rule(\"ID002\", \"System information\", \"Gathering system information\", \"low\", \"info-disclosure\",\n /(?:uname\\s+-a|systeminfo|hostnamectl)/i),\n rule(\"ID003\", \"Network enumeration\", \"Listing network configuration\", \"low\", \"info-disclosure\",\n /(?:ifconfig|ip\\s+addr|ipconfig|netstat\\s+-[at])/i),\n];\n\n/** Get rules by category */\nexport function getRulesByCategory(category: string): AuditRule[] {\n return AUDIT_RULES.filter((r) => r.category === category);\n}\n\n/** Get rules by severity */\nexport function getRulesBySeverity(severity: AuditSeverity): AuditRule[] {\n return AUDIT_RULES.filter((r) => r.severity === severity);\n}\n\n/** Get all unique categories */\nexport function getCategories(): string[] {\n return [...new Set(AUDIT_RULES.map((r) => r.category))];\n}\n","/**\n * SKILL.md validator\n *\n * Validates skill files against the Agent Skills standard.\n */\n\nimport { readFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport matter from \"gray-matter\";\n\n/**\n * A single validation issue found during SKILL.md validation.\n *\n * @example\n * ```typescript\n * const issue: ValidationIssue = {\n * level: \"error\",\n * field: \"name\",\n * message: \"Missing required field: name\",\n * };\n * ```\n */\nexport interface ValidationIssue {\n /** Severity: `\"error\"` causes validation failure, `\"warning\"` does not. */\n level: \"error\" | \"warning\";\n /** The field or section that triggered the issue. */\n field: string;\n /** Human-readable description of the issue. */\n message: string;\n}\n\n/**\n * Result of validating a SKILL.md file against the Agent Skills standard.\n *\n * @example\n * ```typescript\n * const result = await validateSkill(\"/path/to/SKILL.md\");\n * if (!result.valid) {\n * for (const issue of result.issues) {\n * console.log(`[${issue.level}] ${issue.field}: ${issue.message}`);\n * }\n * }\n * ```\n */\nexport interface ValidationResult {\n /** Whether the skill passed validation (no error-level issues). */\n valid: boolean;\n /** All issues found during validation. */\n issues: ValidationIssue[];\n /** Parsed frontmatter metadata, or `null` if parsing failed. */\n metadata: Record<string, unknown> | null;\n}\n\nconst RESERVED_NAMES = [\n \"anthropic\", \"claude\", \"google\", \"openai\", \"microsoft\",\n \"cursor\", \"windsurf\", \"codex\", \"gemini\", \"copilot\",\n];\n\nconst NAME_PATTERN = /^[a-z0-9][a-z0-9-]*[a-z0-9]$|^[a-z0-9]$/;\nconst MAX_NAME_LENGTH = 64;\nconst MAX_DESCRIPTION_LENGTH = 1024;\nconst WARN_BODY_LINES = 500;\nconst WARN_DESCRIPTION_LENGTH = 50;\n\n/**\n * Validate a SKILL.md file against the Agent Skills standard.\n *\n * Checks for required frontmatter fields (`name`, `description`), validates\n * naming conventions, enforces length limits, checks for reserved names,\n * and warns about long skill bodies.\n *\n * @param filePath - Absolute path to the SKILL.md file to validate\n * @returns Validation result with issues and parsed metadata\n *\n * @example\n * ```typescript\n * const result = await validateSkill(\"/path/to/SKILL.md\");\n * console.log(result.valid ? \"Valid\" : `${result.issues.length} issues found`);\n * ```\n */\nexport async function validateSkill(filePath: string): Promise<ValidationResult> {\n const issues: ValidationIssue[] = [];\n\n if (!existsSync(filePath)) {\n return {\n valid: false,\n issues: [{ level: \"error\", field: \"file\", message: \"File does not exist\" }],\n metadata: null,\n };\n }\n\n const content = await readFile(filePath, \"utf-8\");\n\n // Check for frontmatter\n if (!content.startsWith(\"---\")) {\n issues.push({\n level: \"error\",\n field: \"frontmatter\",\n message: \"Missing YAML frontmatter (file must start with ---)\",\n });\n return { valid: false, issues, metadata: null };\n }\n\n let data: Record<string, unknown>;\n let body: string;\n\n try {\n const parsed = matter(content);\n data = parsed.data as Record<string, unknown>;\n body = parsed.content;\n } catch (err) {\n issues.push({\n level: \"error\",\n field: \"frontmatter\",\n message: `Invalid YAML frontmatter: ${err instanceof Error ? err.message : String(err)}`,\n });\n return { valid: false, issues, metadata: null };\n }\n\n // Required: name\n if (!data[\"name\"]) {\n issues.push({ level: \"error\", field: \"name\", message: \"Missing required field: name\" });\n } else {\n const name = String(data[\"name\"]);\n\n if (name.length > MAX_NAME_LENGTH) {\n issues.push({\n level: \"error\",\n field: \"name\",\n message: `Name too long (${name.length} chars, max ${MAX_NAME_LENGTH})`,\n });\n }\n\n if (!NAME_PATTERN.test(name)) {\n issues.push({\n level: \"error\",\n field: \"name\",\n message: \"Name must be lowercase letters, numbers, and hyphens only\",\n });\n }\n\n if (RESERVED_NAMES.includes(name.toLowerCase())) {\n issues.push({\n level: \"error\",\n field: \"name\",\n message: `Name \"${name}\" is reserved`,\n });\n }\n\n if (/<[^>]+>/.test(name)) {\n issues.push({\n level: \"error\",\n field: \"name\",\n message: \"Name must not contain XML/HTML tags\",\n });\n }\n }\n\n // Required: description\n if (!data[\"description\"]) {\n issues.push({ level: \"error\", field: \"description\", message: \"Missing required field: description\" });\n } else {\n const desc = String(data[\"description\"]);\n\n if (desc.length > MAX_DESCRIPTION_LENGTH) {\n issues.push({\n level: \"error\",\n field: \"description\",\n message: `Description too long (${desc.length} chars, max ${MAX_DESCRIPTION_LENGTH})`,\n });\n }\n\n if (desc.length < WARN_DESCRIPTION_LENGTH) {\n issues.push({\n level: \"warning\",\n field: \"description\",\n message: `Description is short (${desc.length} chars). Consider adding more detail.`,\n });\n }\n\n if (/<[^>]+>/.test(desc)) {\n issues.push({\n level: \"error\",\n field: \"description\",\n message: \"Description must not contain XML/HTML tags\",\n });\n }\n }\n\n // Body checks\n const bodyLines = body.trim().split(\"\\n\").length;\n if (bodyLines > WARN_BODY_LINES) {\n issues.push({\n level: \"warning\",\n field: \"body\",\n message: `Body is long (${bodyLines} lines). Consider splitting into multiple skills.`,\n });\n }\n\n if (!body.trim()) {\n issues.push({\n level: \"warning\",\n field: \"body\",\n message: \"Empty skill body. Add instructions for the AI agent.\",\n });\n }\n\n const hasErrors = issues.some((i) => i.level === \"error\");\n\n return {\n valid: !hasErrors,\n issues,\n metadata: data,\n };\n}\n","/**\n * Format utility functions\n */\n\n/**\n * Deep merge two objects, with `source` values winning on conflict.\n *\n * Recursively merges nested plain objects. Arrays and non-object values from\n * `source` overwrite `target` values.\n *\n * @param target - Base object to merge into\n * @param source - Object with values that take precedence\n * @returns A new merged object (does not mutate inputs)\n *\n * @example\n * ```typescript\n * deepMerge({ a: 1, b: { c: 2 } }, { b: { d: 3 } });\n * // { a: 1, b: { c: 2, d: 3 } }\n * ```\n */\nexport function deepMerge(\n target: Record<string, unknown>,\n source: Record<string, unknown>,\n): Record<string, unknown> {\n const result: Record<string, unknown> = { ...target };\n\n for (const key of Object.keys(source)) {\n const sourceVal = source[key];\n const targetVal = target[key];\n\n if (\n sourceVal !== null &&\n typeof sourceVal === \"object\" &&\n !Array.isArray(sourceVal) &&\n targetVal !== null &&\n typeof targetVal === \"object\" &&\n !Array.isArray(targetVal)\n ) {\n result[key] = deepMerge(\n targetVal as Record<string, unknown>,\n sourceVal as Record<string, unknown>,\n );\n } else {\n result[key] = sourceVal;\n }\n }\n\n return result;\n}\n\n/** Set a nested value using dot-notation key path */\nexport function setNestedValue(\n obj: Record<string, unknown>,\n keyPath: string,\n key: string,\n value: unknown,\n): Record<string, unknown> {\n const parts = keyPath.split(\".\");\n const result = { ...obj };\n let current: Record<string, unknown> = result;\n\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i]!;\n if (i === parts.length - 1) {\n // Last part: set the server entry\n const existing = (current[part] as Record<string, unknown>) ?? {};\n current[part] = { ...existing, [key]: value };\n } else {\n // Intermediate: ensure object exists\n if (typeof current[part] !== \"object\" || current[part] === null) {\n current[part] = {};\n }\n current[part] = { ...(current[part] as Record<string, unknown>) };\n current = current[part] as Record<string, unknown>;\n }\n }\n\n return result;\n}\n\n/**\n * Get a nested value from an object using a dot-notation key path.\n *\n * @param obj - Object to traverse\n * @param keyPath - Dot-separated key path (e.g. `\"mcpServers\"` or `\"a.b.c\"`)\n * @returns The value at the key path, or `undefined` if not found\n *\n * @example\n * ```typescript\n * getNestedValue({ a: { b: { c: 42 } } }, \"a.b.c\"); // 42\n * getNestedValue({ a: 1 }, \"a.b\"); // undefined\n * ```\n */\nexport function getNestedValue(\n obj: Record<string, unknown>,\n keyPath: string,\n): unknown {\n const parts = keyPath.split(\".\");\n let current: unknown = obj;\n\n for (const part of parts) {\n if (current === null || typeof current !== \"object\") return undefined;\n current = (current as Record<string, unknown>)[part];\n }\n\n return current;\n}\n\n/**\n * Ensure that the parent directories of a file path exist.\n *\n * Creates directories recursively if they do not exist.\n *\n * @param filePath - Absolute path to a file (parent directories will be created)\n *\n * @example\n * ```typescript\n * await ensureDir(\"/path/to/new/dir/file.json\");\n * // /path/to/new/dir/ now exists\n * ```\n */\nexport async function ensureDir(filePath: string): Promise<void> {\n const { mkdir } = await import(\"node:fs/promises\");\n const { dirname } = await import(\"node:path\");\n await mkdir(dirname(filePath), { recursive: true });\n}\n","/**\n * JSON/JSONC config reader/writer with comment preservation\n *\n * Uses jsonc-parser for surgical edits that preserve comments,\n * formatting, and trailing commas in JSONC files.\n */\n\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport * as jsonc from \"jsonc-parser\";\nimport { deepMerge, setNestedValue, ensureDir } from \"./utils.js\";\n\n/** Read a JSON/JSONC config file */\nexport async function readJsonConfig(filePath: string): Promise<Record<string, unknown>> {\n if (!existsSync(filePath)) return {};\n\n const content = await readFile(filePath, \"utf-8\");\n if (!content.trim()) return {};\n\n const errors: jsonc.ParseError[] = [];\n const result = jsonc.parse(content, errors);\n\n if (errors.length > 0) {\n // Fall back to standard JSON parse for better error messages\n return JSON.parse(content) as Record<string, unknown>;\n }\n\n return (result ?? {}) as Record<string, unknown>;\n}\n\n/** Detect indentation from existing file content */\nfunction detectIndent(content: string): { indent: string; insertSpaces: boolean; tabSize: number } {\n const lines = content.split(\"\\n\");\n for (const line of lines) {\n const match = line.match(/^(\\s+)/);\n if (match?.[1]) {\n const ws = match[1];\n if (ws.startsWith(\"\\t\")) {\n return { indent: \"\\t\", insertSpaces: false, tabSize: 1 };\n }\n return { indent: ws, insertSpaces: true, tabSize: ws.length };\n }\n }\n return { indent: \" \", insertSpaces: true, tabSize: 2 };\n}\n\n/** Write a server config to a JSON/JSONC file, preserving comments */\nexport async function writeJsonConfig(\n filePath: string,\n configKey: string,\n serverName: string,\n serverConfig: unknown,\n): Promise<void> {\n await ensureDir(filePath);\n\n let content: string;\n\n if (existsSync(filePath)) {\n content = await readFile(filePath, \"utf-8\");\n if (!content.trim()) {\n content = \"{}\";\n }\n } else {\n content = \"{}\";\n }\n\n const { tabSize, insertSpaces } = detectIndent(content);\n\n const formatOptions: jsonc.FormattingOptions = {\n tabSize,\n insertSpaces,\n eol: \"\\n\",\n };\n\n // Build the JSON path for the server entry\n const keyParts = configKey.split(\".\");\n const jsonPath = [...keyParts, serverName];\n\n // Use jsonc.modify for surgical, comment-preserving edits\n const edits = jsonc.modify(content, jsonPath, serverConfig, { formattingOptions: formatOptions });\n\n if (edits.length > 0) {\n content = jsonc.applyEdits(content, edits);\n }\n\n // Ensure trailing newline\n if (!content.endsWith(\"\\n\")) {\n content += \"\\n\";\n }\n\n await writeFile(filePath, content, \"utf-8\");\n}\n\n/** Remove a server entry from a JSON/JSONC config */\nexport async function removeJsonConfig(\n filePath: string,\n configKey: string,\n serverName: string,\n): Promise<boolean> {\n if (!existsSync(filePath)) return false;\n\n let content = await readFile(filePath, \"utf-8\");\n if (!content.trim()) return false;\n\n const { tabSize, insertSpaces } = detectIndent(content);\n\n const formatOptions: jsonc.FormattingOptions = {\n tabSize,\n insertSpaces,\n eol: \"\\n\",\n };\n\n const keyParts = configKey.split(\".\");\n const jsonPath = [...keyParts, serverName];\n\n const edits = jsonc.modify(content, jsonPath, undefined, { formattingOptions: formatOptions });\n\n if (edits.length === 0) return false;\n\n content = jsonc.applyEdits(content, edits);\n\n if (!content.endsWith(\"\\n\")) {\n content += \"\\n\";\n }\n\n await writeFile(filePath, content, \"utf-8\");\n return true;\n}\n","/**\n * YAML config reader/writer\n */\n\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport yaml from \"js-yaml\";\nimport { deepMerge, ensureDir } from \"./utils.js\";\n\n/** Read a YAML config file */\nexport async function readYamlConfig(filePath: string): Promise<Record<string, unknown>> {\n if (!existsSync(filePath)) return {};\n\n const content = await readFile(filePath, \"utf-8\");\n if (!content.trim()) return {};\n\n const result = yaml.load(content);\n return (result ?? {}) as Record<string, unknown>;\n}\n\n/** Write a server config to a YAML file */\nexport async function writeYamlConfig(\n filePath: string,\n configKey: string,\n serverName: string,\n serverConfig: unknown,\n): Promise<void> {\n await ensureDir(filePath);\n\n const existing = await readYamlConfig(filePath);\n\n // Build nested structure\n const keyParts = configKey.split(\".\");\n let newEntry: Record<string, unknown> = { [serverName]: serverConfig };\n\n for (let i = keyParts.length - 1; i >= 0; i--) {\n newEntry = { [keyParts[i]!]: newEntry };\n }\n\n const merged = deepMerge(existing, newEntry);\n\n const content = yaml.dump(merged, {\n indent: 2,\n lineWidth: -1,\n noRefs: true,\n sortKeys: false,\n });\n\n await writeFile(filePath, content, \"utf-8\");\n}\n\n/** Remove a server entry from a YAML config */\nexport async function removeYamlConfig(\n filePath: string,\n configKey: string,\n serverName: string,\n): Promise<boolean> {\n if (!existsSync(filePath)) return false;\n\n const existing = await readYamlConfig(filePath);\n\n // Navigate to the config key\n const keyParts = configKey.split(\".\");\n let current: Record<string, unknown> = existing;\n\n for (const part of keyParts) {\n const next = current[part];\n if (typeof next !== \"object\" || next === null) return false;\n current = next as Record<string, unknown>;\n }\n\n if (!(serverName in current)) return false;\n\n delete current[serverName];\n\n const content = yaml.dump(existing, {\n indent: 2,\n lineWidth: -1,\n noRefs: true,\n sortKeys: false,\n });\n\n await writeFile(filePath, content, \"utf-8\");\n return true;\n}\n","/**\n * TOML config reader/writer\n */\n\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport TOML from \"@iarna/toml\";\nimport { deepMerge, ensureDir } from \"./utils.js\";\n\n/** Read a TOML config file */\nexport async function readTomlConfig(filePath: string): Promise<Record<string, unknown>> {\n if (!existsSync(filePath)) return {};\n\n const content = await readFile(filePath, \"utf-8\");\n if (!content.trim()) return {};\n\n const result = TOML.parse(content);\n return result as unknown as Record<string, unknown>;\n}\n\n/** Write a server config to a TOML file */\nexport async function writeTomlConfig(\n filePath: string,\n configKey: string,\n serverName: string,\n serverConfig: unknown,\n): Promise<void> {\n await ensureDir(filePath);\n\n const existing = await readTomlConfig(filePath);\n\n // Build nested structure\n const keyParts = configKey.split(\".\");\n let newEntry: Record<string, unknown> = { [serverName]: serverConfig };\n\n for (let i = keyParts.length - 1; i >= 0; i--) {\n newEntry = { [keyParts[i]!]: newEntry };\n }\n\n const merged = deepMerge(existing, newEntry);\n\n const content = TOML.stringify(merged as TOML.JsonMap);\n\n await writeFile(filePath, content, \"utf-8\");\n}\n\n/** Remove a server entry from a TOML config */\nexport async function removeTomlConfig(\n filePath: string,\n configKey: string,\n serverName: string,\n): Promise<boolean> {\n if (!existsSync(filePath)) return false;\n\n const existing = await readTomlConfig(filePath);\n\n const keyParts = configKey.split(\".\");\n let current: Record<string, unknown> = existing;\n\n for (const part of keyParts) {\n const next = current[part];\n if (typeof next !== \"object\" || next === null) return false;\n current = next as Record<string, unknown>;\n }\n\n if (!(serverName in current)) return false;\n\n delete current[serverName];\n\n const content = TOML.stringify(existing as TOML.JsonMap);\n\n await writeFile(filePath, content, \"utf-8\");\n return true;\n}\n","/**\n * Format router - dispatches config reads/writes to format-specific handlers\n */\n\nimport type { ConfigFormat } from \"../../types.js\";\nimport { readJsonConfig, writeJsonConfig, removeJsonConfig } from \"./json.js\";\nimport { readYamlConfig, writeYamlConfig, removeYamlConfig } from \"./yaml.js\";\nimport { readTomlConfig, writeTomlConfig, removeTomlConfig } from \"./toml.js\";\nimport { debug } from \"../logger.js\";\n\nexport { deepMerge, getNestedValue, ensureDir } from \"./utils.js\";\n\n/**\n * Read and parse a config file in the specified format.\n *\n * Dispatches to the appropriate format handler (JSON/JSONC, YAML, or TOML).\n *\n * @param filePath - Absolute path to the config file\n * @param format - Config file format\n * @returns Parsed config object\n * @throws If the file cannot be read or the format is unsupported\n *\n * @example\n * ```typescript\n * const config = await readConfig(\"/path/to/config.json\", \"jsonc\");\n * ```\n */\nexport async function readConfig(filePath: string, format: ConfigFormat): Promise<Record<string, unknown>> {\n debug(`reading config: ${filePath} (format: ${format})`);\n switch (format) {\n case \"json\":\n case \"jsonc\":\n return readJsonConfig(filePath);\n case \"yaml\":\n return readYamlConfig(filePath);\n case \"toml\":\n return readTomlConfig(filePath);\n default:\n throw new Error(`Unsupported config format: ${format as string}`);\n }\n}\n\n/**\n * Write a server entry to a config file, preserving existing content.\n *\n * Dispatches to the appropriate format handler. For JSONC files, comments are\n * preserved using `jsonc-parser`.\n *\n * @param filePath - Absolute path to the config file\n * @param format - Config file format\n * @param key - Dot-notation key path to the servers section (e.g. `\"mcpServers\"`)\n * @param serverName - Name/key for the server entry\n * @param serverConfig - Server configuration object to write\n * @throws If the format is unsupported\n *\n * @example\n * ```typescript\n * await writeConfig(\"/path/to/config.json\", \"jsonc\", \"mcpServers\", \"my-server\", config);\n * ```\n */\nexport async function writeConfig(\n filePath: string,\n format: ConfigFormat,\n key: string,\n serverName: string,\n serverConfig: unknown,\n): Promise<void> {\n debug(`writing config: ${filePath} (format: ${format}, key: ${key}, server: ${serverName})`);\n switch (format) {\n case \"json\":\n case \"jsonc\":\n return writeJsonConfig(filePath, key, serverName, serverConfig);\n case \"yaml\":\n return writeYamlConfig(filePath, key, serverName, serverConfig);\n case \"toml\":\n return writeTomlConfig(filePath, key, serverName, serverConfig);\n default:\n throw new Error(`Unsupported config format: ${format as string}`);\n }\n}\n\n/**\n * Remove a server entry from a config file in the specified format.\n *\n * @param filePath - Absolute path to the config file\n * @param format - Config file format\n * @param key - Dot-notation key path to the servers section\n * @param serverName - Name/key of the server entry to remove\n * @returns `true` if the entry was removed, `false` otherwise\n * @throws If the format is unsupported\n *\n * @example\n * ```typescript\n * const removed = await removeConfig(\"/path/to/config.json\", \"jsonc\", \"mcpServers\", \"my-server\");\n * ```\n */\nexport async function removeConfig(\n filePath: string,\n format: ConfigFormat,\n key: string,\n serverName: string,\n): Promise<boolean> {\n switch (format) {\n case \"json\":\n case \"jsonc\":\n return removeJsonConfig(filePath, key, serverName);\n case \"yaml\":\n return removeYamlConfig(filePath, key, serverName);\n case \"toml\":\n return removeTomlConfig(filePath, key, serverName);\n default:\n throw new Error(`Unsupported config format: ${format as string}`);\n }\n}\n","/**\n * Per-agent MCP config transformations\n *\n * Most agents use the canonical McpServerConfig directly.\n * These transforms handle agents with non-standard schemas.\n */\n\nimport type { McpServerConfig } from \"../../types.js\";\n\n/** Transform config for Goose (YAML extensions format) */\nexport function transformGoose(serverName: string, config: McpServerConfig): unknown {\n if (config.url) {\n // Remote server\n const transport = config.type === \"sse\" ? \"sse\" : \"streamable_http\";\n return {\n name: serverName,\n type: transport,\n uri: config.url,\n ...(config.headers ? { headers: config.headers } : {}),\n enabled: true,\n timeout: 300,\n };\n }\n\n // Stdio server\n return {\n name: serverName,\n type: \"stdio\",\n cmd: config.command,\n args: config.args ?? [],\n ...(config.env ? { envs: config.env } : {}),\n enabled: true,\n timeout: 300,\n };\n}\n\n/** Transform config for Zed (context_servers format) */\nexport function transformZed(serverName: string, config: McpServerConfig): unknown {\n if (config.url) {\n return {\n source: \"custom\",\n type: config.type ?? \"http\",\n url: config.url,\n ...(config.headers ? { headers: config.headers } : {}),\n };\n }\n\n return {\n source: \"custom\",\n command: config.command,\n args: config.args ?? [],\n ...(config.env ? { env: config.env } : {}),\n };\n}\n\n/** Transform config for OpenCode (mcp format) */\nexport function transformOpenCode(serverName: string, config: McpServerConfig): unknown {\n if (config.url) {\n return {\n type: \"remote\",\n url: config.url,\n enabled: true,\n ...(config.headers ? { headers: config.headers } : {}),\n };\n }\n\n return {\n type: \"local\",\n command: config.command,\n args: config.args ?? [],\n enabled: true,\n ...(config.env ? { environment: config.env } : {}),\n };\n}\n\n/** Transform config for Codex (TOML mcp_servers format) */\nexport function transformCodex(serverName: string, config: McpServerConfig): unknown {\n if (config.url) {\n return {\n type: config.type ?? \"http\",\n url: config.url,\n ...(config.headers ? { headers: config.headers } : {}),\n };\n }\n\n return {\n command: config.command,\n args: config.args ?? [],\n ...(config.env ? { env: config.env } : {}),\n };\n}\n\n/** Transform config for Cursor (mcpServers format - strips type field for remote) */\nexport function transformCursor(serverName: string, config: McpServerConfig): unknown {\n if (config.url) {\n return {\n url: config.url,\n ...(config.headers ? { headers: config.headers } : {}),\n };\n }\n\n // Stdio passthrough\n return config;\n}\n\n/**\n * Get the config transform function for a provider, or `undefined` for passthrough.\n *\n * Providers with non-standard MCP config schemas (Goose, Zed, OpenCode, Codex, Cursor)\n * require transforms to convert the canonical {@link McpServerConfig} into their\n * provider-specific format.\n *\n * @param providerId - Provider ID to look up (e.g. `\"goose\"`, `\"zed\"`)\n * @returns Transform function, or `undefined` if the provider uses the canonical format\n *\n * @example\n * ```typescript\n * const transform = getTransform(\"goose\");\n * if (transform) {\n * const gooseConfig = transform(\"my-server\", canonicalConfig);\n * }\n * ```\n */\nexport function getTransform(\n providerId: string,\n): ((name: string, config: McpServerConfig) => unknown) | undefined {\n switch (providerId) {\n case \"goose\":\n return transformGoose;\n case \"zed\":\n return transformZed;\n case \"opencode\":\n return transformOpenCode;\n case \"codex\":\n return transformCodex;\n case \"cursor\":\n return transformCursor;\n default:\n return undefined;\n }\n}\n","/**\n * MCP config reader\n *\n * Reads, lists, and removes MCP server entries from agent config files.\n * Provides the programmatic API that CLI commands delegate to.\n */\n\nimport { join } from \"node:path\";\nimport { existsSync } from \"node:fs\";\nimport type { Provider, McpServerEntry } from \"../../types.js\";\nimport { readConfig, removeConfig } from \"../formats/index.js\";\nimport { getNestedValue } from \"../formats/utils.js\";\nimport { debug } from \"../logger.js\";\n\n/**\n * Resolve the absolute config file path for a provider and scope.\n *\n * For project scope, joins the project directory with the provider's relative\n * config path. For global scope, returns the provider's global config path.\n *\n * @param provider - Provider to resolve config path for\n * @param scope - Whether to resolve project or global config path\n * @param projectDir - Project directory (defaults to `process.cwd()`)\n * @returns Absolute config file path, or `null` if the provider does not support the given scope\n *\n * @example\n * ```typescript\n * const path = resolveConfigPath(provider, \"project\", \"/home/user/my-project\");\n * // \"/home/user/my-project/.claude/settings.json\"\n * ```\n */\nexport function resolveConfigPath(\n provider: Provider,\n scope: \"project\" | \"global\",\n projectDir?: string,\n): string | null {\n if (scope === \"project\") {\n if (!provider.configPathProject) return null;\n return join(projectDir ?? process.cwd(), provider.configPathProject);\n }\n return provider.configPathGlobal;\n}\n\n/**\n * List MCP servers configured for a single provider.\n *\n * Reads the provider's config file, extracts the MCP servers section using the\n * provider's `configKey`, and returns each server entry with metadata.\n *\n * @param provider - Provider whose config file to read\n * @param scope - Whether to read project or global config\n * @param projectDir - Project directory (defaults to `process.cwd()`)\n * @returns Array of MCP server entries found in the config file\n *\n * @example\n * ```typescript\n * const servers = await listMcpServers(provider, \"project\");\n * for (const s of servers) {\n * console.log(`${s.name} (${s.scope})`);\n * }\n * ```\n */\nexport async function listMcpServers(\n provider: Provider,\n scope: \"project\" | \"global\",\n projectDir?: string,\n): Promise<McpServerEntry[]> {\n const configPath = resolveConfigPath(provider, scope, projectDir);\n debug(`listing MCP servers for ${provider.id} (${scope}) at ${configPath ?? \"(none)\"}`);\n if (!configPath || !existsSync(configPath)) return [];\n\n try {\n const config = await readConfig(configPath, provider.configFormat);\n const servers = getNestedValue(config, provider.configKey);\n\n if (!servers || typeof servers !== \"object\") return [];\n\n const entries: McpServerEntry[] = [];\n for (const [name, cfg] of Object.entries(servers as Record<string, unknown>)) {\n entries.push({\n name,\n providerId: provider.id,\n providerName: provider.toolName,\n scope,\n configPath,\n config: (cfg ?? {}) as Record<string, unknown>,\n });\n }\n\n return entries;\n } catch {\n return [];\n }\n}\n\n/**\n * List MCP servers across all given providers, deduplicating by config path.\n *\n * Multiple providers may share the same config file. This function ensures each\n * config file is read only once to avoid duplicate entries.\n *\n * @param providers - Array of providers to query\n * @param scope - Whether to read project or global config\n * @param projectDir - Project directory (defaults to `process.cwd()`)\n * @returns Combined array of MCP server entries from all providers\n *\n * @example\n * ```typescript\n * const allServers = await listAllMcpServers(getInstalledProviders(), \"global\");\n * ```\n */\nexport async function listAllMcpServers(\n providers: Provider[],\n scope: \"project\" | \"global\",\n projectDir?: string,\n): Promise<McpServerEntry[]> {\n const seen = new Set<string>();\n const allEntries: McpServerEntry[] = [];\n\n for (const provider of providers) {\n const configPath = resolveConfigPath(provider, scope, projectDir);\n if (!configPath || seen.has(configPath)) continue;\n seen.add(configPath);\n\n const entries = await listMcpServers(provider, scope, projectDir);\n allEntries.push(...entries);\n }\n\n return allEntries;\n}\n\n/**\n * Remove an MCP server entry from a provider's config file.\n *\n * @param provider - Provider whose config file to modify\n * @param serverName - Name/key of the MCP server to remove\n * @param scope - Whether to modify project or global config\n * @param projectDir - Project directory (defaults to `process.cwd()`)\n * @returns `true` if the entry was removed, `false` if no config path exists\n *\n * @example\n * ```typescript\n * const removed = await removeMcpServer(provider, \"my-server\", \"project\");\n * ```\n */\nexport async function removeMcpServer(\n provider: Provider,\n serverName: string,\n scope: \"project\" | \"global\",\n projectDir?: string,\n): Promise<boolean> {\n const configPath = resolveConfigPath(provider, scope, projectDir);\n if (!configPath) return false;\n\n return removeConfig(configPath, provider.configFormat, provider.configKey, serverName);\n}\n","/**\n * MCP config installer\n *\n * Writes MCP server configurations to agent config files,\n * handling per-agent formats, keys, and transformations.\n */\n\nimport type { Provider, McpServerConfig, GlobalOptions } from \"../../types.js\";\nimport { writeConfig } from \"../formats/index.js\";\nimport { getTransform } from \"./transforms.js\";\nimport { resolveConfigPath } from \"./reader.js\";\nimport { debug } from \"../logger.js\";\n\n/**\n * Result of installing an MCP server configuration to a single provider.\n *\n * @example\n * ```typescript\n * const result = await installMcpServer(provider, \"my-server\", config);\n * if (result.success) {\n * console.log(`Written to ${result.configPath}`);\n * }\n * ```\n */\nexport interface InstallResult {\n /** The provider the config was written to. */\n provider: Provider;\n /** Whether project or global scope was used. */\n scope: \"project\" | \"global\";\n /** Absolute path to the config file that was written. */\n configPath: string;\n /** Whether the write succeeded. */\n success: boolean;\n /** Error message if the write failed. */\n error?: string;\n}\n\n/** Build the config to write, applying transforms if needed */\nfunction buildConfig(provider: Provider, serverName: string, config: McpServerConfig): unknown {\n const transform = getTransform(provider.id);\n if (transform) {\n return transform(serverName, config);\n }\n return config;\n}\n\n/**\n * Install an MCP server configuration for a single provider.\n *\n * Applies provider-specific transforms (e.g. Goose, Zed, Codex) and writes\n * the config to the provider's config file in the specified scope.\n *\n * @param provider - Target provider to write config for\n * @param serverName - Name/key for the MCP server entry\n * @param config - Canonical MCP server configuration\n * @param scope - Whether to write to project or global config (default: `\"project\"`)\n * @param projectDir - Project directory path (defaults to `process.cwd()`)\n * @returns Install result with success status and config path\n *\n * @example\n * ```typescript\n * const provider = getProvider(\"claude-code\")!;\n * const result = await installMcpServer(provider, \"filesystem\", {\n * command: \"npx\",\n * args: [\"-y\", \"@modelcontextprotocol/server-filesystem\"],\n * });\n * ```\n */\nexport async function installMcpServer(\n provider: Provider,\n serverName: string,\n config: McpServerConfig,\n scope: \"project\" | \"global\" = \"project\",\n projectDir?: string,\n): Promise<InstallResult> {\n const configPath = resolveConfigPath(provider, scope, projectDir);\n\n debug(`installing MCP server \"${serverName}\" for ${provider.id} (${scope})`);\n debug(` config path: ${configPath ?? \"(none)\"}`);\n\n if (!configPath) {\n return {\n provider,\n scope,\n configPath: \"\",\n success: false,\n error: `Provider ${provider.id} does not support ${scope} config`,\n };\n }\n\n try {\n const transformedConfig = buildConfig(provider, serverName, config);\n const transform = getTransform(provider.id);\n debug(` transform applied: ${transform ? \"yes\" : \"no\"}`);\n\n await writeConfig(\n configPath,\n provider.configFormat,\n provider.configKey,\n serverName,\n transformedConfig,\n );\n\n return {\n provider,\n scope,\n configPath,\n success: true,\n };\n } catch (err) {\n return {\n provider,\n scope,\n configPath,\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\n/**\n * Install an MCP server configuration to multiple providers.\n *\n * Calls {@link installMcpServer} for each provider sequentially and collects results.\n *\n * @param providers - Array of target providers\n * @param serverName - Name/key for the MCP server entry\n * @param config - Canonical MCP server configuration\n * @param scope - Whether to write to project or global config (default: `\"project\"`)\n * @param projectDir - Project directory path (defaults to `process.cwd()`)\n * @returns Array of install results, one per provider\n *\n * @example\n * ```typescript\n * const providers = getInstalledProviders();\n * const results = await installMcpServerToAll(providers, \"my-server\", config);\n * const successes = results.filter(r => r.success);\n * ```\n */\nexport async function installMcpServerToAll(\n providers: Provider[],\n serverName: string,\n config: McpServerConfig,\n scope: \"project\" | \"global\" = \"project\",\n projectDir?: string,\n): Promise<InstallResult[]> {\n const results: InstallResult[] = [];\n\n for (const provider of providers) {\n const result = await installMcpServer(provider, serverName, config, scope, projectDir);\n results.push(result);\n }\n\n return results;\n}\n\n/**\n * Build a canonical {@link McpServerConfig} from a parsed source.\n *\n * Maps source types to appropriate transport configurations:\n * - `\"remote\"` sources become HTTP/SSE configs with a `url`\n * - `\"package\"` sources become `npx -y <package>` stdio configs\n * - All others are treated as shell commands split into `command` + `args`\n *\n * @param source - Parsed source with `type` and `value`\n * @param transport - Override transport type for remote sources (default: `\"http\"`)\n * @param headers - Optional HTTP headers for remote servers\n * @returns Canonical MCP server configuration\n *\n * @example\n * ```typescript\n * buildServerConfig({ type: \"package\", value: \"@mcp/server-fs\" });\n * // { command: \"npx\", args: [\"-y\", \"@mcp/server-fs\"] }\n *\n * buildServerConfig({ type: \"remote\", value: \"https://mcp.example.com\" });\n * // { type: \"http\", url: \"https://mcp.example.com\" }\n * ```\n */\nexport function buildServerConfig(\n source: { type: string; value: string },\n transport?: string,\n headers?: Record<string, string>,\n): McpServerConfig {\n if (source.type === \"remote\") {\n return {\n type: (transport ?? \"http\") as \"sse\" | \"http\",\n url: source.value,\n ...(headers && Object.keys(headers).length > 0 ? { headers } : {}),\n };\n }\n\n if (source.type === \"package\") {\n return {\n command: \"npx\",\n args: [\"-y\", source.value],\n };\n }\n\n // Command type - split into command and args\n const parts = source.value.split(/\\s+/);\n return {\n command: parts[0]!,\n args: parts.slice(1),\n };\n}\n","/**\n * MCP lock file management\n *\n * Tracks installed MCP servers with source and agent metadata.\n * Stored at ~/.agents/.caamp-lock.json (shared with skills lock).\n */\n\nimport type { LockEntry, SourceType } from \"../../types.js\";\nimport { readLockFile, writeLockFile } from \"../lock-utils.js\";\n\n/**\n * Read and parse the CAAMP lock file from `~/.agents/.caamp-lock.json`.\n *\n * Returns the full {@link CaampLockFile} structure. Creates a default lock file\n * if one does not exist.\n *\n * @returns The parsed lock file contents\n *\n * @example\n * ```typescript\n * const lock = await readLockFile();\n * console.log(Object.keys(lock.mcpServers));\n * ```\n */\nexport { readLockFile } from \"../lock-utils.js\";\n\n/**\n * Record an MCP server installation in the lock file.\n *\n * Creates or updates an entry in `lock.mcpServers`. If the server already exists,\n * the agent list is merged and `updatedAt` is refreshed while `installedAt` is preserved.\n *\n * @param serverName - Name/key of the MCP server\n * @param source - Original source string\n * @param sourceType - Classified source type\n * @param agents - Provider IDs the server was installed to\n * @param isGlobal - Whether this is a global installation\n *\n * @example\n * ```typescript\n * await recordMcpInstall(\"filesystem\", \"@mcp/server-fs\", \"package\", [\"claude-code\"], true);\n * ```\n */\nexport async function recordMcpInstall(\n serverName: string,\n source: string,\n sourceType: SourceType,\n agents: string[],\n isGlobal: boolean,\n): Promise<void> {\n const lock = await readLockFile();\n const now = new Date().toISOString();\n\n const existing = lock.mcpServers[serverName];\n\n lock.mcpServers[serverName] = {\n name: serverName,\n scopedName: serverName,\n source,\n sourceType,\n installedAt: existing?.installedAt ?? now,\n updatedAt: now,\n agents: [...new Set([...(existing?.agents ?? []), ...agents])],\n canonicalPath: \"\",\n isGlobal,\n };\n\n await writeLockFile(lock);\n}\n\n/**\n * Remove an MCP server entry from the lock file.\n *\n * @param serverName - Name/key of the MCP server to remove\n * @returns `true` if the entry was found and removed, `false` if not found\n *\n * @example\n * ```typescript\n * const removed = await removeMcpFromLock(\"filesystem\");\n * ```\n */\nexport async function removeMcpFromLock(serverName: string): Promise<boolean> {\n const lock = await readLockFile();\n if (!(serverName in lock.mcpServers)) return false;\n\n delete lock.mcpServers[serverName];\n await writeLockFile(lock);\n return true;\n}\n\n/**\n * Get all MCP servers tracked in the lock file.\n *\n * @returns Record of server name to lock entry\n *\n * @example\n * ```typescript\n * const servers = await getTrackedMcpServers();\n * for (const [name, entry] of Object.entries(servers)) {\n * console.log(`${name}: installed ${entry.installedAt}`);\n * }\n * ```\n */\nexport async function getTrackedMcpServers(): Promise<Record<string, LockEntry>> {\n const lock = await readLockFile();\n return lock.mcpServers;\n}\n\n/**\n * Save the last selected agent IDs to the lock file for UX persistence.\n *\n * Used to remember the user's agent selection between CLI invocations.\n *\n * @param agents - Array of provider IDs to remember\n *\n * @example\n * ```typescript\n * await saveLastSelectedAgents([\"claude-code\", \"cursor\"]);\n * ```\n */\nexport async function saveLastSelectedAgents(agents: string[]): Promise<void> {\n const lock = await readLockFile();\n lock.lastSelectedAgents = agents;\n await writeLockFile(lock);\n}\n\n/**\n * Retrieve the last selected agent IDs from the lock file.\n *\n * @returns Array of provider IDs, or `undefined` if none were saved\n *\n * @example\n * ```typescript\n * const agents = await getLastSelectedAgents();\n * // [\"claude-code\", \"cursor\"] or undefined\n * ```\n */\nexport async function getLastSelectedAgents(): Promise<string[] | undefined> {\n const lock = await readLockFile();\n return lock.lastSelectedAgents;\n}\n","/**\n * Marker-based instruction file injection\n *\n * Injects content blocks between CAAMP markers in instruction files\n * (CLAUDE.md, AGENTS.md, GEMINI.md).\n */\n\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { mkdir } from \"node:fs/promises\";\nimport type { InjectionStatus, InjectionCheckResult, Provider } from \"../../types.js\";\n\nconst MARKER_START = \"<!-- CAAMP:START -->\";\nconst MARKER_END = \"<!-- CAAMP:END -->\";\nconst MARKER_PATTERN = /<!-- CAAMP:START -->[\\s\\S]*?<!-- CAAMP:END -->/;\n\n/**\n * Check the status of a CAAMP injection block in an instruction file.\n *\n * Returns the injection status:\n * - `\"missing\"` - File does not exist\n * - `\"none\"` - File exists but has no CAAMP markers\n * - `\"current\"` - CAAMP block exists and matches expected content (or no expected content given)\n * - `\"outdated\"` - CAAMP block exists but differs from expected content\n *\n * @param filePath - Absolute path to the instruction file\n * @param expectedContent - Optional expected content to compare against\n * @returns The injection status\n *\n * @example\n * ```typescript\n * const status = await checkInjection(\"/project/CLAUDE.md\", expectedContent);\n * if (status === \"outdated\") {\n * console.log(\"CAAMP injection needs updating\");\n * }\n * ```\n */\nexport async function checkInjection(\n filePath: string,\n expectedContent?: string,\n): Promise<InjectionStatus> {\n if (!existsSync(filePath)) return \"missing\";\n\n const content = await readFile(filePath, \"utf-8\");\n\n if (!MARKER_PATTERN.test(content)) return \"none\";\n\n if (expectedContent) {\n const blockContent = extractBlock(content);\n if (blockContent && blockContent.trim() === expectedContent.trim()) {\n return \"current\";\n }\n return \"outdated\";\n }\n\n return \"current\";\n}\n\n/** Extract the content between CAAMP markers */\nfunction extractBlock(content: string): string | null {\n const match = content.match(MARKER_PATTERN);\n if (!match) return null;\n\n return match[0]\n .replace(MARKER_START, \"\")\n .replace(MARKER_END, \"\")\n .trim();\n}\n\n/** Build the injection block */\nfunction buildBlock(content: string): string {\n return `${MARKER_START}\\n${content}\\n${MARKER_END}`;\n}\n\n/**\n * Inject content into an instruction file between CAAMP markers.\n *\n * Behavior depends on the file state:\n * - File does not exist: creates the file with the injection block\n * - File exists without markers: prepends the injection block\n * - File exists with markers: replaces the existing injection block\n *\n * @param filePath - Absolute path to the instruction file\n * @param content - Content to inject between CAAMP markers\n * @returns Action taken: `\"created\"`, `\"added\"`, or `\"updated\"`\n *\n * @example\n * ```typescript\n * const action = await inject(\"/project/CLAUDE.md\", \"## My Config\\nSome content\");\n * console.log(`File ${action}`);\n * ```\n */\nexport async function inject(\n filePath: string,\n content: string,\n): Promise<\"created\" | \"added\" | \"updated\"> {\n const block = buildBlock(content);\n\n // Ensure parent directory exists\n await mkdir(dirname(filePath), { recursive: true });\n\n if (!existsSync(filePath)) {\n // Create new file with injection block\n await writeFile(filePath, block + \"\\n\", \"utf-8\");\n return \"created\";\n }\n\n const existing = await readFile(filePath, \"utf-8\");\n\n if (MARKER_PATTERN.test(existing)) {\n // Replace existing block\n const updated = existing.replace(MARKER_PATTERN, block);\n await writeFile(filePath, updated, \"utf-8\");\n return \"updated\";\n }\n\n // Prepend block to existing content\n const updated = block + \"\\n\\n\" + existing;\n await writeFile(filePath, updated, \"utf-8\");\n return \"added\";\n}\n\n/**\n * Remove the CAAMP injection block from an instruction file.\n *\n * If removing the block would leave the file empty, the file is deleted entirely.\n *\n * @param filePath - Absolute path to the instruction file\n * @returns `true` if a CAAMP block was found and removed, `false` otherwise\n *\n * @example\n * ```typescript\n * const removed = await removeInjection(\"/project/CLAUDE.md\");\n * ```\n */\nexport async function removeInjection(filePath: string): Promise<boolean> {\n if (!existsSync(filePath)) return false;\n\n const content = await readFile(filePath, \"utf-8\");\n if (!MARKER_PATTERN.test(content)) return false;\n\n const cleaned = content\n .replace(MARKER_PATTERN, \"\")\n .replace(/^\\n{2,}/, \"\\n\")\n .trim();\n\n if (!cleaned) {\n // File would be empty - remove it entirely\n const { rm } = await import(\"node:fs/promises\");\n await rm(filePath);\n } else {\n await writeFile(filePath, cleaned + \"\\n\", \"utf-8\");\n }\n\n return true;\n}\n\n/**\n * Check injection status across all providers' instruction files.\n *\n * Deduplicates by file path since multiple providers may share the same\n * instruction file (e.g. many providers use `AGENTS.md`).\n *\n * @param providers - Array of providers to check\n * @param projectDir - Absolute path to the project directory\n * @param scope - Whether to check project or global instruction files\n * @param expectedContent - Optional expected content to compare against\n * @returns Array of injection check results, one per unique instruction file\n *\n * @example\n * ```typescript\n * const results = await checkAllInjections(providers, \"/project\", \"project\");\n * const outdated = results.filter(r => r.status === \"outdated\");\n * ```\n */\nexport async function checkAllInjections(\n providers: Provider[],\n projectDir: string,\n scope: \"project\" | \"global\",\n expectedContent?: string,\n): Promise<InjectionCheckResult[]> {\n const results: InjectionCheckResult[] = [];\n const checked = new Set<string>();\n\n for (const provider of providers) {\n const filePath = scope === \"global\"\n ? join(provider.pathGlobal, provider.instructFile)\n : join(projectDir, provider.instructFile);\n\n // Skip duplicates (multiple providers share same instruction file)\n if (checked.has(filePath)) continue;\n checked.add(filePath);\n\n const status = await checkInjection(filePath, expectedContent);\n\n results.push({\n file: filePath,\n provider: provider.id,\n status,\n fileExists: existsSync(filePath),\n });\n }\n\n return results;\n}\n\n/**\n * Inject content into all providers' instruction files.\n *\n * Deduplicates by file path to avoid injecting the same file multiple times.\n *\n * @param providers - Array of providers to inject into\n * @param projectDir - Absolute path to the project directory\n * @param scope - Whether to target project or global instruction files\n * @param content - Content to inject between CAAMP markers\n * @returns Map of file path to action taken (`\"created\"`, `\"added\"`, or `\"updated\"`)\n *\n * @example\n * ```typescript\n * const results = await injectAll(providers, \"/project\", \"project\", content);\n * for (const [file, action] of results) {\n * console.log(`${file}: ${action}`);\n * }\n * ```\n */\nexport async function injectAll(\n providers: Provider[],\n projectDir: string,\n scope: \"project\" | \"global\",\n content: string,\n): Promise<Map<string, \"created\" | \"added\" | \"updated\">> {\n const results = new Map<string, \"created\" | \"added\" | \"updated\">();\n const injected = new Set<string>();\n\n for (const provider of providers) {\n const filePath = scope === \"global\"\n ? join(provider.pathGlobal, provider.instructFile)\n : join(projectDir, provider.instructFile);\n\n // Skip duplicates\n if (injected.has(filePath)) continue;\n injected.add(filePath);\n\n const action = await inject(filePath, content);\n results.set(filePath, action);\n }\n\n return results;\n}\n","/**\n * Instruction template management\n *\n * Generates injection content based on provider capabilities.\n */\n\nimport type { Provider } from \"../../types.js\";\n\n/**\n * Generate a standard CAAMP injection block for instruction files.\n *\n * Produces markdown content suitable for injection between CAAMP markers.\n * Optionally includes MCP server and custom content sections.\n *\n * @param options - Optional configuration for the generated content\n * @param options.mcpServerName - MCP server name to include a server section\n * @param options.customContent - Additional custom markdown content to append\n * @returns Generated markdown string\n *\n * @example\n * ```typescript\n * const content = generateInjectionContent({ mcpServerName: \"filesystem\" });\n * ```\n */\nexport function generateInjectionContent(options?: {\n mcpServerName?: string;\n customContent?: string;\n}): string {\n const lines: string[] = [];\n\n lines.push(\"## CAAMP Managed Configuration\");\n lines.push(\"\");\n lines.push(\"This section is managed by [CAAMP](https://github.com/caamp/caamp).\");\n lines.push(\"Do not edit between the CAAMP markers manually.\");\n\n if (options?.mcpServerName) {\n lines.push(\"\");\n lines.push(`### MCP Server: ${options.mcpServerName}`);\n lines.push(`Configured via \\`caamp mcp install\\`.`);\n }\n\n if (options?.customContent) {\n lines.push(\"\");\n lines.push(options.customContent);\n }\n\n return lines.join(\"\\n\");\n}\n\n/** Generate a skills discovery section for instruction files */\nexport function generateSkillsSection(skillNames: string[]): string {\n if (skillNames.length === 0) return \"\";\n\n const lines: string[] = [];\n lines.push(\"### Installed Skills\");\n lines.push(\"\");\n\n for (const name of skillNames) {\n lines.push(`- \\`${name}\\` - Available via SKILL.md`);\n }\n\n return lines.join(\"\\n\");\n}\n\n/** Get the correct instruction file name for a provider */\nexport function getInstructFile(provider: Provider): string {\n return provider.instructFile;\n}\n\n/**\n * Group providers by their instruction file name.\n *\n * Useful for determining which providers share the same instruction file\n * (e.g. multiple providers using `AGENTS.md`).\n *\n * @param providers - Array of providers to group\n * @returns Map from instruction file name to array of providers using that file\n *\n * @example\n * ```typescript\n * const groups = groupByInstructFile(getAllProviders());\n * for (const [file, providers] of groups) {\n * console.log(`${file}: ${providers.map(p => p.id).join(\", \")}`);\n * }\n * ```\n */\nexport function groupByInstructFile(providers: Provider[]): Map<string, Provider[]> {\n const groups = new Map<string, Provider[]>();\n\n for (const provider of providers) {\n const existing = groups.get(provider.instructFile) ?? [];\n existing.push(provider);\n groups.set(provider.instructFile, existing);\n }\n\n return groups;\n}\n","/**\n * Advanced orchestration helpers for multi-provider operations.\n *\n * These helpers compose CAAMP's lower-level APIs into production patterns:\n * tier-based targeting, conflict-aware installs, and rollback-capable batches.\n */\n\nimport { existsSync, lstatSync } from \"node:fs\";\nimport {\n cp,\n mkdir,\n readFile,\n readlink,\n rm,\n symlink,\n writeFile,\n} from \"node:fs/promises\";\nimport { homedir, tmpdir } from \"node:os\";\nimport { basename, dirname, join } from \"node:path\";\nimport type {\n ConfigFormat,\n McpServerConfig,\n Provider,\n ProviderPriority,\n} from \"../../types.js\";\nimport { injectAll } from \"../instructions/injector.js\";\nimport { groupByInstructFile } from \"../instructions/templates.js\";\nimport { installMcpServer, type InstallResult } from \"../mcp/installer.js\";\nimport { listMcpServers, resolveConfigPath } from \"../mcp/reader.js\";\nimport { getTransform } from \"../mcp/transforms.js\";\nimport { getInstalledProviders } from \"../registry/detection.js\";\nimport { installSkill, removeSkill } from \"../skills/installer.js\";\n\ntype Scope = \"project\" | \"global\";\n\nconst PRIORITY_ORDER: Record<ProviderPriority, number> = {\n high: 0,\n medium: 1,\n low: 2,\n};\n\nconst CANONICAL_SKILLS_DIR = join(homedir(), \".agents\", \"skills\");\n\n/**\n * Filter providers by minimum priority and return them in deterministic tier order.\n *\n * `minimumPriority = \"medium\"` returns `high` + `medium`.\n */\nexport function selectProvidersByMinimumPriority(\n providers: Provider[],\n minimumPriority: ProviderPriority = \"low\",\n): Provider[] {\n const maxRank = PRIORITY_ORDER[minimumPriority];\n\n return [...providers]\n .filter((provider) => PRIORITY_ORDER[provider.priority] <= maxRank)\n .sort((a, b) => PRIORITY_ORDER[a.priority] - PRIORITY_ORDER[b.priority]);\n}\n\n/**\n * Single MCP operation entry used by batch orchestration.\n */\nexport interface McpBatchOperation {\n serverName: string;\n config: McpServerConfig;\n scope?: Scope;\n}\n\n/**\n * Single skill operation entry used by batch orchestration.\n */\nexport interface SkillBatchOperation {\n sourcePath: string;\n skillName: string;\n isGlobal?: boolean;\n}\n\n/**\n * Options for rollback-capable batch installation.\n */\nexport interface BatchInstallOptions {\n providers?: Provider[];\n minimumPriority?: ProviderPriority;\n mcp?: McpBatchOperation[];\n skills?: SkillBatchOperation[];\n projectDir?: string;\n}\n\n/**\n * Result of rollback-capable batch installation.\n */\nexport interface BatchInstallResult {\n success: boolean;\n providerIds: string[];\n mcpApplied: number;\n skillsApplied: number;\n rollbackPerformed: boolean;\n rollbackErrors: string[];\n error?: string;\n}\n\ninterface SkillPathSnapshot {\n linkPath: string;\n state: \"missing\" | \"symlink\" | \"directory\" | \"file\";\n symlinkTarget?: string;\n backupPath?: string;\n}\n\ninterface SkillSnapshot {\n skillName: string;\n isGlobal: boolean;\n canonicalPath: string;\n canonicalBackupPath?: string;\n canonicalExisted: boolean;\n pathSnapshots: SkillPathSnapshot[];\n}\n\ninterface AppliedSkillInstall {\n skillName: string;\n isGlobal: boolean;\n linkedProviders: Provider[];\n}\n\nfunction resolveSkillLinkPath(\n provider: Provider,\n skillName: string,\n isGlobal: boolean,\n projectDir: string,\n): string {\n const skillDir = isGlobal\n ? provider.pathSkills\n : join(projectDir, provider.pathProjectSkills);\n return join(skillDir, skillName);\n}\n\nasync function snapshotConfigs(paths: string[]): Promise<Map<string, string | null>> {\n const snapshots = new Map<string, string | null>();\n\n for (const path of paths) {\n if (!path || snapshots.has(path)) continue;\n if (!existsSync(path)) {\n snapshots.set(path, null);\n continue;\n }\n snapshots.set(path, await readFile(path, \"utf-8\"));\n }\n\n return snapshots;\n}\n\nasync function restoreConfigSnapshots(snapshots: Map<string, string | null>): Promise<void> {\n for (const [path, content] of snapshots) {\n if (content === null) {\n await rm(path, { force: true });\n continue;\n }\n\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, content, \"utf-8\");\n }\n}\n\nasync function snapshotSkillState(\n providerTargets: Provider[],\n operation: SkillBatchOperation,\n projectDir: string,\n backupRoot: string,\n): Promise<SkillSnapshot> {\n const skillName = operation.skillName;\n const isGlobal = operation.isGlobal ?? true;\n const canonicalPath = join(CANONICAL_SKILLS_DIR, skillName);\n const canonicalExisted = existsSync(canonicalPath);\n const canonicalBackupPath = join(backupRoot, \"canonical\", skillName);\n\n if (canonicalExisted) {\n await mkdir(dirname(canonicalBackupPath), { recursive: true });\n await cp(canonicalPath, canonicalBackupPath, { recursive: true });\n }\n\n const pathSnapshots: SkillPathSnapshot[] = [];\n for (const provider of providerTargets) {\n const linkPath = resolveSkillLinkPath(provider, skillName, isGlobal, projectDir);\n\n if (!existsSync(linkPath)) {\n pathSnapshots.push({ linkPath, state: \"missing\" });\n continue;\n }\n\n const stat = lstatSync(linkPath);\n\n if (stat.isSymbolicLink()) {\n pathSnapshots.push({\n linkPath,\n state: \"symlink\",\n symlinkTarget: await readlink(linkPath),\n });\n continue;\n }\n\n const backupPath = join(backupRoot, \"links\", provider.id, `${skillName}-${basename(linkPath)}`);\n await mkdir(dirname(backupPath), { recursive: true });\n\n if (stat.isDirectory()) {\n await cp(linkPath, backupPath, { recursive: true });\n pathSnapshots.push({ linkPath, state: \"directory\", backupPath });\n continue;\n }\n\n await cp(linkPath, backupPath);\n pathSnapshots.push({ linkPath, state: \"file\", backupPath });\n }\n\n return {\n skillName,\n isGlobal,\n canonicalPath,\n canonicalBackupPath: canonicalExisted ? canonicalBackupPath : undefined,\n canonicalExisted,\n pathSnapshots,\n };\n}\n\nasync function restoreSkillSnapshot(snapshot: SkillSnapshot): Promise<void> {\n if (existsSync(snapshot.canonicalPath)) {\n await rm(snapshot.canonicalPath, { recursive: true, force: true });\n }\n\n if (snapshot.canonicalExisted && snapshot.canonicalBackupPath && existsSync(snapshot.canonicalBackupPath)) {\n await mkdir(dirname(snapshot.canonicalPath), { recursive: true });\n await cp(snapshot.canonicalBackupPath, snapshot.canonicalPath, { recursive: true });\n }\n\n for (const pathSnapshot of snapshot.pathSnapshots) {\n await rm(pathSnapshot.linkPath, { recursive: true, force: true });\n\n if (pathSnapshot.state === \"missing\") continue;\n\n await mkdir(dirname(pathSnapshot.linkPath), { recursive: true });\n\n if (pathSnapshot.state === \"symlink\" && pathSnapshot.symlinkTarget) {\n const linkType = process.platform === \"win32\" ? \"junction\" : \"dir\";\n await symlink(pathSnapshot.symlinkTarget, pathSnapshot.linkPath, linkType);\n continue;\n }\n\n if ((pathSnapshot.state === \"directory\" || pathSnapshot.state === \"file\") && pathSnapshot.backupPath) {\n if (pathSnapshot.state === \"directory\") {\n await cp(pathSnapshot.backupPath, pathSnapshot.linkPath, { recursive: true });\n } else {\n await cp(pathSnapshot.backupPath, pathSnapshot.linkPath);\n }\n }\n }\n}\n\n/**\n * Install multiple MCP servers and skills across filtered providers with rollback.\n *\n * Rollback behavior:\n * - MCP config files are restored exactly from snapshots.\n * - Skill state is restored for canonical skill dirs and targeted provider link paths.\n */\nexport async function installBatchWithRollback(\n options: BatchInstallOptions,\n): Promise<BatchInstallResult> {\n const projectDir = options.projectDir ?? process.cwd();\n const minimumPriority = options.minimumPriority ?? \"low\";\n const mcpOps = options.mcp ?? [];\n const skillOps = options.skills ?? [];\n const baseProviders = options.providers ?? getInstalledProviders();\n const providers = selectProvidersByMinimumPriority(baseProviders, minimumPriority);\n\n const configPaths = providers.flatMap((provider) => {\n const paths: string[] = [];\n for (const operation of mcpOps) {\n const path = resolveConfigPath(provider, operation.scope ?? \"project\", projectDir);\n if (path) paths.push(path);\n }\n return paths;\n });\n\n const configSnapshots = await snapshotConfigs(configPaths);\n const backupRoot = join(\n tmpdir(),\n `caamp-skill-backup-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n );\n\n const skillSnapshots = await Promise.all(\n skillOps.map((operation) => snapshotSkillState(providers, operation, projectDir, backupRoot)),\n );\n\n const appliedSkills: AppliedSkillInstall[] = [];\n const rollbackErrors: string[] = [];\n let mcpApplied = 0;\n let skillsApplied = 0;\n let rollbackPerformed = false;\n\n try {\n for (const operation of mcpOps) {\n const scope = operation.scope ?? \"project\";\n for (const provider of providers) {\n const result = await installMcpServer(\n provider,\n operation.serverName,\n operation.config,\n scope,\n projectDir,\n );\n\n if (!result.success) {\n throw new Error(result.error ?? `Failed MCP install for ${provider.id}`);\n }\n mcpApplied += 1;\n }\n }\n\n for (const operation of skillOps) {\n const isGlobal = operation.isGlobal ?? true;\n const result = await installSkill(\n operation.sourcePath,\n operation.skillName,\n providers,\n isGlobal,\n projectDir,\n );\n\n const linkedProviders = providers.filter((provider) => result.linkedAgents.includes(provider.id));\n appliedSkills.push({\n skillName: operation.skillName,\n isGlobal,\n linkedProviders,\n });\n\n if (result.errors.length > 0) {\n throw new Error(result.errors.join(\"; \"));\n }\n\n skillsApplied += 1;\n }\n\n await rm(backupRoot, { recursive: true, force: true });\n\n return {\n success: true,\n providerIds: providers.map((provider) => provider.id),\n mcpApplied,\n skillsApplied,\n rollbackPerformed: false,\n rollbackErrors: [],\n };\n } catch (error) {\n rollbackPerformed = true;\n\n for (const applied of [...appliedSkills].reverse()) {\n try {\n await removeSkill(applied.skillName, applied.linkedProviders, applied.isGlobal, projectDir);\n } catch (err) {\n rollbackErrors.push(err instanceof Error ? err.message : String(err));\n }\n }\n\n try {\n await restoreConfigSnapshots(configSnapshots);\n } catch (err) {\n rollbackErrors.push(err instanceof Error ? err.message : String(err));\n }\n\n for (const snapshot of skillSnapshots) {\n try {\n await restoreSkillSnapshot(snapshot);\n } catch (err) {\n rollbackErrors.push(err instanceof Error ? err.message : String(err));\n }\n }\n\n await rm(backupRoot, { recursive: true, force: true });\n\n return {\n success: false,\n providerIds: providers.map((provider) => provider.id),\n mcpApplied,\n skillsApplied,\n rollbackPerformed,\n rollbackErrors,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\n/**\n * Conflict policy when applying MCP install plans.\n */\nexport type ConflictPolicy = \"fail\" | \"skip\" | \"overwrite\";\n\n/**\n * MCP conflict code.\n */\nexport type McpConflictCode =\n | \"unsupported-transport\"\n | \"unsupported-headers\"\n | \"existing-mismatch\";\n\n/**\n * Conflict detected during preflight.\n */\nexport interface McpConflict {\n providerId: string;\n serverName: string;\n scope: Scope;\n code: McpConflictCode;\n message: string;\n}\n\n/**\n * Result from applying install plan with conflict policy.\n */\nexport interface McpPlanApplyResult {\n conflicts: McpConflict[];\n applied: InstallResult[];\n skipped: Array<{\n providerId: string;\n serverName: string;\n scope: Scope;\n reason: McpConflictCode;\n }>;\n}\n\nfunction stableStringify(value: unknown): string {\n if (Array.isArray(value)) {\n return `[${value.map(stableStringify).join(\",\")}]`;\n }\n\n if (value && typeof value === \"object\") {\n const record = value as Record<string, unknown>;\n const keys = Object.keys(record).sort();\n return `{${keys.map((key) => `${JSON.stringify(key)}:${stableStringify(record[key])}`).join(\",\")}}`;\n }\n\n return JSON.stringify(value);\n}\n\n/**\n * Preflight conflict detection for MCP install plans across providers.\n */\nexport async function detectMcpConfigConflicts(\n providers: Provider[],\n operations: McpBatchOperation[],\n projectDir = process.cwd(),\n): Promise<McpConflict[]> {\n const conflicts: McpConflict[] = [];\n\n for (const provider of providers) {\n for (const operation of operations) {\n const scope = operation.scope ?? \"project\";\n\n if (operation.config.type && !provider.supportedTransports.includes(operation.config.type)) {\n conflicts.push({\n providerId: provider.id,\n serverName: operation.serverName,\n scope,\n code: \"unsupported-transport\",\n message: `${provider.id} does not support transport ${operation.config.type}`,\n });\n }\n\n if (operation.config.headers && !provider.supportsHeaders) {\n conflicts.push({\n providerId: provider.id,\n serverName: operation.serverName,\n scope,\n code: \"unsupported-headers\",\n message: `${provider.id} does not support header configuration`,\n });\n }\n\n const existingEntries = await listMcpServers(provider, scope, projectDir);\n const current = existingEntries.find((entry) => entry.name === operation.serverName);\n if (!current) continue;\n\n const transform = getTransform(provider.id);\n const desired = transform\n ? transform(operation.serverName, operation.config)\n : operation.config;\n\n if (stableStringify(current.config) !== stableStringify(desired)) {\n conflicts.push({\n providerId: provider.id,\n serverName: operation.serverName,\n scope,\n code: \"existing-mismatch\",\n message: `${provider.id} has existing config mismatch for ${operation.serverName}`,\n });\n }\n }\n }\n\n return conflicts;\n}\n\n/**\n * Apply MCP install plan with a conflict policy.\n */\nexport async function applyMcpInstallWithPolicy(\n providers: Provider[],\n operations: McpBatchOperation[],\n policy: ConflictPolicy = \"fail\",\n projectDir = process.cwd(),\n): Promise<McpPlanApplyResult> {\n const conflicts = await detectMcpConfigConflicts(providers, operations, projectDir);\n const conflictKey = (providerId: string, serverName: string, scope: Scope) => `${providerId}::${serverName}::${scope}`;\n const conflictMap = new Map<string, McpConflict>();\n for (const conflict of conflicts) {\n conflictMap.set(conflictKey(conflict.providerId, conflict.serverName, conflict.scope), conflict);\n }\n\n if (policy === \"fail\" && conflicts.length > 0) {\n return { conflicts, applied: [], skipped: [] };\n }\n\n const applied: InstallResult[] = [];\n const skipped: McpPlanApplyResult[\"skipped\"] = [];\n\n for (const provider of providers) {\n for (const operation of operations) {\n const scope = operation.scope ?? \"project\";\n const key = conflictKey(provider.id, operation.serverName, scope);\n const conflict = conflictMap.get(key);\n\n if (policy === \"skip\" && conflict) {\n skipped.push({\n providerId: provider.id,\n serverName: operation.serverName,\n scope,\n reason: conflict.code,\n });\n continue;\n }\n\n const result = await installMcpServer(\n provider,\n operation.serverName,\n operation.config,\n scope,\n projectDir,\n );\n applied.push(result);\n }\n }\n\n return { conflicts, applied, skipped };\n}\n\n/**\n * Result of a single-operation instruction update across providers.\n */\nexport interface InstructionUpdateSummary {\n scope: Scope;\n updatedFiles: number;\n actions: Array<{\n file: string;\n action: \"created\" | \"added\" | \"updated\";\n providers: string[];\n configFormats: ConfigFormat[];\n }>;\n}\n\n/**\n * Update instruction files across providers as a single operation.\n *\n * Works the same regardless of provider config format (JSON/YAML/TOML/JSONC)\n * because instruction files are handled through CAAMP markers.\n */\nexport async function updateInstructionsSingleOperation(\n providers: Provider[],\n content: string,\n scope: Scope = \"project\",\n projectDir = process.cwd(),\n): Promise<InstructionUpdateSummary> {\n const actions = await injectAll(providers, projectDir, scope, content);\n const groupedByFile = groupByInstructFile(providers);\n\n const summary: InstructionUpdateSummary = {\n scope,\n updatedFiles: actions.size,\n actions: [],\n };\n\n for (const [filePath, action] of actions.entries()) {\n const providersForFile = providers.filter((provider) => {\n const expectedPath = scope === \"global\"\n ? join(provider.pathGlobal, provider.instructFile)\n : join(projectDir, provider.instructFile);\n return expectedPath === filePath;\n });\n\n const fallback = groupedByFile.get(basename(filePath)) ?? [];\n const selected = providersForFile.length > 0 ? providersForFile : fallback;\n\n summary.actions.push({\n file: filePath,\n action,\n providers: selected.map((provider) => provider.id),\n configFormats: Array.from(new Set(selected.map((provider) => provider.configFormat))),\n });\n }\n\n return summary;\n}\n\n/**\n * Request payload for dual-scope provider configuration.\n */\nexport interface DualScopeConfigureOptions {\n globalMcp?: Array<{ serverName: string; config: McpServerConfig }>;\n projectMcp?: Array<{ serverName: string; config: McpServerConfig }>;\n instructionContent?: string | { global?: string; project?: string };\n projectDir?: string;\n}\n\n/**\n * Result of dual-scope provider configuration.\n */\nexport interface DualScopeConfigureResult {\n providerId: string;\n configPaths: {\n global: string | null;\n project: string | null;\n };\n mcp: {\n global: InstallResult[];\n project: InstallResult[];\n };\n instructions: {\n global?: Map<string, \"created\" | \"added\" | \"updated\">;\n project?: Map<string, \"created\" | \"added\" | \"updated\">;\n };\n}\n\n/**\n * Configure both global and project-level settings for one provider in one call.\n */\nexport async function configureProviderGlobalAndProject(\n provider: Provider,\n options: DualScopeConfigureOptions,\n): Promise<DualScopeConfigureResult> {\n const projectDir = options.projectDir ?? process.cwd();\n const globalOps = options.globalMcp ?? [];\n const projectOps = options.projectMcp ?? [];\n\n const globalResults: InstallResult[] = [];\n for (const operation of globalOps) {\n globalResults.push(await installMcpServer(\n provider,\n operation.serverName,\n operation.config,\n \"global\",\n projectDir,\n ));\n }\n\n const projectResults: InstallResult[] = [];\n for (const operation of projectOps) {\n projectResults.push(await installMcpServer(\n provider,\n operation.serverName,\n operation.config,\n \"project\",\n projectDir,\n ));\n }\n\n const instructionResults: DualScopeConfigureResult[\"instructions\"] = {};\n const instructionContent = options.instructionContent;\n if (typeof instructionContent === \"string\") {\n instructionResults.global = await injectAll([provider], projectDir, \"global\", instructionContent);\n instructionResults.project = await injectAll([provider], projectDir, \"project\", instructionContent);\n } else if (instructionContent) {\n if (instructionContent.global) {\n instructionResults.global = await injectAll([provider], projectDir, \"global\", instructionContent.global);\n }\n if (instructionContent.project) {\n instructionResults.project = await injectAll([provider], projectDir, \"project\", instructionContent.project);\n }\n }\n\n return {\n providerId: provider.id,\n configPaths: {\n global: resolveConfigPath(provider, \"global\", projectDir),\n project: resolveConfigPath(provider, \"project\", projectDir),\n },\n mcp: {\n global: globalResults,\n project: projectResults,\n },\n instructions: instructionResults,\n };\n}\n"],"mappings":"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","names":["existsSync","join","existsSync","join","existsSync","homedir","join","readdir","readFile","writeFile","mkdir","existsSync","homedir","join","API_BASE","toResult","readFile","existsSync","join","recommendSkills","readFile","existsSync","existsSync","readFile","rule","readdir","join","readFile","existsSync","matter","mkdir","dirname","readFile","writeFile","existsSync","existsSync","readFile","writeFile","readFile","writeFile","existsSync","existsSync","readFile","writeFile","readFile","writeFile","existsSync","existsSync","readFile","writeFile","join","existsSync","join","existsSync","readFile","writeFile","existsSync","join","dirname","mkdir","updated","rm","existsSync","lstatSync","cp","mkdir","readFile","readlink","rm","symlink","writeFile","homedir","basename","dirname","join","join","homedir","existsSync","readFile","rm","mkdir","dirname","writeFile","cp","lstatSync","readlink","basename","symlink"]}