frontmcp 1.2.1 → 1.3.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.
Files changed (108) hide show
  1. package/package.json +4 -4
  2. package/src/commands/build/exec/bin-meta.d.ts +49 -0
  3. package/src/commands/build/exec/bin-meta.js +68 -0
  4. package/src/commands/build/exec/bin-meta.js.map +1 -0
  5. package/src/commands/build/exec/cli-runtime/generate-cli-entry.js +195 -3
  6. package/src/commands/build/exec/cli-runtime/generate-cli-entry.js.map +1 -1
  7. package/src/commands/build/exec/cli-runtime/plugin-emitter.d.ts +160 -0
  8. package/src/commands/build/exec/cli-runtime/plugin-emitter.js +512 -0
  9. package/src/commands/build/exec/cli-runtime/plugin-emitter.js.map +1 -0
  10. package/src/commands/build/exec/cli-runtime/schema-extractor.d.ts +13 -1
  11. package/src/commands/build/exec/cli-runtime/schema-extractor.js +29 -3
  12. package/src/commands/build/exec/cli-runtime/schema-extractor.js.map +1 -1
  13. package/src/commands/build/exec/cli-runtime/skill-md-compose.d.ts +25 -0
  14. package/src/commands/build/exec/cli-runtime/skill-md-compose.js +63 -0
  15. package/src/commands/build/exec/cli-runtime/skill-md-compose.js.map +1 -0
  16. package/src/commands/build/exec/index.js +26 -0
  17. package/src/commands/build/exec/index.js.map +1 -1
  18. package/src/commands/dev/bridge/child-supervisor.d.ts +48 -0
  19. package/src/commands/dev/bridge/child-supervisor.js +228 -0
  20. package/src/commands/dev/bridge/child-supervisor.js.map +1 -0
  21. package/src/commands/dev/bridge/errors.d.ts +23 -0
  22. package/src/commands/dev/bridge/errors.js +34 -0
  23. package/src/commands/dev/bridge/errors.js.map +1 -0
  24. package/src/commands/dev/bridge/index.d.ts +30 -0
  25. package/src/commands/dev/bridge/index.js +220 -0
  26. package/src/commands/dev/bridge/index.js.map +1 -0
  27. package/src/commands/dev/bridge/log.d.ts +29 -0
  28. package/src/commands/dev/bridge/log.js +82 -0
  29. package/src/commands/dev/bridge/log.js.map +1 -0
  30. package/src/commands/dev/bridge/state-machine.d.ts +56 -0
  31. package/src/commands/dev/bridge/state-machine.js +245 -0
  32. package/src/commands/dev/bridge/state-machine.js.map +1 -0
  33. package/src/commands/dev/bridge/stdio-framer.d.ts +47 -0
  34. package/src/commands/dev/bridge/stdio-framer.js +128 -0
  35. package/src/commands/dev/bridge/stdio-framer.js.map +1 -0
  36. package/src/commands/dev/bridge/upstream-client.d.ts +49 -0
  37. package/src/commands/dev/bridge/upstream-client.js +159 -0
  38. package/src/commands/dev/bridge/upstream-client.js.map +1 -0
  39. package/src/commands/dev/bridge/watcher.d.ts +30 -0
  40. package/src/commands/dev/bridge/watcher.js +87 -0
  41. package/src/commands/dev/bridge/watcher.js.map +1 -0
  42. package/src/commands/dev/dev.d.ts +18 -1
  43. package/src/commands/dev/dev.js +134 -14
  44. package/src/commands/dev/dev.js.map +1 -1
  45. package/src/commands/dev/inspector.d.ts +13 -1
  46. package/src/commands/dev/inspector.js +77 -3
  47. package/src/commands/dev/inspector.js.map +1 -1
  48. package/src/commands/dev/port.d.ts +23 -0
  49. package/src/commands/dev/port.js +87 -0
  50. package/src/commands/dev/port.js.map +1 -0
  51. package/src/commands/dev/register.d.ts +1 -1
  52. package/src/commands/dev/register.js +28 -4
  53. package/src/commands/dev/register.js.map +1 -1
  54. package/src/commands/dev/test.d.ts +26 -1
  55. package/src/commands/dev/test.js +181 -64
  56. package/src/commands/dev/test.js.map +1 -1
  57. package/src/commands/eject/mcp-client.d.ts +25 -0
  58. package/src/commands/eject/mcp-client.js +74 -0
  59. package/src/commands/eject/mcp-client.js.map +1 -0
  60. package/src/commands/eject/register.d.ts +9 -0
  61. package/src/commands/eject/register.js +56 -0
  62. package/src/commands/eject/register.js.map +1 -0
  63. package/src/commands/install/install-claude-plugin.d.ts +13 -0
  64. package/src/commands/install/install-claude-plugin.js +327 -0
  65. package/src/commands/install/install-claude-plugin.js.map +1 -0
  66. package/src/commands/install/register.d.ts +16 -0
  67. package/src/commands/install/register.js +70 -0
  68. package/src/commands/install/register.js.map +1 -0
  69. package/src/commands/scaffold/create.js +44 -0
  70. package/src/commands/scaffold/create.js.map +1 -1
  71. package/src/commands/skills/from-entry.d.ts +31 -0
  72. package/src/commands/skills/from-entry.js +68 -0
  73. package/src/commands/skills/from-entry.js.map +1 -0
  74. package/src/commands/skills/install.d.ts +12 -0
  75. package/src/commands/skills/install.js +173 -8
  76. package/src/commands/skills/install.js.map +1 -1
  77. package/src/commands/skills/register.js +7 -3
  78. package/src/commands/skills/register.js.map +1 -1
  79. package/src/config/frontmcp-config.loader.d.ts +28 -0
  80. package/src/config/frontmcp-config.loader.js +146 -67
  81. package/src/config/frontmcp-config.loader.js.map +1 -1
  82. package/src/config/frontmcp-config.resolve.d.ts +67 -0
  83. package/src/config/frontmcp-config.resolve.js +118 -0
  84. package/src/config/frontmcp-config.resolve.js.map +1 -0
  85. package/src/config/frontmcp-config.schema.d.ts +207 -0
  86. package/src/config/frontmcp-config.schema.js +217 -1
  87. package/src/config/frontmcp-config.schema.js.map +1 -1
  88. package/src/config/frontmcp-config.types.d.ts +133 -0
  89. package/src/config/frontmcp-config.types.js.map +1 -1
  90. package/src/config/index.d.ts +2 -1
  91. package/src/config/index.js +3 -1
  92. package/src/config/index.js.map +1 -1
  93. package/src/core/args.d.ts +13 -0
  94. package/src/core/args.js.map +1 -1
  95. package/src/core/bridge.js +39 -0
  96. package/src/core/bridge.js.map +1 -1
  97. package/src/core/cli.d.ts +0 -6
  98. package/src/core/cli.js +23 -3
  99. package/src/core/cli.js.map +1 -1
  100. package/src/core/help.d.ts +1 -1
  101. package/src/core/help.js +27 -6
  102. package/src/core/help.js.map +1 -1
  103. package/src/core/program.d.ts +1 -1
  104. package/src/core/program.js +56 -12
  105. package/src/core/program.js.map +1 -1
  106. package/src/core/project-commands.d.ts +44 -0
  107. package/src/core/project-commands.js +216 -0
  108. package/src/core/project-commands.js.map +1 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-emitter.js","sourceRoot":"","sources":["../../../../../../src/commands/build/exec/cli-runtime/plugin-emitter.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Plugin emitter for issue #411 — turn a FrontMCP server's metadata into\n * a Claude Code plugin folder (`.claude/plugins/<bin>/`) or a Codex\n * `mcp_servers` entry. Shared by the dev-tool `frontmcp install` command\n * and the per-bin `<bin> install -p claude|codex` command.\n *\n * Design constraints (from planning/issues/411.md):\n * - Pure helper module — no side-effects at import time.\n * - All filesystem ops go through `@frontmcp/utils`.\n * - Re-running install must be idempotent: managed files tracked in\n * `_meta.frontmcp.managedFiles`; user-added files in the plugin\n * directory are NEVER deleted.\n * - Manifest written deterministically (sorted keys, fixed spacing) so\n * snapshots are stable and re-runs are no-ops when nothing changed.\n * - Codex emitter writes a TOML fragment without pulling in a TOML\n * dependency — only the `[[mcp_servers]]` shape is needed.\n */\n\nimport * as path from 'path';\n\nimport {\n cp,\n ensureDir,\n fileExists,\n readdir,\n readFile,\n rm,\n writeFile,\n} from '@frontmcp/utils';\n\nimport { composeSkillMd } from './skill-md-compose';\n\n// ============================================================================\n// Public types\n// ============================================================================\n\nexport interface PluginEmitterSkillInput {\n name: string;\n description: string;\n /**\n * Tags from `@Skill({ tags })`. Forwarded into the synthesized SKILL.md\n * frontmatter so Claude Code's filesystem loader can index by tag.\n */\n tags?: string[];\n /** License from `@Skill({ license })`. Forwarded into the synthesized frontmatter. */\n license?: string;\n /** Absolute path to SKILL.md. When missing, only frontmatter is emitted. */\n instructionFile?: string;\n /** Absolute paths to the skill's resource subdirectories. */\n resourceDirs?: {\n references?: string;\n examples?: string;\n scripts?: string;\n assets?: string;\n };\n}\n\nexport interface PluginEmitterCommandInput {\n /** Slash-command name without leading `/`. */\n name: string;\n description?: string;\n arguments?: Array<{ name: string; description?: string; required?: boolean }>;\n}\n\nexport interface EmitClaudePluginOptions {\n /** Root dir under which `<name>/` will be created. */\n destRoot: string;\n name: string;\n version: string;\n description: string;\n /** MCP server invocation command (e.g. the bin name, or `node ./dist/main.js`). */\n mcpCommand: string;\n /** Typically `['serve', '--stdio']`. */\n mcpArgs: string[];\n /** Env-var names (placeholder values) to surface in `mcpServers.<bin>.env`. */\n envHints: string[];\n skills: PluginEmitterSkillInput[];\n commands: PluginEmitterCommandInput[];\n /** Used for `_meta.frontmcp.installedBy`. */\n cliVersion: string;\n /** If true: plan only, do not write. */\n dryRun?: boolean;\n}\n\nexport interface EmitClaudePluginResult {\n pluginDir: string;\n manifest: ClaudePluginManifest;\n /** Absolute paths written (or that WOULD be written when dryRun). */\n filesWritten: string[];\n /** Absolute paths of pre-existing user files left in place. */\n filesPreserved: string[];\n /** Managed files from a previous install that were removed this run. */\n filesRemoved: string[];\n}\n\nexport interface ClaudePluginManifest {\n name: string;\n version: string;\n description: string;\n mcpServers: Record<string, McpServerEntry>;\n skills: string[];\n commands?: string[];\n _meta: {\n frontmcp: {\n installedBy: string;\n installedAt: string;\n bin: string;\n binVersion: string;\n managedFields: string[];\n managedFiles: string[];\n };\n };\n}\n\nexport interface McpServerEntry {\n command: string;\n args: string[];\n transport?: 'stdio';\n env?: Record<string, string>;\n}\n\nexport interface EmitCodexOptions {\n /** `~/.codex/config.toml` typically. */\n configPath: string;\n name: string;\n command: string;\n args: string[];\n env?: Record<string, string>;\n dryRun?: boolean;\n}\n\nexport interface EmitCodexResult {\n written: boolean;\n previousVersion?: string;\n /** Final TOML content (or what would be written when dryRun). */\n configContent: string;\n}\n\n// ============================================================================\n// Claude plugin emitter\n// ============================================================================\n\n/**\n * Validate a plugin name before it touches the filesystem or TOML blocks.\n * Rejects anything that could traverse out of the destination directory,\n * inject newlines into the codex block markers (`# frontmcp:codex-start:<name>`\n * / `# frontmcp:codex-end:<name>` — finding from #411 review), or smuggle\n * TOML-significant characters past the `tomlString` quoting.\n *\n * The allowed set is intentionally narrow — npm-style scoped names\n * (`@scope/name`) are NOT allowed since the `@` and `/` characters would\n * still produce surprising directory layouts. Callers that need scoped\n * names should sanitise first.\n */\n/**\n * Validate a slash-command name (frontmatter / body content). Same rules\n * as `assertValidPluginName` so a malicious command name cannot inject\n * YAML directives or new markdown sections via interpolated body text\n * in `renderCommandFile`.\n */\nexport function assertValidCommandName(name: string, where: string): void {\n assertValidPluginName(name, where);\n}\n\nexport function assertValidPluginName(name: string, where: string): void {\n if (typeof name !== 'string' || name.length === 0) {\n throw new Error(`Invalid plugin name passed to ${where}: must be a non-empty string`);\n }\n if (name.length > 64) {\n throw new Error(`Invalid plugin name \"${name}\" passed to ${where}: must be 64 chars or fewer`);\n }\n if (name === '.' || name === '..') {\n throw new Error(`Invalid plugin name \"${name}\" passed to ${where}: must not be \".\" or \"..\"`);\n }\n if (!/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(name)) {\n throw new Error(\n `Invalid plugin name \"${name}\" passed to ${where}: must match /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/ (no slashes, newlines, or special chars)`,\n );\n }\n}\n\n/**\n * Returns true when `rel` resolves to a path strictly inside `pluginDir`.\n * Defends `emitClaudePlugin` and `removeClaudePlugin` against a tampered\n * prior `plugin.json` whose `_meta.frontmcp.managedFiles` entries try to\n * escape the plugin root with `../` traversals or absolute paths.\n */\nexport function isPluginContainedPath(pluginDir: string, rel: string): boolean {\n if (typeof rel !== 'string' || rel.length === 0) return false;\n if (path.isAbsolute(rel)) return false;\n const resolved = path.resolve(pluginDir, rel);\n const relative = path.relative(pluginDir, resolved);\n if (relative === '') return false; // never delete the plugin dir itself via a managedFile entry\n return !relative.startsWith('..') && !path.isAbsolute(relative);\n}\n\nconst FRAMEWORK_MANAGED_FIELDS = [\n 'name',\n 'version',\n 'description',\n 'mcpServers',\n 'skills',\n 'commands',\n '_meta.frontmcp',\n];\n\nexport async function emitClaudePlugin(opts: EmitClaudePluginOptions): Promise<EmitClaudePluginResult> {\n assertValidPluginName(opts.name, 'emitClaudePlugin');\n const pluginDir = path.join(opts.destRoot, opts.name);\n const claudePluginDir = path.join(pluginDir, '.claude-plugin');\n const manifestPath = path.join(claudePluginDir, 'plugin.json');\n\n // Read prior manifest (idempotency baseline) — file may not exist on first install.\n const previousManifest = await readPluginManifest(manifestPath);\n const previouslyManaged = previousManifest?._meta?.frontmcp?.managedFiles ?? [];\n\n // Build the new file plan in deterministic order.\n const plannedFiles: Array<{ absPath: string; relPath: string; action: () => Promise<void> }> = [];\n\n // Skills subtree. Validate the name before it lands in a filesystem\n // path or in synthesized SKILL.md frontmatter — same rules as command\n // names (issue #411 security pass), so a malicious `@Skill({ name: '../x' })`\n // can't escape the plugin tree.\n for (const skill of [...opts.skills].sort((a, b) => a.name.localeCompare(b.name))) {\n assertValidPluginName(skill.name, 'emitClaudePlugin.skill');\n const skillDir = path.join(pluginDir, 'skills', skill.name);\n const skillMd = path.join(skillDir, 'SKILL.md');\n plannedFiles.push({\n absPath: skillMd,\n relPath: path.relative(pluginDir, skillMd),\n action: async () => {\n await ensureDir(skillDir);\n const body = skill.instructionFile && (await fileExists(skill.instructionFile))\n ? await readFile(skill.instructionFile)\n : '';\n // The instruction file is typically a raw markdown body authored by\n // the user; Claude Code's filesystem loader needs YAML frontmatter\n // with at least `name` + `description`. composeSkillMd preserves a\n // pre-existing frontmatter block verbatim and otherwise synthesizes\n // one from the decorator metadata we plumbed through bin-meta.json.\n await writeFile(\n skillMd,\n composeSkillMd(\n { name: skill.name, description: skill.description, tags: skill.tags, license: skill.license },\n body,\n ),\n );\n },\n });\n for (const kind of ['references', 'examples', 'scripts', 'assets'] as const) {\n const src = skill.resourceDirs?.[kind];\n if (!src) continue;\n const dest = path.join(skillDir, kind);\n plannedFiles.push({\n absPath: dest,\n relPath: path.relative(pluginDir, dest),\n action: async () => {\n await ensureDir(skillDir);\n if (await fileExists(src)) {\n await cp(src, dest, { recursive: true });\n }\n },\n });\n }\n }\n\n // Commands subtree. Validate each command name before it lands in the\n // markdown body or the filesystem path — same rules as the plugin name.\n for (const cmd of [...opts.commands].sort((a, b) => a.name.localeCompare(b.name))) {\n assertValidCommandName(cmd.name, 'emitClaudePlugin.command');\n const cmdPath = path.join(pluginDir, 'commands', `${cmd.name}.md`);\n plannedFiles.push({\n absPath: cmdPath,\n relPath: path.relative(pluginDir, cmdPath),\n action: async () => {\n await ensureDir(path.dirname(cmdPath));\n await writeFile(cmdPath, renderCommandFile(cmd, opts.name));\n },\n });\n }\n\n // Build the manifest. Manifest is itself a managed file and appears last in\n // managedFiles so removal-on-uninstall happens after subtree cleanup.\n const newManagedFiles = plannedFiles.map((f) => f.relPath).sort();\n const manifest: ClaudePluginManifest = {\n name: opts.name,\n version: opts.version,\n description: opts.description,\n mcpServers: {\n [opts.name]: makeMcpServerEntry(opts),\n },\n skills: opts.skills.map((s) => s.name).sort(),\n ...(opts.commands.length > 0 ? { commands: opts.commands.map((c) => c.name).sort() } : {}),\n _meta: {\n frontmcp: {\n installedBy: `frontmcp@${opts.cliVersion}`,\n installedAt: new Date().toISOString(),\n bin: opts.name,\n binVersion: opts.version,\n managedFields: [...FRAMEWORK_MANAGED_FIELDS].sort(),\n managedFiles: newManagedFiles,\n },\n },\n };\n\n // Merge any user-owned top-level keys back in from the previous manifest.\n const mergedManifest = mergeUserManifestFields(manifest, previousManifest);\n\n // Compute the file delta. We don't `rm -rf` the plugin dir; we only:\n // 1. Remove previously-managed files that are no longer in newManagedFiles.\n // 2. Write/overwrite the new managed files.\n // 3. Write the manifest.\n const previousSet = new Set(previouslyManaged);\n const newSet = new Set(newManagedFiles);\n const removed: string[] = [];\n const written: string[] = [];\n\n if (!opts.dryRun) {\n await ensureDir(claudePluginDir);\n // 1. Drop stale managed files. Guard against a tampered prior manifest\n // that may have injected escape-paths into `managedFiles`.\n for (const rel of previousSet) {\n if (newSet.has(rel)) continue;\n if (!isPluginContainedPath(pluginDir, rel)) continue;\n const abs = path.join(pluginDir, rel);\n if (await fileExists(abs)) {\n await rm(abs, { recursive: true, force: true });\n removed.push(abs);\n }\n }\n // 2. Write new/refreshed managed files.\n for (const f of plannedFiles) {\n await f.action();\n written.push(f.absPath);\n }\n // 3. Manifest.\n await writeFile(manifestPath, serializeManifest(mergedManifest));\n written.push(manifestPath);\n } else {\n written.push(...plannedFiles.map((f) => f.absPath), manifestPath);\n }\n\n const preserved = previousManifest\n ? Object.keys(previousManifest)\n .filter((k) => !FRAMEWORK_MANAGED_FIELDS.includes(k) && k !== '_meta')\n .map((k) => `<plugin.json>.${k}`)\n : [];\n\n return {\n pluginDir,\n manifest: mergedManifest,\n filesWritten: written,\n filesPreserved: preserved,\n filesRemoved: removed,\n };\n}\n\nexport async function removeClaudePlugin(args: {\n destRoot: string;\n name: string;\n}): Promise<{ removed: string[]; preserved: string[]; pluginDir: string }> {\n assertValidPluginName(args.name, 'removeClaudePlugin');\n const pluginDir = path.join(args.destRoot, args.name);\n const manifestPath = path.join(pluginDir, '.claude-plugin', 'plugin.json');\n const manifest = await readPluginManifest(manifestPath);\n const removed: string[] = [];\n const preserved: string[] = [];\n\n if (!manifest) {\n return { removed, preserved, pluginDir };\n }\n\n // A tampered `plugin.json` could have injected paths like `../../etc/foo`\n // into `_meta.frontmcp.managedFiles` to coerce `rm` outside `pluginDir`\n // on uninstall. Guard each entry against escaping the plugin root.\n const managed = manifest._meta?.frontmcp?.managedFiles ?? [];\n for (const rel of managed) {\n if (!isPluginContainedPath(pluginDir, rel)) continue;\n const abs = path.join(pluginDir, rel);\n if (await fileExists(abs)) {\n await rm(abs, { recursive: true, force: true });\n removed.push(abs);\n }\n }\n if (await fileExists(manifestPath)) {\n await rm(manifestPath, { force: true });\n removed.push(manifestPath);\n }\n\n // Bottom-up empty-dir cleanup. Stops at first non-empty dir, preserving\n // user-added files.\n await cleanupEmptyDirs(pluginDir, preserved);\n\n return { removed, preserved, pluginDir };\n}\n\nexport async function readInstalledPluginVersion(pluginDir: string): Promise<string | undefined> {\n const manifestPath = path.join(pluginDir, '.claude-plugin', 'plugin.json');\n const manifest = await readPluginManifest(manifestPath);\n return manifest?._meta?.frontmcp?.binVersion;\n}\n\n// ============================================================================\n// Codex emitter\n// ============================================================================\n\nconst CODEX_BLOCK_START = '# frontmcp:codex-start';\nconst CODEX_BLOCK_END = '# frontmcp:codex-end';\n\nexport async function emitCodexEntry(opts: EmitCodexOptions): Promise<EmitCodexResult> {\n assertValidPluginName(opts.name, 'emitCodexEntry');\n const existing = (await fileExists(opts.configPath)) ? await readFile(opts.configPath) : '';\n const previousVersion = extractCodexEntryComment(existing, opts.name);\n const newBlock = renderCodexBlock(opts);\n const merged = replaceCodexBlock(existing, opts.name, newBlock);\n\n if (!opts.dryRun) {\n await ensureDir(path.dirname(opts.configPath));\n await writeFile(opts.configPath, merged);\n }\n\n return {\n written: !opts.dryRun,\n previousVersion,\n configContent: merged,\n };\n}\n\nexport async function removeCodexEntry(args: {\n configPath: string;\n name: string;\n}): Promise<{ removed: boolean; configContent: string }> {\n assertValidPluginName(args.name, 'removeCodexEntry');\n if (!(await fileExists(args.configPath))) {\n return { removed: false, configContent: '' };\n }\n const existing = await readFile(args.configPath);\n const stripped = stripCodexBlock(existing, args.name);\n const removed = stripped !== existing;\n if (removed) {\n await writeFile(args.configPath, stripped);\n }\n return { removed, configContent: stripped };\n}\n\n// ============================================================================\n// Internals\n// ============================================================================\n\nfunction makeMcpServerEntry(opts: EmitClaudePluginOptions): McpServerEntry {\n const entry: McpServerEntry = {\n command: opts.mcpCommand,\n args: opts.mcpArgs,\n transport: 'stdio',\n };\n if (opts.envHints.length > 0) {\n const env: Record<string, string> = {};\n for (const name of opts.envHints.slice().sort()) {\n env[name] = `\\${${name}}`;\n }\n entry.env = env;\n }\n return entry;\n}\n\nasync function readPluginManifest(manifestPath: string): Promise<ClaudePluginManifest | undefined> {\n if (!(await fileExists(manifestPath))) return undefined;\n try {\n const raw = await readFile(manifestPath);\n return JSON.parse(raw) as ClaudePluginManifest;\n } catch {\n return undefined;\n }\n}\n\nfunction mergeUserManifestFields(\n next: ClaudePluginManifest,\n previous: ClaudePluginManifest | undefined,\n): ClaudePluginManifest {\n if (!previous) return next;\n const out = { ...next } as Record<string, unknown>;\n // Preserve user-added entries in mcpServers other than the framework-owned one.\n if (previous.mcpServers && typeof previous.mcpServers === 'object') {\n const mergedMcp: Record<string, McpServerEntry> = { ...next.mcpServers };\n for (const [k, v] of Object.entries(previous.mcpServers)) {\n if (k !== next.name) mergedMcp[k] = v;\n }\n out.mcpServers = sortObjectKeys(mergedMcp);\n }\n // Preserve any unknown top-level key the user added.\n for (const [k, v] of Object.entries(previous)) {\n if (!FRAMEWORK_MANAGED_FIELDS.includes(k) && k !== '_meta' && !(k in out)) {\n out[k] = v;\n }\n }\n return out as unknown as ClaudePluginManifest;\n}\n\nfunction serializeManifest(manifest: ClaudePluginManifest): string {\n return JSON.stringify(sortObjectKeys(manifest), null, 2) + '\\n';\n}\n\nfunction sortObjectKeys<T>(value: T): T {\n if (Array.isArray(value)) {\n return value.map((v) => sortObjectKeys(v)) as unknown as T;\n }\n if (value && typeof value === 'object') {\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(value as object).sort()) {\n sorted[key] = sortObjectKeys((value as Record<string, unknown>)[key]);\n }\n return sorted as unknown as T;\n }\n return value;\n}\n\nfunction renderCommandFile(cmd: PluginEmitterCommandInput, binName: string): string {\n const args = cmd.arguments ?? [];\n const argHint = args\n .map((a) => (a.required === false ? `[${a.name}]` : `<${a.name}>`))\n .join(' ');\n const fm = ['---'];\n if (cmd.description) fm.push(`description: ${JSON.stringify(cmd.description)}`);\n if (argHint) fm.push(`argument-hint: ${JSON.stringify(argHint)}`);\n fm.push('---', '');\n const body = [\n `Invokes the MCP prompt \\`${cmd.name}\\` from the \\`${binName}\\` server.`,\n '',\n `See \\`${binName} prompt get ${cmd.name}\\` for the latest argument list.`,\n '',\n ];\n return fm.join('\\n') + '\\n' + body.join('\\n');\n}\n\n/**\n * Bottom-up empty-directory cleanup after `removeClaudePlugin`. We only\n * remove a directory when:\n * 1. it's a framework-managed directory we know we created\n * (`commands/`, `skills/`, `skills/<name>/`, `.claude-plugin/`,\n * and the plugin root itself), AND\n * 2. it is empty (`readdir` returns []).\n *\n * Any user-added file under those dirs blocks the cleanup at that level\n * and bubbles all the way up — so a single user file anywhere in the\n * plugin tree leaves the entire tree (and the plugin dir itself) intact.\n * We never traverse INTO user-added subdirs.\n */\nasync function cleanupEmptyDirs(root: string, _preserved: string[]): Promise<void> {\n if (!(await fileExists(root))) return;\n // `readdir` and `rm` are imported statically at the top of this module so\n // the file bundles cleanly into the per-bin CLI (esbuild can't resolve\n // `await import('@frontmcp/utils')` inside a CJS bundle, which manifests\n // as a runtime \"Dynamic require of fs is not supported\" error when the\n // bin's own `uninstall -p claude` walks the plugin tree).\n\n // Pass 1: each per-skill folder under skills/ (one level deep).\n const skillsDir = path.join(root, 'skills');\n if (await fileExists(skillsDir)) {\n for (const entry of await safeReaddir(readdir, skillsDir)) {\n const sub = path.join(skillsDir, entry);\n await removeIfEmpty(sub, rm, readdir);\n }\n }\n\n // Pass 2: framework-managed dirs directly under the plugin root.\n for (const sub of ['commands', 'skills', '.claude-plugin']) {\n await removeIfEmpty(path.join(root, sub), rm, readdir);\n }\n\n // Pass 3: the plugin root itself (only if user added nothing).\n await removeIfEmpty(root, rm, readdir);\n}\n\nasync function removeIfEmpty(\n dir: string,\n rmFn: (p: string, opts?: { recursive?: boolean; force?: boolean }) => Promise<void>,\n readdirFn: (p: string) => Promise<string[]>,\n): Promise<void> {\n if (!(await fileExists(dir))) return;\n const entries = await safeReaddir(readdirFn, dir);\n if (entries.length === 0) {\n await rmFn(dir, { recursive: true, force: true });\n }\n}\n\nasync function safeReaddir(\n readdirFn: (p: string) => Promise<string[]>,\n dir: string,\n): Promise<string[]> {\n try {\n return await readdirFn(dir);\n } catch {\n return [];\n }\n}\n\n// ----- Codex TOML -----\n\nfunction renderCodexBlock(opts: EmitCodexOptions): string {\n const lines: string[] = [];\n lines.push(`${CODEX_BLOCK_START}:${opts.name}`);\n lines.push(`[[mcp_servers]]`);\n lines.push(`name = ${tomlString(opts.name)}`);\n lines.push(`command = ${tomlString(opts.command)}`);\n lines.push(`args = [${opts.args.map(tomlString).join(', ')}]`);\n if (opts.env && Object.keys(opts.env).length > 0) {\n const entries = Object.entries(opts.env)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([k, v]) => `${tomlBareKey(k)} = ${tomlString(v)}`);\n lines.push(`env = { ${entries.join(', ')} }`);\n }\n lines.push(`${CODEX_BLOCK_END}:${opts.name}`);\n return lines.join('\\n');\n}\n\nfunction replaceCodexBlock(existing: string, name: string, newBlock: string): string {\n const start = `${CODEX_BLOCK_START}:${name}`;\n const end = `${CODEX_BLOCK_END}:${name}`;\n const startIdx = existing.indexOf(start);\n if (startIdx === -1) {\n // Normalize the existing content to end in exactly one newline before\n // appending the new block, so we don't double-up on first insert.\n const normalized = existing.length === 0 ? '' : existing.replace(/\\n*$/, '\\n');\n const sep = normalized.length === 0 ? '' : '\\n';\n return `${normalized}${sep}${newBlock}\\n`;\n }\n const endIdx = existing.indexOf(end, startIdx);\n if (endIdx === -1) {\n // Corrupt block — treat as missing and append fresh.\n return `${existing.replace(/\\n*$/, '\\n')}\\n${newBlock}\\n`;\n }\n const before = existing.slice(0, startIdx);\n const after = existing.slice(endIdx + end.length).replace(/^\\n/, '');\n return `${before}${newBlock}\\n${after}`;\n}\n\nfunction stripCodexBlock(existing: string, name: string): string {\n const start = `${CODEX_BLOCK_START}:${name}`;\n const end = `${CODEX_BLOCK_END}:${name}`;\n const startIdx = existing.indexOf(start);\n if (startIdx === -1) return existing;\n const endIdx = existing.indexOf(end, startIdx);\n if (endIdx === -1) return existing;\n const before = existing.slice(0, startIdx).replace(/\\n+$/, '\\n');\n const after = existing.slice(endIdx + end.length).replace(/^\\n+/, '\\n');\n return (before + after).replace(/\\n{3,}/g, '\\n\\n');\n}\n\nfunction extractCodexEntryComment(content: string, name: string): string | undefined {\n // Optional: look for an `# version:` comment inside the block; for now we\n // just return undefined since the block itself doesn't carry a version.\n void content;\n void name;\n return undefined;\n}\n\nfunction tomlString(value: string): string {\n // Basic strings: escape backslash + double-quote, encode common control chars.\n const escaped = value\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r')\n .replace(/\\t/g, '\\\\t');\n return `\"${escaped}\"`;\n}\n\nfunction tomlBareKey(key: string): string {\n return /^[A-Za-z0-9_-]+$/.test(key) ? key : tomlString(key);\n}\n"]}
@@ -49,6 +49,12 @@ export interface ExtractedSkillAsset {
49
49
  scripts?: string;
50
50
  assets?: string;
51
51
  };
52
+ /** Mirrors `SkillAssetEntry.description` so consumers can compose frontmatter. */
53
+ description?: string;
54
+ /** Mirrors `SkillAssetEntry.tags`. */
55
+ tags?: string[];
56
+ /** Mirrors `SkillAssetEntry.license`. */
57
+ license?: string;
52
58
  }
53
59
  export interface ExtractedSchema {
54
60
  tools: ExtractedTool[];
@@ -66,7 +72,13 @@ export interface ExtractedSchema {
66
72
  */
67
73
  httpPort?: number;
68
74
  }
69
- /** Known system tool names injected by SDK features (jobs, workflows). */
75
+ /**
76
+ * Known system tool names injected by SDK features (jobs, workflows).
77
+ *
78
+ * Canonical names are snake_case per issue #408; hyphenated aliases are
79
+ * kept transitionally so older built bundles continue to be recognized by
80
+ * the schema extractor.
81
+ */
70
82
  export declare const SYSTEM_TOOL_NAMES: Set<string>;
71
83
  /**
72
84
  * Extract schemas from a compiled server bundle.
@@ -7,8 +7,25 @@
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
8
  exports.SYSTEM_TOOL_NAMES = void 0;
9
9
  exports.extractSchemas = extractSchemas;
10
- /** Known system tool names injected by SDK features (jobs, workflows). */
10
+ /**
11
+ * Known system tool names injected by SDK features (jobs, workflows).
12
+ *
13
+ * Canonical names are snake_case per issue #408; hyphenated aliases are
14
+ * kept transitionally so older built bundles continue to be recognized by
15
+ * the schema extractor.
16
+ */
11
17
  exports.SYSTEM_TOOL_NAMES = new Set([
18
+ 'list_jobs',
19
+ 'execute_job',
20
+ 'get_job_status',
21
+ 'register_job',
22
+ 'remove_job',
23
+ 'list_workflows',
24
+ 'execute_workflow',
25
+ 'get_workflow_status',
26
+ 'register_workflow',
27
+ 'remove_workflow',
28
+ // Legacy hyphen names — accepted for back-compat with previously built bundles.
12
29
  'list-jobs',
13
30
  'execute-job',
14
31
  'get-job-status',
@@ -101,8 +118,14 @@ async function extractSchemas(bundlePath) {
101
118
  const hasSkillsResources = resourceTemplates.some((rt) => rt.uriTemplate.startsWith('skill://'));
102
119
  const capabilities = {
103
120
  skills: hasSkillsResources,
104
- jobs: toolNameSet.has('execute-job') || toolNameSet.has('get-job-status'),
105
- workflows: toolNameSet.has('execute-workflow') || toolNameSet.has('get-workflow-status'),
121
+ jobs: toolNameSet.has('execute_job') ||
122
+ toolNameSet.has('get_job_status') ||
123
+ toolNameSet.has('execute-job') ||
124
+ toolNameSet.has('get-job-status'),
125
+ workflows: toolNameSet.has('execute_workflow') ||
126
+ toolNameSet.has('get_workflow_status') ||
127
+ toolNameSet.has('execute-workflow') ||
128
+ toolNameSet.has('get-workflow-status'),
106
129
  };
107
130
  // Extract job schemas if jobs capability is available
108
131
  let jobs = [];
@@ -130,6 +153,9 @@ async function extractSchemas(bundlePath) {
130
153
  baseDir: e.baseDir,
131
154
  instructionFile: e.instructionFile,
132
155
  resourceDirs: e.resources,
156
+ description: e.description,
157
+ tags: e.tags,
158
+ license: e.license,
133
159
  }));
134
160
  }
135
161
  catch {
@@ -1 +1 @@
1
- {"version":3,"file":"schema-extractor.js","sourceRoot":"","sources":["../../../../../../src/commands/build/exec/cli-runtime/schema-extractor.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Build-time schema extraction.\n * After the server bundle is produced, boots a DirectClient via connect(),\n * extracts tool/resource/prompt schemas, and serializes them for CLI code generation.\n */\n\nexport interface ExtractedTool {\n name: string;\n description: string;\n inputSchema: Record<string, unknown>;\n}\n\nexport interface ExtractedResource {\n uri: string;\n name: string;\n description?: string;\n mimeType?: string;\n}\n\nexport interface ExtractedResourceTemplate {\n uriTemplate: string;\n name: string;\n description?: string;\n}\n\nexport interface ExtractedPrompt {\n name: string;\n description?: string;\n arguments?: Array<{\n name: string;\n description?: string;\n required?: boolean;\n }>;\n}\n\nexport interface ExtractedJob {\n name: string;\n description?: string;\n inputSchema?: Record<string, unknown>;\n tags?: string[];\n}\n\nexport interface ExtractedCapabilities {\n skills: boolean;\n jobs: boolean;\n workflows: boolean;\n}\n\nexport interface ExtractedSkillAsset {\n skillName: string;\n baseDir?: string;\n instructionFile?: string;\n resourceDirs?: {\n references?: string;\n examples?: string;\n scripts?: string;\n assets?: string;\n };\n}\n\nexport interface ExtractedSchema {\n tools: ExtractedTool[];\n resources: ExtractedResource[];\n resourceTemplates: ExtractedResourceTemplate[];\n prompts: ExtractedPrompt[];\n jobs: ExtractedJob[];\n capabilities: ExtractedCapabilities;\n skillAssets: ExtractedSkillAsset[];\n /**\n * Server bind config extracted from `@FrontMcp({ http })` (or its\n * decorator-attached `__frontmcp:config` metadata). Used by the manifest\n * writer so the published manifest reflects the port the server will\n * actually listen on, not a hard-coded SDK default.\n */\n httpPort?: number;\n}\n\n/** Known system tool names injected by SDK features (jobs, workflows). */\nexport const SYSTEM_TOOL_NAMES = new Set([\n 'list-jobs',\n 'execute-job',\n 'get-job-status',\n 'register-job',\n 'remove-job',\n 'list-workflows',\n 'execute-workflow',\n 'get-workflow-status',\n 'register-workflow',\n 'remove-workflow',\n]);\n\n/**\n * Extract schemas from a compiled server bundle.\n * Requires the bundle to export a FrontMcp-decorated class as default export\n * or a config object usable by connect().\n */\nexport async function extractSchemas(bundlePath: string): Promise<ExtractedSchema> {\n // Suppress @FrontMcp() decorator bootstrap — we only need metadata, not a running server\n const prev = process.env['FRONTMCP_SCHEMA_EXTRACT'];\n process.env['FRONTMCP_SCHEMA_EXTRACT'] = '1';\n\n let mod: Record<string, unknown>;\n try {\n mod = require(bundlePath);\n } finally {\n if (prev === undefined) {\n delete process.env['FRONTMCP_SCHEMA_EXTRACT'];\n } else {\n process.env['FRONTMCP_SCHEMA_EXTRACT'] = prev;\n }\n }\n\n const configOrClass = mod.default || mod;\n\n // Use @frontmcp/sdk connect() to boot in-memory client\n let connect: (config: unknown, options?: { mode?: string }) => Promise<unknown>;\n try {\n const sdk = require('@frontmcp/sdk');\n connect = sdk.connect || sdk.direct?.connect;\n if (!connect) {\n throw new Error('connect() not found in @frontmcp/sdk');\n }\n } catch {\n throw new Error(\n '@frontmcp/sdk is required for CLI schema extraction. Ensure it is installed.',\n );\n }\n\n const client = await connect(configOrClass, { mode: 'cli' }) as {\n listTools(): Promise<unknown>;\n listResources(): Promise<{ resources: Array<{ uri: string; name?: string; description?: string; mimeType?: string }> }>;\n listResourceTemplates?(): Promise<{ resourceTemplates: Array<{ uriTemplate: string; name?: string; description?: string }> }>;\n listPrompts(): Promise<{ prompts: Array<{ name: string; description?: string; arguments?: unknown[] }> }>;\n listJobs?(): Promise<{ jobs: Array<{ name: string; description?: string; inputSchema?: Record<string, unknown>; tags?: string[] }>; count: number }>;\n collectSkillAssets?(): Promise<{ entries: Array<{ skillName: string; baseDir?: string; instructionFile?: string; resources?: Record<string, string | undefined> }> }>;\n close(): Promise<void>;\n };\n\n try {\n const [toolsRaw, resourcesResult, promptsResult] = await Promise.all([\n client.listTools().catch(() => []),\n client.listResources().catch(() => ({ resources: [] })),\n client.listPrompts().catch(() => ({ prompts: [] })),\n ]);\n\n let resourceTemplates: ExtractedResourceTemplate[] = [];\n if (client.listResourceTemplates) {\n try {\n const templatesResult = await client.listResourceTemplates();\n resourceTemplates = (templatesResult.resourceTemplates || []).map((t) => ({\n uriTemplate: t.uriTemplate,\n name: t.name || t.uriTemplate,\n description: t.description,\n }));\n } catch {\n // Resource templates not supported\n }\n }\n\n // DirectClient.listTools() returns FormattedTools (array) directly,\n // not { tools: [...] } like the raw MCP client\n const toolsList = Array.isArray(toolsRaw)\n ? toolsRaw as Array<{ name: string; description?: string; inputSchema?: unknown }>\n : ((toolsRaw as { tools?: unknown[] })?.tools || []) as Array<{ name: string; description?: string; inputSchema?: unknown }>;\n\n const tools: ExtractedTool[] = toolsList.map((t) => ({\n name: t.name,\n description: t.description || '',\n inputSchema: (t.inputSchema as Record<string, unknown>) || { type: 'object', properties: {} },\n }));\n\n const resources: ExtractedResource[] = (resourcesResult.resources || []).map((r) => ({\n uri: r.uri,\n name: r.name || r.uri,\n description: r.description,\n mimeType: r.mimeType,\n }));\n\n const prompts: ExtractedPrompt[] = (promptsResult.prompts || []).map((p) => ({\n name: p.name,\n description: p.description,\n arguments: p.arguments as ExtractedPrompt['arguments'],\n }));\n\n const toolNameSet = new Set(tools.map((t) => t.name));\n // SEP-2640: skills are exposed under the singular `skill://` URI scheme.\n const hasSkillsResources = resourceTemplates.some(\n (rt) => rt.uriTemplate.startsWith('skill://'),\n );\n const capabilities: ExtractedCapabilities = {\n skills: hasSkillsResources,\n jobs: toolNameSet.has('execute-job') || toolNameSet.has('get-job-status'),\n workflows: toolNameSet.has('execute-workflow') || toolNameSet.has('get-workflow-status'),\n };\n\n // Extract job schemas if jobs capability is available\n let jobs: ExtractedJob[] = [];\n if (capabilities.jobs && client.listJobs) {\n try {\n const jobsResult = await client.listJobs();\n jobs = (jobsResult.jobs || []).map((j) => ({\n name: j.name,\n description: j.description,\n inputSchema: j.inputSchema,\n tags: j.tags,\n }));\n } catch {\n // Jobs listing not available at build time\n }\n }\n\n // Collect skill file assets for copying to dist\n let skillAssets: ExtractedSkillAsset[] = [];\n if (capabilities.skills && client.collectSkillAssets) {\n try {\n const manifest = await client.collectSkillAssets();\n skillAssets = manifest.entries.map((e) => ({\n skillName: e.skillName,\n baseDir: e.baseDir,\n instructionFile: e.instructionFile,\n resourceDirs: e.resources as ExtractedSkillAsset['resourceDirs'],\n }));\n } catch {\n // Skill asset collection not available\n }\n }\n\n // Extract http.port from the @FrontMcp() decorator metadata. Returns\n // undefined when the entry is a plain config object (no decorator) or\n // when no port was declared — caller falls back to its own default.\n let httpPort: number | undefined;\n try {\n const sdk = require('@frontmcp/sdk') as { getDecoratorConfig?: (t: unknown) => Record<string, unknown> | undefined };\n const cfg = typeof sdk.getDecoratorConfig === 'function'\n ? sdk.getDecoratorConfig(configOrClass)\n : (configOrClass as Record<string, unknown> | undefined);\n const http = cfg?.['http'] as { port?: number } | undefined;\n if (http && typeof http.port === 'number') httpPort = http.port;\n } catch {\n // best-effort — manifest writer will fall back to its own default\n }\n\n return { tools, resources, resourceTemplates, prompts, jobs, capabilities, skillAssets, httpPort };\n } finally {\n await client.close().catch(() => {});\n }\n}\n"]}
1
+ {"version":3,"file":"schema-extractor.js","sourceRoot":"","sources":["../../../../../../src/commands/build/exec/cli-runtime/schema-extractor.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Build-time schema extraction.\n * After the server bundle is produced, boots a DirectClient via connect(),\n * extracts tool/resource/prompt schemas, and serializes them for CLI code generation.\n */\n\nexport interface ExtractedTool {\n name: string;\n description: string;\n inputSchema: Record<string, unknown>;\n}\n\nexport interface ExtractedResource {\n uri: string;\n name: string;\n description?: string;\n mimeType?: string;\n}\n\nexport interface ExtractedResourceTemplate {\n uriTemplate: string;\n name: string;\n description?: string;\n}\n\nexport interface ExtractedPrompt {\n name: string;\n description?: string;\n arguments?: Array<{\n name: string;\n description?: string;\n required?: boolean;\n }>;\n}\n\nexport interface ExtractedJob {\n name: string;\n description?: string;\n inputSchema?: Record<string, unknown>;\n tags?: string[];\n}\n\nexport interface ExtractedCapabilities {\n skills: boolean;\n jobs: boolean;\n workflows: boolean;\n}\n\nexport interface ExtractedSkillAsset {\n skillName: string;\n baseDir?: string;\n instructionFile?: string;\n resourceDirs?: {\n references?: string;\n examples?: string;\n scripts?: string;\n assets?: string;\n };\n /** Mirrors `SkillAssetEntry.description` so consumers can compose frontmatter. */\n description?: string;\n /** Mirrors `SkillAssetEntry.tags`. */\n tags?: string[];\n /** Mirrors `SkillAssetEntry.license`. */\n license?: string;\n}\n\nexport interface ExtractedSchema {\n tools: ExtractedTool[];\n resources: ExtractedResource[];\n resourceTemplates: ExtractedResourceTemplate[];\n prompts: ExtractedPrompt[];\n jobs: ExtractedJob[];\n capabilities: ExtractedCapabilities;\n skillAssets: ExtractedSkillAsset[];\n /**\n * Server bind config extracted from `@FrontMcp({ http })` (or its\n * decorator-attached `__frontmcp:config` metadata). Used by the manifest\n * writer so the published manifest reflects the port the server will\n * actually listen on, not a hard-coded SDK default.\n */\n httpPort?: number;\n}\n\n/**\n * Known system tool names injected by SDK features (jobs, workflows).\n *\n * Canonical names are snake_case per issue #408; hyphenated aliases are\n * kept transitionally so older built bundles continue to be recognized by\n * the schema extractor.\n */\nexport const SYSTEM_TOOL_NAMES = new Set([\n 'list_jobs',\n 'execute_job',\n 'get_job_status',\n 'register_job',\n 'remove_job',\n 'list_workflows',\n 'execute_workflow',\n 'get_workflow_status',\n 'register_workflow',\n 'remove_workflow',\n // Legacy hyphen names — accepted for back-compat with previously built bundles.\n 'list-jobs',\n 'execute-job',\n 'get-job-status',\n 'register-job',\n 'remove-job',\n 'list-workflows',\n 'execute-workflow',\n 'get-workflow-status',\n 'register-workflow',\n 'remove-workflow',\n]);\n\n/**\n * Extract schemas from a compiled server bundle.\n * Requires the bundle to export a FrontMcp-decorated class as default export\n * or a config object usable by connect().\n */\nexport async function extractSchemas(bundlePath: string): Promise<ExtractedSchema> {\n // Suppress @FrontMcp() decorator bootstrap — we only need metadata, not a running server\n const prev = process.env['FRONTMCP_SCHEMA_EXTRACT'];\n process.env['FRONTMCP_SCHEMA_EXTRACT'] = '1';\n\n let mod: Record<string, unknown>;\n try {\n mod = require(bundlePath);\n } finally {\n if (prev === undefined) {\n delete process.env['FRONTMCP_SCHEMA_EXTRACT'];\n } else {\n process.env['FRONTMCP_SCHEMA_EXTRACT'] = prev;\n }\n }\n\n const configOrClass = mod.default || mod;\n\n // Use @frontmcp/sdk connect() to boot in-memory client\n let connect: (config: unknown, options?: { mode?: string }) => Promise<unknown>;\n try {\n const sdk = require('@frontmcp/sdk');\n connect = sdk.connect || sdk.direct?.connect;\n if (!connect) {\n throw new Error('connect() not found in @frontmcp/sdk');\n }\n } catch {\n throw new Error(\n '@frontmcp/sdk is required for CLI schema extraction. Ensure it is installed.',\n );\n }\n\n const client = await connect(configOrClass, { mode: 'cli' }) as {\n listTools(): Promise<unknown>;\n listResources(): Promise<{ resources: Array<{ uri: string; name?: string; description?: string; mimeType?: string }> }>;\n listResourceTemplates?(): Promise<{ resourceTemplates: Array<{ uriTemplate: string; name?: string; description?: string }> }>;\n listPrompts(): Promise<{ prompts: Array<{ name: string; description?: string; arguments?: unknown[] }> }>;\n listJobs?(): Promise<{ jobs: Array<{ name: string; description?: string; inputSchema?: Record<string, unknown>; tags?: string[] }>; count: number }>;\n collectSkillAssets?(): Promise<{\n entries: Array<{\n skillName: string;\n baseDir?: string;\n instructionFile?: string;\n resources?: Record<string, string | undefined>;\n description?: string;\n tags?: string[];\n license?: string;\n }>;\n }>;\n close(): Promise<void>;\n };\n\n try {\n const [toolsRaw, resourcesResult, promptsResult] = await Promise.all([\n client.listTools().catch(() => []),\n client.listResources().catch(() => ({ resources: [] })),\n client.listPrompts().catch(() => ({ prompts: [] })),\n ]);\n\n let resourceTemplates: ExtractedResourceTemplate[] = [];\n if (client.listResourceTemplates) {\n try {\n const templatesResult = await client.listResourceTemplates();\n resourceTemplates = (templatesResult.resourceTemplates || []).map((t) => ({\n uriTemplate: t.uriTemplate,\n name: t.name || t.uriTemplate,\n description: t.description,\n }));\n } catch {\n // Resource templates not supported\n }\n }\n\n // DirectClient.listTools() returns FormattedTools (array) directly,\n // not { tools: [...] } like the raw MCP client\n const toolsList = Array.isArray(toolsRaw)\n ? toolsRaw as Array<{ name: string; description?: string; inputSchema?: unknown }>\n : ((toolsRaw as { tools?: unknown[] })?.tools || []) as Array<{ name: string; description?: string; inputSchema?: unknown }>;\n\n const tools: ExtractedTool[] = toolsList.map((t) => ({\n name: t.name,\n description: t.description || '',\n inputSchema: (t.inputSchema as Record<string, unknown>) || { type: 'object', properties: {} },\n }));\n\n const resources: ExtractedResource[] = (resourcesResult.resources || []).map((r) => ({\n uri: r.uri,\n name: r.name || r.uri,\n description: r.description,\n mimeType: r.mimeType,\n }));\n\n const prompts: ExtractedPrompt[] = (promptsResult.prompts || []).map((p) => ({\n name: p.name,\n description: p.description,\n arguments: p.arguments as ExtractedPrompt['arguments'],\n }));\n\n const toolNameSet = new Set(tools.map((t) => t.name));\n // SEP-2640: skills are exposed under the singular `skill://` URI scheme.\n const hasSkillsResources = resourceTemplates.some(\n (rt) => rt.uriTemplate.startsWith('skill://'),\n );\n const capabilities: ExtractedCapabilities = {\n skills: hasSkillsResources,\n jobs:\n toolNameSet.has('execute_job') ||\n toolNameSet.has('get_job_status') ||\n toolNameSet.has('execute-job') ||\n toolNameSet.has('get-job-status'),\n workflows:\n toolNameSet.has('execute_workflow') ||\n toolNameSet.has('get_workflow_status') ||\n toolNameSet.has('execute-workflow') ||\n toolNameSet.has('get-workflow-status'),\n };\n\n // Extract job schemas if jobs capability is available\n let jobs: ExtractedJob[] = [];\n if (capabilities.jobs && client.listJobs) {\n try {\n const jobsResult = await client.listJobs();\n jobs = (jobsResult.jobs || []).map((j) => ({\n name: j.name,\n description: j.description,\n inputSchema: j.inputSchema,\n tags: j.tags,\n }));\n } catch {\n // Jobs listing not available at build time\n }\n }\n\n // Collect skill file assets for copying to dist\n let skillAssets: ExtractedSkillAsset[] = [];\n if (capabilities.skills && client.collectSkillAssets) {\n try {\n const manifest = await client.collectSkillAssets();\n skillAssets = manifest.entries.map((e) => ({\n skillName: e.skillName,\n baseDir: e.baseDir,\n instructionFile: e.instructionFile,\n resourceDirs: e.resources as ExtractedSkillAsset['resourceDirs'],\n description: e.description,\n tags: e.tags,\n license: e.license,\n }));\n } catch {\n // Skill asset collection not available\n }\n }\n\n // Extract http.port from the @FrontMcp() decorator metadata. Returns\n // undefined when the entry is a plain config object (no decorator) or\n // when no port was declared — caller falls back to its own default.\n let httpPort: number | undefined;\n try {\n const sdk = require('@frontmcp/sdk') as { getDecoratorConfig?: (t: unknown) => Record<string, unknown> | undefined };\n const cfg = typeof sdk.getDecoratorConfig === 'function'\n ? sdk.getDecoratorConfig(configOrClass)\n : (configOrClass as Record<string, unknown> | undefined);\n const http = cfg?.['http'] as { port?: number } | undefined;\n if (http && typeof http.port === 'number') httpPort = http.port;\n } catch {\n // best-effort — manifest writer will fall back to its own default\n }\n\n return { tools, resources, resourceTemplates, prompts, jobs, capabilities, skillAssets, httpPort };\n } finally {\n await client.close().catch(() => {});\n }\n}\n"]}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Compose a SKILL.md document from `@Skill` decorator metadata + an optional
3
+ * body (typically the contents of the file referenced by `instructions.file`).
4
+ *
5
+ * Claude Code's filesystem-based skills loader discovers skills by reading
6
+ * `SKILL.md` frontmatter (`name`, `description`). A `@Skill`-decorated entry
7
+ * usually points `instructions.file` at a plain markdown body without
8
+ * frontmatter, so the install path needs to synthesize the frontmatter from
9
+ * the decorator metadata before writing the file under `.claude/skills/<name>/`.
10
+ *
11
+ * If the body already starts with a YAML frontmatter block we use it
12
+ * verbatim — the user is treated as the authoritative source.
13
+ */
14
+ export interface SkillFrontmatter {
15
+ name: string;
16
+ description?: string;
17
+ tags?: string[];
18
+ license?: string;
19
+ }
20
+ /**
21
+ * @returns the body with a `---` frontmatter block prepended, unless the
22
+ * body already starts with one (in which case the body is returned as-is).
23
+ */
24
+ export declare function composeSkillMd(meta: SkillFrontmatter, body: string): string;
25
+ export declare function hasFrontmatter(body: string): boolean;
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ /**
3
+ * Compose a SKILL.md document from `@Skill` decorator metadata + an optional
4
+ * body (typically the contents of the file referenced by `instructions.file`).
5
+ *
6
+ * Claude Code's filesystem-based skills loader discovers skills by reading
7
+ * `SKILL.md` frontmatter (`name`, `description`). A `@Skill`-decorated entry
8
+ * usually points `instructions.file` at a plain markdown body without
9
+ * frontmatter, so the install path needs to synthesize the frontmatter from
10
+ * the decorator metadata before writing the file under `.claude/skills/<name>/`.
11
+ *
12
+ * If the body already starts with a YAML frontmatter block we use it
13
+ * verbatim — the user is treated as the authoritative source.
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.composeSkillMd = composeSkillMd;
17
+ exports.hasFrontmatter = hasFrontmatter;
18
+ const FRONTMATTER_DELIMITER = '---';
19
+ /**
20
+ * @returns the body with a `---` frontmatter block prepended, unless the
21
+ * body already starts with one (in which case the body is returned as-is).
22
+ */
23
+ function composeSkillMd(meta, body) {
24
+ if (hasFrontmatter(body)) {
25
+ return body;
26
+ }
27
+ const lines = [FRONTMATTER_DELIMITER];
28
+ lines.push(`name: ${yamlScalar(meta.name)}`);
29
+ lines.push(`description: ${yamlScalar(meta.description ?? `${meta.name} skill`)}`);
30
+ if (meta.tags && meta.tags.length > 0) {
31
+ lines.push(`tags: [${meta.tags.map(yamlScalar).join(', ')}]`);
32
+ }
33
+ if (meta.license) {
34
+ lines.push(`license: ${yamlScalar(meta.license)}`);
35
+ }
36
+ lines.push(FRONTMATTER_DELIMITER);
37
+ lines.push('');
38
+ // Drop AT MOST a single optional leading newline — that's the separator
39
+ // between the (now-prepended) frontmatter and the body itself. Stripping
40
+ // all leading whitespace would eat intentional blank lines or indentation
41
+ // the author put at the top of the body, which is content, not noise.
42
+ const normalizedBody = body.replace(/^\r?\n/, '');
43
+ return lines.join('\n') + (normalizedBody.length > 0 ? normalizedBody : `# ${meta.name}\n`);
44
+ }
45
+ function hasFrontmatter(body) {
46
+ if (!body.startsWith(FRONTMATTER_DELIMITER))
47
+ return false;
48
+ const afterFirst = body.slice(FRONTMATTER_DELIMITER.length);
49
+ if (!afterFirst.startsWith('\n') && !afterFirst.startsWith('\r'))
50
+ return false;
51
+ return afterFirst.includes(`\n${FRONTMATTER_DELIMITER}`);
52
+ }
53
+ /**
54
+ * Quote scalars that contain YAML-significant characters; leave simple strings
55
+ * unquoted to keep the rendered frontmatter readable.
56
+ */
57
+ function yamlScalar(value) {
58
+ if (/[:#&*!|>'"%@`{}[\]\n\r\t]/.test(value) || value.startsWith('-') || value.startsWith('?')) {
59
+ return JSON.stringify(value);
60
+ }
61
+ return value;
62
+ }
63
+ //# sourceMappingURL=skill-md-compose.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-md-compose.js","sourceRoot":"","sources":["../../../../../../src/commands/build/exec/cli-runtime/skill-md-compose.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;GAYG;;AAeH,wCAqBC;AAED,wCAKC;AAlCD,MAAM,qBAAqB,GAAG,KAAK,CAAC;AAEpC;;;GAGG;AACH,SAAgB,cAAc,CAAC,IAAsB,EAAE,IAAY;IACjE,IAAI,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,KAAK,GAAa,CAAC,qBAAqB,CAAC,CAAC;IAChD,KAAK,CAAC,IAAI,CAAC,SAAS,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC7C,KAAK,CAAC,IAAI,CAAC,gBAAgB,UAAU,CAAC,IAAI,CAAC,WAAW,IAAI,GAAG,IAAI,CAAC,IAAI,QAAQ,CAAC,EAAE,CAAC,CAAC;IACnF,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtC,KAAK,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChE,CAAC;IACD,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,KAAK,CAAC,IAAI,CAAC,YAAY,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACrD,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IAClC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,wEAAwE;IACxE,yEAAyE;IACzE,0EAA0E;IAC1E,sEAAsE;IACtE,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAClD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC;AAC9F,CAAC;AAED,SAAgB,cAAc,CAAC,IAAY;IACzC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,qBAAqB,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1D,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC5D,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/E,OAAO,UAAU,CAAC,QAAQ,CAAC,KAAK,qBAAqB,EAAE,CAAC,CAAC;AAC3D,CAAC;AAED;;;GAGG;AACH,SAAS,UAAU,CAAC,KAAa;IAC/B,IAAI,2BAA2B,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC9F,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["/**\n * Compose a SKILL.md document from `@Skill` decorator metadata + an optional\n * body (typically the contents of the file referenced by `instructions.file`).\n *\n * Claude Code's filesystem-based skills loader discovers skills by reading\n * `SKILL.md` frontmatter (`name`, `description`). A `@Skill`-decorated entry\n * usually points `instructions.file` at a plain markdown body without\n * frontmatter, so the install path needs to synthesize the frontmatter from\n * the decorator metadata before writing the file under `.claude/skills/<name>/`.\n *\n * If the body already starts with a YAML frontmatter block we use it\n * verbatim — the user is treated as the authoritative source.\n */\n\nexport interface SkillFrontmatter {\n name: string;\n description?: string;\n tags?: string[];\n license?: string;\n}\n\nconst FRONTMATTER_DELIMITER = '---';\n\n/**\n * @returns the body with a `---` frontmatter block prepended, unless the\n * body already starts with one (in which case the body is returned as-is).\n */\nexport function composeSkillMd(meta: SkillFrontmatter, body: string): string {\n if (hasFrontmatter(body)) {\n return body;\n }\n const lines: string[] = [FRONTMATTER_DELIMITER];\n lines.push(`name: ${yamlScalar(meta.name)}`);\n lines.push(`description: ${yamlScalar(meta.description ?? `${meta.name} skill`)}`);\n if (meta.tags && meta.tags.length > 0) {\n lines.push(`tags: [${meta.tags.map(yamlScalar).join(', ')}]`);\n }\n if (meta.license) {\n lines.push(`license: ${yamlScalar(meta.license)}`);\n }\n lines.push(FRONTMATTER_DELIMITER);\n lines.push('');\n // Drop AT MOST a single optional leading newline — that's the separator\n // between the (now-prepended) frontmatter and the body itself. Stripping\n // all leading whitespace would eat intentional blank lines or indentation\n // the author put at the top of the body, which is content, not noise.\n const normalizedBody = body.replace(/^\\r?\\n/, '');\n return lines.join('\\n') + (normalizedBody.length > 0 ? normalizedBody : `# ${meta.name}\\n`);\n}\n\nexport function hasFrontmatter(body: string): boolean {\n if (!body.startsWith(FRONTMATTER_DELIMITER)) return false;\n const afterFirst = body.slice(FRONTMATTER_DELIMITER.length);\n if (!afterFirst.startsWith('\\n') && !afterFirst.startsWith('\\r')) return false;\n return afterFirst.includes(`\\n${FRONTMATTER_DELIMITER}`);\n}\n\n/**\n * Quote scalars that contain YAML-significant characters; leave simple strings\n * unquoted to keep the rendered frontmatter readable.\n */\nfunction yamlScalar(value: string): string {\n if (/[:#&*!|>'\"%@`{}[\\]\\n\\r\\t]/.test(value) || value.startsWith('-') || value.startsWith('?')) {\n return JSON.stringify(value);\n }\n return value;\n}\n"]}
@@ -167,6 +167,13 @@ async function buildExec(opts) {
167
167
  if (copiedCount > 0) {
168
168
  console.log(`${(0, colors_1.c)('green', '[build:exec]')} copied ${copiedCount} skill content file(s) to _skills/`);
169
169
  }
170
+ // bin-meta.json (issue #411) — sidecar carrying everything the per-bin
171
+ // `<bin> install -p claude|codex` needs without re-running schema
172
+ // extraction at install time. The bin-runtime install command reads
173
+ // this file + the staged _skills/ directory and hands the result to the
174
+ // shared plugin-emitter.
175
+ const { writeBinMeta } = await import('./bin-meta.js');
176
+ await writeBinMeta(outDir, config, schema);
170
177
  // Log tool name conflicts
171
178
  const cliConfig = config.cli || { enabled: true };
172
179
  const excludeTools = cliConfig.excludeTools || [];
@@ -191,6 +198,21 @@ async function buildExec(opts) {
191
198
  fs.writeFileSync(path.join(tempDir, 'credential-store.js'), generateCredentialStoreSource(config.name));
192
199
  fs.writeFileSync(path.join(tempDir, 'oauth-helper.js'), generateOAuthHelperSource(config.name));
193
200
  fs.writeFileSync(path.join(tempDir, 'daemon-client.js'), generateDaemonClientSource());
201
+ // Issue #411 — copy the compiled plugin-emitter so the per-bin
202
+ // `<bin> install -p claude|codex` can `require('./plugin-emitter')`.
203
+ // esbuild then bundles it (and its `@frontmcp/utils` deps) into the
204
+ // final CLI bundle. The emitter imports `./skill-md-compose`, so the
205
+ // sibling file has to land in __cli_temp/ too — otherwise the esbuild
206
+ // step that produces the bin's CLI bundle fails with a missing-module
207
+ // error. Tolerate absence in test/source-only contexts.
208
+ const pluginEmitterSrc = path.join(__dirname, 'cli-runtime', 'plugin-emitter.js');
209
+ if (fs.existsSync(pluginEmitterSrc)) {
210
+ fs.copyFileSync(pluginEmitterSrc, path.join(tempDir, 'plugin-emitter.js'));
211
+ }
212
+ const skillMdComposeSrc = path.join(__dirname, 'cli-runtime', 'skill-md-compose.js');
213
+ if (fs.existsSync(skillMdComposeSrc)) {
214
+ fs.copyFileSync(skillMdComposeSrc, path.join(tempDir, 'skill-md-compose.js'));
215
+ }
194
216
  // Generate CLI entry
195
217
  const cliEntrySource = generateCliEntry({
196
218
  appName: config.name,
@@ -289,6 +311,10 @@ async function buildExec(opts) {
289
311
  `${config.name}-bin`,
290
312
  `${config.name}-cli-bin`,
291
313
  '_skills',
314
+ // bin-meta.json (issue #411) — the bin's runtime install command
315
+ // reads this sidecar at execution time, so the cleanup pass MUST NOT
316
+ // delete it. Whitelisted alongside the other emitted artifacts.
317
+ 'bin-meta.json',
292
318
  ]);
293
319
  const allFiles = fs.readdirSync(outDir);
294
320
  let cleaned = 0;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/commands/build/exec/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * buildExec() orchestrator — produces a distributable bundle from a FrontMCP app.\n *\n * Output (server-only mode):\n * dist/{name}.bundle.js — esbuild single-file bundle\n * dist/{name}.manifest.json — app metadata (runtime reqs, setup questions)\n * dist/{name} — bash runner script\n * dist/install-{name}.sh — bash installer script\n *\n * Output (CLI mode, --cli flag):\n * All of the above, plus:\n * dist/{name}-cli.bundle.js — CLI executable bundle (commander.js)\n * dist/{name} — bash runner dispatches to CLI bundle\n */\n\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport { type ParsedArgs } from '../../../core/args';\nimport { c } from '../../../core/colors';\nimport { resolveEntry } from '../../../shared/fs';\nimport { loadExecConfig, normalizeConfig } from './config';\nimport { bundleWithEsbuild, formatSize } from './esbuild-bundler';\nimport { generateManifest } from './manifest';\nimport { generateRunnerScript } from './runner-script';\nimport { generateInstallerScript } from './installer-script';\nimport { validateStepGraph } from './setup';\nimport { ensureDir, fileExists, runCmd } from '@frontmcp/utils';\nimport { REQUIRED_DECORATOR_FIELDS } from '../../../core/tsconfig';\n\nexport async function buildExec(\n opts: ParsedArgs & {\n cli?: boolean;\n sea?: boolean;\n execOverrides?: {\n storage?: { type: 'sqlite' | 'redis' | 'none'; required?: boolean };\n cli?: { outputDefault?: 'text' | 'json'; description?: string; authRequired?: boolean };\n // #365 round-3 — top-level `nodeVersion` from new-shape frontmcp.config\n // gets forwarded here because the legacy `loadExecConfig` doesn't read\n // it from .ts files (and never read top-level nodeVersion at all in\n // the legacy shape).\n nodeVersion?: string;\n };\n },\n): Promise<void> {\n const cwd = process.cwd();\n const outDir = path.resolve(cwd, opts.outDir || 'dist');\n\n console.log(`${c('cyan', '[build:exec]')} Building executable bundle...`);\n\n // 1. Load config (and merge in overrides forwarded from frontmcp.config —\n // `build.storage`, `deployments[].cli.outputDefault`, etc.)\n const rawConfig = await loadExecConfig(cwd);\n if (opts.execOverrides) {\n if (opts.execOverrides.storage && !rawConfig.storage) {\n rawConfig.storage = opts.execOverrides.storage;\n }\n if (opts.execOverrides.cli) {\n const existing = rawConfig.cli;\n // CliConfig requires `enabled: boolean`; preserve any existing value or\n // default to true (we only get here when CLI mode is being configured).\n rawConfig.cli = {\n enabled: existing?.enabled ?? true,\n ...existing,\n ...opts.execOverrides.cli,\n };\n }\n // #365 round-3 — apply only when the legacy loader didn't already pick up\n // a value (the legacy loader can read it from .js/.json/.cjs/.mjs configs;\n // the new-shape forward fills the .ts gap).\n if (opts.execOverrides.nodeVersion && !rawConfig.nodeVersion) {\n rawConfig.nodeVersion = opts.execOverrides.nodeVersion;\n }\n }\n const config = normalizeConfig(rawConfig);\n const cliEnabled = opts.cli || config.cli?.enabled;\n const seaEnabled = opts.sea || config.sea?.enabled;\n\n console.log(`${c('cyan', '[build:exec]')} name: ${config.name}`);\n console.log(`${c('cyan', '[build:exec]')} version: ${config.version}`);\n if (cliEnabled) {\n console.log(`${c('cyan', '[build:exec]')} CLI mode: enabled`);\n }\n if (seaEnabled) {\n console.log(`${c('cyan', '[build:exec]')} SEA mode: enabled (single executable)`);\n }\n\n // 2. Resolve entry\n const entry = await resolveEntry(cwd, config.entry || opts.entry);\n console.log(`${c('cyan', '[build:exec]')} entry: ${path.relative(cwd, entry)}`);\n\n // 3. Validate setup graph if present\n if (config.setup?.steps) {\n console.log(\n `${c('cyan', '[build:exec]')} validating setup questionnaire (${config.setup.steps.length} steps)...`,\n );\n const errors = validateStepGraph(config.setup.steps);\n const realErrors = errors.filter((e) => !e.startsWith('Warning:'));\n const warnings = errors.filter((e) => e.startsWith('Warning:'));\n\n for (const w of warnings) {\n console.log(`${c('yellow', '[build:exec]')} ${w}`);\n }\n if (realErrors.length > 0) {\n for (const e of realErrors) {\n console.error(`${c('red', '[build:exec]')} ${e}`);\n }\n throw new Error('Setup questionnaire has validation errors. Fix them before building.');\n }\n }\n\n // 4. Compile TypeScript\n console.log(`${c('cyan', '[build:exec]')} compiling TypeScript...`);\n await ensureDir(outDir);\n\n const tsconfigPath = path.join(cwd, 'tsconfig.json');\n const hasTsconfig = await fileExists(tsconfigPath);\n const tscArgs: string[] = ['-y', 'tsc'];\n\n if (hasTsconfig) {\n tscArgs.push('--project', tsconfigPath);\n } else {\n tscArgs.push(entry);\n tscArgs.push('--rootDir', path.dirname(entry));\n tscArgs.push('--experimentalDecorators', '--emitDecoratorMetadata');\n tscArgs.push('--target', REQUIRED_DECORATOR_FIELDS.target);\n }\n\n tscArgs.push('--module', 'commonjs');\n tscArgs.push('--outDir', outDir);\n tscArgs.push('--skipLibCheck');\n\n await runCmd('npx', tscArgs);\n console.log(`${c('green', '[build:exec]')} TypeScript compiled.`);\n\n // 5. Bundle with esbuild\n console.log(`${c('cyan', '[build:exec]')} bundling with esbuild...`);\n const compiledEntry = path.join(\n outDir,\n path.basename(entry).replace(/\\.tsx?$/, '.js'),\n );\n\n // Always build non-self-contained first (schema extraction needs host SDK)\n const bundleResult = await bundleWithEsbuild(compiledEntry, outDir, config);\n console.log(\n `${c('green', '[build:exec]')} bundle created: ${path.relative(cwd, bundleResult.bundlePath)} (${formatSize(bundleResult.bundleSize)})`,\n );\n\n // 6. Extract schema once and reuse for both the manifest port resolution\n // (#371) and the CLI command generation (when cliEnabled). Schema\n // extraction loads the user's bundle and boots an in-memory client\n // (~200ms); running it twice on every --target cli build added up.\n const bundleFilename = `${config.name}.bundle.js`;\n const { extractSchemas } = await import('./cli-runtime/schema-extractor.js');\n let extractedSchema: Awaited<ReturnType<typeof extractSchemas>> | undefined;\n try {\n extractedSchema = await extractSchemas(bundleResult.bundlePath);\n } catch (err) {\n if (cliEnabled) {\n // CLI builds genuinely need the schema — fail loud.\n throw err;\n }\n // For --target node we only need httpPort from the schema; falling back\n // to the manifest's default precedence chain is acceptable.\n }\n\n // 7. Generate manifest with extracted decorator port + per-deployment cli config\n const manifest = generateManifest(config, bundleFilename, {\n target: cliEnabled ? 'cli' : 'node',\n decoratorHttpPort: extractedSchema?.httpPort,\n outputDefault: config.cli?.outputDefault as 'text' | 'json' | undefined,\n });\n\n // 7. CLI build step (if enabled)\n let cliBundlePath: string | undefined;\n if (cliEnabled) {\n console.log(`${c('cyan', '[build:exec]')} extracting schemas for CLI...`);\n\n const { SYSTEM_TOOL_NAMES } = await import('./cli-runtime/schema-extractor.js');\n const { generateCliEntry, resolveToolCommandName } = await import('./cli-runtime/generate-cli-entry.js');\n const { generateOutputFormatterSource } = await import('./cli-runtime/output-formatter.js');\n const { generateSessionManagerSource } = await import('./cli-runtime/session-manager.js');\n const { generateCredentialStoreSource } = await import('./cli-runtime/credential-store.js');\n const { generateOAuthHelperSource } = await import('./cli-runtime/oauth-helper.js');\n const { generateDaemonClientSource } = await import('./cli-runtime/daemon-client.js');\n const { bundleCliWithEsbuild } = await import('./cli-runtime/cli-bundler.js');\n\n // Reuse the schema extracted in step 6 (single extraction per build).\n // The non-null assertion is safe — we threw above if cliEnabled and\n // extraction failed, so by here `extractedSchema` is always defined.\n const schema = extractedSchema!;\n\n const capabilities = schema.capabilities;\n const userToolCount = schema.tools.filter(\n (t) => !SYSTEM_TOOL_NAMES.has(t.name),\n ).length;\n\n console.log(\n `${c('cyan', '[build:exec]')} extracted: ${schema.tools.length} tools (${userToolCount} user), ${schema.resources.length} resources, ${schema.resourceTemplates.length} templates, ${schema.prompts.length} prompts`,\n );\n if (capabilities.skills) console.log(`${c('cyan', '[build:exec]')} capability: skills`);\n if (capabilities.jobs) console.log(`${c('cyan', '[build:exec]')} capability: jobs`);\n if (capabilities.workflows) console.log(`${c('cyan', '[build:exec]')} capability: workflows`);\n\n // Copy skill content files via shared helper (flat _skills/ layout).\n const { copySkillAssets } = await import('./skill-assets.js');\n const { copiedCount } = copySkillAssets(outDir, schema.skillAssets);\n if (copiedCount > 0) {\n console.log(`${c('green', '[build:exec]')} copied ${copiedCount} skill content file(s) to _skills/`);\n }\n\n // Log tool name conflicts\n const cliConfig = config.cli || { enabled: true };\n const excludeTools = cliConfig.excludeTools || [];\n schema.tools\n .filter((t) => !excludeTools.includes(t.name))\n .forEach((t) => {\n const { wasRenamed, cmdName } = resolveToolCommandName(t.name);\n if (wasRenamed) {\n console.log(\n `${c('yellow', '[build:exec]')} Tool \"${t.name}\" conflicts with built-in command, mapped to \"${cmdName}\"`,\n );\n }\n });\n\n // Generate runtime modules\n const outputDefault = cliConfig.outputDefault || 'text';\n const authRequired = cliConfig.authRequired ?? false;\n const nativeDeps = cliConfig.nativeDeps || {};\n const oauthConfig = cliConfig.oauth;\n\n // Write runtime modules to temp files for bundling\n const tempDir = path.join(outDir, '__cli_temp');\n fs.mkdirSync(tempDir, { recursive: true });\n\n fs.writeFileSync(\n path.join(tempDir, 'output-formatter.js'),\n generateOutputFormatterSource(),\n );\n fs.writeFileSync(\n path.join(tempDir, 'session-manager.js'),\n generateSessionManagerSource(config.name),\n );\n fs.writeFileSync(\n path.join(tempDir, 'credential-store.js'),\n generateCredentialStoreSource(config.name),\n );\n fs.writeFileSync(\n path.join(tempDir, 'oauth-helper.js'),\n generateOAuthHelperSource(config.name),\n );\n fs.writeFileSync(\n path.join(tempDir, 'daemon-client.js'),\n generateDaemonClientSource(),\n );\n\n // Generate CLI entry\n const cliEntrySource = generateCliEntry({\n appName: config.name,\n appVersion: config.version || '1.0.0',\n description: cliConfig.description || `${config.name} CLI`,\n serverBundleFilename: bundleFilename,\n outputDefault,\n authRequired,\n excludeTools,\n nativeDeps,\n schema,\n oauthConfig,\n selfContained: !!seaEnabled,\n });\n\n const cliEntryPath = path.join(tempDir, 'cli-entry.js');\n fs.writeFileSync(cliEntryPath, cliEntrySource);\n\n // Bundle CLI\n console.log(`${c('cyan', '[build:exec]')} bundling CLI...`);\n const cliResult = await bundleCliWithEsbuild(cliEntryPath, outDir, config, {\n selfContained: !!seaEnabled,\n });\n cliBundlePath = cliResult.bundlePath;\n console.log(\n `${c('green', '[build:exec]')} CLI bundle: ${path.relative(cwd, cliResult.bundlePath)} (${formatSize(cliResult.bundleSize)})`,\n );\n\n // Clean temp\n fs.rmSync(tempDir, { recursive: true, force: true });\n\n // Extend manifest with CLI metadata\n manifest.cli = {\n enabled: true,\n cliBundle: `${config.name}-cli.bundle.js`,\n outputDefault,\n authRequired,\n toolCount: userToolCount,\n resourceCount: schema.resources.length,\n templateCount: schema.resourceTemplates.length,\n promptCount: schema.prompts.length,\n oauthEnabled: !!oauthConfig,\n skillsEnabled: capabilities.skills || undefined,\n jobsEnabled: capabilities.jobs || undefined,\n workflowsEnabled: capabilities.workflows || undefined,\n };\n }\n\n // 8. Build SEA binaries if enabled\n //\n // For --target cli (cliEnabled === true), the runner script `exec`s only\n // the CLI binary — the standalone server SEA is dead weight (~114 MB, see\n // issue #373). Skip the server-SEA pass entirely in that mode. For\n // --target node (cliEnabled === false), build only the server SEA.\n let seaServerResult: { executablePath: string; executableSize: number } | undefined;\n let seaCliResult: { executablePath: string; executableSize: number } | undefined;\n if (seaEnabled) {\n const { buildSea } = await import('./sea-builder.js');\n\n if (!cliEnabled) {\n // Server-only SEA path (--target node): rebuild bundle as self-contained\n // (inlines all deps) and produce ${name}-bin.\n const seaTempName = `${config.name}.sea-temp`;\n console.log(`${c('cyan', '[build:sea]')} rebuilding server bundle (self-contained)...`);\n const seaBundle = await bundleWithEsbuild(compiledEntry, outDir, config, {\n selfContained: true,\n outputName: seaTempName,\n });\n\n console.log(`${c('cyan', '[build:sea]')} building server SEA binary...`);\n seaServerResult = await buildSea(seaBundle.bundlePath, outDir, config.name);\n fs.unlinkSync(seaBundle.bundlePath);\n console.log(\n `${c('green', '[build:sea]')} server binary: ${path.relative(cwd, seaServerResult.executablePath)} (${formatSize(seaServerResult.executableSize)})`,\n );\n }\n\n if (cliBundlePath) {\n console.log(`${c('cyan', '[build:sea]')} building CLI SEA binary...`);\n seaCliResult = await buildSea(cliBundlePath, outDir, `${config.name}-cli`);\n console.log(\n `${c('green', '[build:sea]')} CLI binary: ${path.relative(cwd, seaCliResult.executablePath)} (${formatSize(seaCliResult.executableSize)})`,\n );\n }\n }\n\n // 9. Write manifest\n const manifestPath = path.join(outDir, `${config.name}.manifest.json`);\n fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), 'utf-8');\n console.log(\n `${c('green', '[build:exec]')} manifest: ${path.relative(cwd, manifestPath)}`,\n );\n\n // 10. Generate runner script (dispatches to CLI bundle or SEA binary)\n const runnerContent = generateRunnerScript(config, !!cliEnabled, !!seaEnabled);\n const runnerPath = path.join(outDir, config.name);\n fs.writeFileSync(runnerPath, runnerContent, { mode: 0o755 });\n console.log(\n `${c('green', '[build:exec]')} runner: ${path.relative(cwd, runnerPath)}`,\n );\n\n // 10. Generate installer script\n const installerContent = generateInstallerScript(config, {\n target: cliEnabled ? 'cli' : 'node',\n seaEnabled: !!seaEnabled,\n });\n const installerPath = path.join(outDir, `install-${config.name}.sh`);\n fs.writeFileSync(installerPath, installerContent, { mode: 0o755 });\n console.log(\n `${c('green', '[build:exec]')} installer: ${path.relative(cwd, installerPath)}`,\n );\n\n // 12. Clean up intermediate compiled files\n const keepFiles = new Set([\n `${config.name}.bundle.js`,\n `${config.name}-cli.bundle.js`,\n `${config.name}.manifest.json`,\n config.name,\n `install-${config.name}.sh`,\n `${config.name}-bin`,\n `${config.name}-cli-bin`,\n '_skills',\n ]);\n\n const allFiles = fs.readdirSync(outDir);\n let cleaned = 0;\n for (const file of allFiles) {\n if (!keepFiles.has(file)) {\n const filePath = path.join(outDir, file);\n const stat = fs.statSync(filePath);\n // Only clean intermediate compiled files; preserve .md and _skills/ directory\n if (stat.isFile() && !file.endsWith('.md')) {\n fs.unlinkSync(filePath);\n cleaned++;\n }\n }\n }\n if (cleaned > 0) {\n console.log(\n `${c('gray', '[build:exec]')} cleaned ${cleaned} intermediate file(s)`,\n );\n }\n\n // 13. Print summary\n console.log(`\\n${c('green', 'Executable build completed.')}`);\n console.log(`\\n${c('bold', 'Output:')}`);\n console.log(` ${path.relative(cwd, bundleResult.bundlePath)} ${c('gray', `(${formatSize(bundleResult.bundleSize)})`)}`);\n if (cliBundlePath) {\n const cliStat = fs.statSync(cliBundlePath);\n console.log(` ${path.relative(cwd, cliBundlePath)} ${c('gray', `(${formatSize(cliStat.size)})`)}`);\n }\n if (seaServerResult) {\n console.log(` ${path.relative(cwd, seaServerResult.executablePath)} ${c('gray', `(${formatSize(seaServerResult.executableSize)})`)}`);\n }\n if (seaCliResult) {\n console.log(` ${path.relative(cwd, seaCliResult.executablePath)} ${c('gray', `(${formatSize(seaCliResult.executableSize)})`)}`);\n }\n console.log(` ${path.relative(cwd, manifestPath)}`);\n console.log(` ${path.relative(cwd, runnerPath)}`);\n console.log(` ${path.relative(cwd, installerPath)}`);\n\n if (cliEnabled) {\n console.log(`\\n${c('gray', 'Run the CLI:')} ./${path.relative(cwd, runnerPath)} --help`);\n console.log(`${c('gray', 'Start server:')} ./${path.relative(cwd, runnerPath)} serve`);\n } else {\n console.log(`\\n${c('gray', 'Run the server:')} ./${path.relative(cwd, runnerPath)}`);\n }\n if (seaServerResult || seaCliResult) {\n console.log(`\\n${c('yellow', 'Note:')} SEA binaries are native executables. Run directly (not via bash).`);\n }\n console.log(`${c('gray', 'Install to system:')} bash ./${path.relative(cwd, installerPath)}`);\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/commands/build/exec/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * buildExec() orchestrator — produces a distributable bundle from a FrontMCP app.\n *\n * Output (server-only mode):\n * dist/{name}.bundle.js — esbuild single-file bundle\n * dist/{name}.manifest.json — app metadata (runtime reqs, setup questions)\n * dist/{name} — bash runner script\n * dist/install-{name}.sh — bash installer script\n *\n * Output (CLI mode, --cli flag):\n * All of the above, plus:\n * dist/{name}-cli.bundle.js — CLI executable bundle (commander.js)\n * dist/{name} — bash runner dispatches to CLI bundle\n */\n\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport { type ParsedArgs } from '../../../core/args';\nimport { c } from '../../../core/colors';\nimport { resolveEntry } from '../../../shared/fs';\nimport { loadExecConfig, normalizeConfig } from './config';\nimport { bundleWithEsbuild, formatSize } from './esbuild-bundler';\nimport { generateManifest } from './manifest';\nimport { generateRunnerScript } from './runner-script';\nimport { generateInstallerScript } from './installer-script';\nimport { validateStepGraph } from './setup';\nimport { ensureDir, fileExists, runCmd } from '@frontmcp/utils';\nimport { REQUIRED_DECORATOR_FIELDS } from '../../../core/tsconfig';\n\nexport async function buildExec(\n opts: ParsedArgs & {\n cli?: boolean;\n sea?: boolean;\n execOverrides?: {\n storage?: { type: 'sqlite' | 'redis' | 'none'; required?: boolean };\n cli?: { outputDefault?: 'text' | 'json'; description?: string; authRequired?: boolean };\n // #365 round-3 — top-level `nodeVersion` from new-shape frontmcp.config\n // gets forwarded here because the legacy `loadExecConfig` doesn't read\n // it from .ts files (and never read top-level nodeVersion at all in\n // the legacy shape).\n nodeVersion?: string;\n };\n },\n): Promise<void> {\n const cwd = process.cwd();\n const outDir = path.resolve(cwd, opts.outDir || 'dist');\n\n console.log(`${c('cyan', '[build:exec]')} Building executable bundle...`);\n\n // 1. Load config (and merge in overrides forwarded from frontmcp.config —\n // `build.storage`, `deployments[].cli.outputDefault`, etc.)\n const rawConfig = await loadExecConfig(cwd);\n if (opts.execOverrides) {\n if (opts.execOverrides.storage && !rawConfig.storage) {\n rawConfig.storage = opts.execOverrides.storage;\n }\n if (opts.execOverrides.cli) {\n const existing = rawConfig.cli;\n // CliConfig requires `enabled: boolean`; preserve any existing value or\n // default to true (we only get here when CLI mode is being configured).\n rawConfig.cli = {\n enabled: existing?.enabled ?? true,\n ...existing,\n ...opts.execOverrides.cli,\n };\n }\n // #365 round-3 — apply only when the legacy loader didn't already pick up\n // a value (the legacy loader can read it from .js/.json/.cjs/.mjs configs;\n // the new-shape forward fills the .ts gap).\n if (opts.execOverrides.nodeVersion && !rawConfig.nodeVersion) {\n rawConfig.nodeVersion = opts.execOverrides.nodeVersion;\n }\n }\n const config = normalizeConfig(rawConfig);\n const cliEnabled = opts.cli || config.cli?.enabled;\n const seaEnabled = opts.sea || config.sea?.enabled;\n\n console.log(`${c('cyan', '[build:exec]')} name: ${config.name}`);\n console.log(`${c('cyan', '[build:exec]')} version: ${config.version}`);\n if (cliEnabled) {\n console.log(`${c('cyan', '[build:exec]')} CLI mode: enabled`);\n }\n if (seaEnabled) {\n console.log(`${c('cyan', '[build:exec]')} SEA mode: enabled (single executable)`);\n }\n\n // 2. Resolve entry\n const entry = await resolveEntry(cwd, config.entry || opts.entry);\n console.log(`${c('cyan', '[build:exec]')} entry: ${path.relative(cwd, entry)}`);\n\n // 3. Validate setup graph if present\n if (config.setup?.steps) {\n console.log(\n `${c('cyan', '[build:exec]')} validating setup questionnaire (${config.setup.steps.length} steps)...`,\n );\n const errors = validateStepGraph(config.setup.steps);\n const realErrors = errors.filter((e) => !e.startsWith('Warning:'));\n const warnings = errors.filter((e) => e.startsWith('Warning:'));\n\n for (const w of warnings) {\n console.log(`${c('yellow', '[build:exec]')} ${w}`);\n }\n if (realErrors.length > 0) {\n for (const e of realErrors) {\n console.error(`${c('red', '[build:exec]')} ${e}`);\n }\n throw new Error('Setup questionnaire has validation errors. Fix them before building.');\n }\n }\n\n // 4. Compile TypeScript\n console.log(`${c('cyan', '[build:exec]')} compiling TypeScript...`);\n await ensureDir(outDir);\n\n const tsconfigPath = path.join(cwd, 'tsconfig.json');\n const hasTsconfig = await fileExists(tsconfigPath);\n const tscArgs: string[] = ['-y', 'tsc'];\n\n if (hasTsconfig) {\n tscArgs.push('--project', tsconfigPath);\n } else {\n tscArgs.push(entry);\n tscArgs.push('--rootDir', path.dirname(entry));\n tscArgs.push('--experimentalDecorators', '--emitDecoratorMetadata');\n tscArgs.push('--target', REQUIRED_DECORATOR_FIELDS.target);\n }\n\n tscArgs.push('--module', 'commonjs');\n tscArgs.push('--outDir', outDir);\n tscArgs.push('--skipLibCheck');\n\n await runCmd('npx', tscArgs);\n console.log(`${c('green', '[build:exec]')} TypeScript compiled.`);\n\n // 5. Bundle with esbuild\n console.log(`${c('cyan', '[build:exec]')} bundling with esbuild...`);\n const compiledEntry = path.join(\n outDir,\n path.basename(entry).replace(/\\.tsx?$/, '.js'),\n );\n\n // Always build non-self-contained first (schema extraction needs host SDK)\n const bundleResult = await bundleWithEsbuild(compiledEntry, outDir, config);\n console.log(\n `${c('green', '[build:exec]')} bundle created: ${path.relative(cwd, bundleResult.bundlePath)} (${formatSize(bundleResult.bundleSize)})`,\n );\n\n // 6. Extract schema once and reuse for both the manifest port resolution\n // (#371) and the CLI command generation (when cliEnabled). Schema\n // extraction loads the user's bundle and boots an in-memory client\n // (~200ms); running it twice on every --target cli build added up.\n const bundleFilename = `${config.name}.bundle.js`;\n const { extractSchemas } = await import('./cli-runtime/schema-extractor.js');\n let extractedSchema: Awaited<ReturnType<typeof extractSchemas>> | undefined;\n try {\n extractedSchema = await extractSchemas(bundleResult.bundlePath);\n } catch (err) {\n if (cliEnabled) {\n // CLI builds genuinely need the schema — fail loud.\n throw err;\n }\n // For --target node we only need httpPort from the schema; falling back\n // to the manifest's default precedence chain is acceptable.\n }\n\n // 7. Generate manifest with extracted decorator port + per-deployment cli config\n const manifest = generateManifest(config, bundleFilename, {\n target: cliEnabled ? 'cli' : 'node',\n decoratorHttpPort: extractedSchema?.httpPort,\n outputDefault: config.cli?.outputDefault as 'text' | 'json' | undefined,\n });\n\n // 7. CLI build step (if enabled)\n let cliBundlePath: string | undefined;\n if (cliEnabled) {\n console.log(`${c('cyan', '[build:exec]')} extracting schemas for CLI...`);\n\n const { SYSTEM_TOOL_NAMES } = await import('./cli-runtime/schema-extractor.js');\n const { generateCliEntry, resolveToolCommandName } = await import('./cli-runtime/generate-cli-entry.js');\n const { generateOutputFormatterSource } = await import('./cli-runtime/output-formatter.js');\n const { generateSessionManagerSource } = await import('./cli-runtime/session-manager.js');\n const { generateCredentialStoreSource } = await import('./cli-runtime/credential-store.js');\n const { generateOAuthHelperSource } = await import('./cli-runtime/oauth-helper.js');\n const { generateDaemonClientSource } = await import('./cli-runtime/daemon-client.js');\n const { bundleCliWithEsbuild } = await import('./cli-runtime/cli-bundler.js');\n\n // Reuse the schema extracted in step 6 (single extraction per build).\n // The non-null assertion is safe — we threw above if cliEnabled and\n // extraction failed, so by here `extractedSchema` is always defined.\n const schema = extractedSchema!;\n\n const capabilities = schema.capabilities;\n const userToolCount = schema.tools.filter(\n (t) => !SYSTEM_TOOL_NAMES.has(t.name),\n ).length;\n\n console.log(\n `${c('cyan', '[build:exec]')} extracted: ${schema.tools.length} tools (${userToolCount} user), ${schema.resources.length} resources, ${schema.resourceTemplates.length} templates, ${schema.prompts.length} prompts`,\n );\n if (capabilities.skills) console.log(`${c('cyan', '[build:exec]')} capability: skills`);\n if (capabilities.jobs) console.log(`${c('cyan', '[build:exec]')} capability: jobs`);\n if (capabilities.workflows) console.log(`${c('cyan', '[build:exec]')} capability: workflows`);\n\n // Copy skill content files via shared helper (flat _skills/ layout).\n const { copySkillAssets } = await import('./skill-assets.js');\n const { copiedCount } = copySkillAssets(outDir, schema.skillAssets);\n if (copiedCount > 0) {\n console.log(`${c('green', '[build:exec]')} copied ${copiedCount} skill content file(s) to _skills/`);\n }\n\n // bin-meta.json (issue #411) — sidecar carrying everything the per-bin\n // `<bin> install -p claude|codex` needs without re-running schema\n // extraction at install time. The bin-runtime install command reads\n // this file + the staged _skills/ directory and hands the result to the\n // shared plugin-emitter.\n const { writeBinMeta } = await import('./bin-meta.js');\n await writeBinMeta(outDir, config, schema);\n\n // Log tool name conflicts\n const cliConfig = config.cli || { enabled: true };\n const excludeTools = cliConfig.excludeTools || [];\n schema.tools\n .filter((t) => !excludeTools.includes(t.name))\n .forEach((t) => {\n const { wasRenamed, cmdName } = resolveToolCommandName(t.name);\n if (wasRenamed) {\n console.log(\n `${c('yellow', '[build:exec]')} Tool \"${t.name}\" conflicts with built-in command, mapped to \"${cmdName}\"`,\n );\n }\n });\n\n // Generate runtime modules\n const outputDefault = cliConfig.outputDefault || 'text';\n const authRequired = cliConfig.authRequired ?? false;\n const nativeDeps = cliConfig.nativeDeps || {};\n const oauthConfig = cliConfig.oauth;\n\n // Write runtime modules to temp files for bundling\n const tempDir = path.join(outDir, '__cli_temp');\n fs.mkdirSync(tempDir, { recursive: true });\n\n fs.writeFileSync(\n path.join(tempDir, 'output-formatter.js'),\n generateOutputFormatterSource(),\n );\n fs.writeFileSync(\n path.join(tempDir, 'session-manager.js'),\n generateSessionManagerSource(config.name),\n );\n fs.writeFileSync(\n path.join(tempDir, 'credential-store.js'),\n generateCredentialStoreSource(config.name),\n );\n fs.writeFileSync(\n path.join(tempDir, 'oauth-helper.js'),\n generateOAuthHelperSource(config.name),\n );\n fs.writeFileSync(\n path.join(tempDir, 'daemon-client.js'),\n generateDaemonClientSource(),\n );\n\n // Issue #411 — copy the compiled plugin-emitter so the per-bin\n // `<bin> install -p claude|codex` can `require('./plugin-emitter')`.\n // esbuild then bundles it (and its `@frontmcp/utils` deps) into the\n // final CLI bundle. The emitter imports `./skill-md-compose`, so the\n // sibling file has to land in __cli_temp/ too — otherwise the esbuild\n // step that produces the bin's CLI bundle fails with a missing-module\n // error. Tolerate absence in test/source-only contexts.\n const pluginEmitterSrc = path.join(__dirname, 'cli-runtime', 'plugin-emitter.js');\n if (fs.existsSync(pluginEmitterSrc)) {\n fs.copyFileSync(pluginEmitterSrc, path.join(tempDir, 'plugin-emitter.js'));\n }\n const skillMdComposeSrc = path.join(__dirname, 'cli-runtime', 'skill-md-compose.js');\n if (fs.existsSync(skillMdComposeSrc)) {\n fs.copyFileSync(skillMdComposeSrc, path.join(tempDir, 'skill-md-compose.js'));\n }\n\n // Generate CLI entry\n const cliEntrySource = generateCliEntry({\n appName: config.name,\n appVersion: config.version || '1.0.0',\n description: cliConfig.description || `${config.name} CLI`,\n serverBundleFilename: bundleFilename,\n outputDefault,\n authRequired,\n excludeTools,\n nativeDeps,\n schema,\n oauthConfig,\n selfContained: !!seaEnabled,\n });\n\n const cliEntryPath = path.join(tempDir, 'cli-entry.js');\n fs.writeFileSync(cliEntryPath, cliEntrySource);\n\n // Bundle CLI\n console.log(`${c('cyan', '[build:exec]')} bundling CLI...`);\n const cliResult = await bundleCliWithEsbuild(cliEntryPath, outDir, config, {\n selfContained: !!seaEnabled,\n });\n cliBundlePath = cliResult.bundlePath;\n console.log(\n `${c('green', '[build:exec]')} CLI bundle: ${path.relative(cwd, cliResult.bundlePath)} (${formatSize(cliResult.bundleSize)})`,\n );\n\n // Clean temp\n fs.rmSync(tempDir, { recursive: true, force: true });\n\n // Extend manifest with CLI metadata\n manifest.cli = {\n enabled: true,\n cliBundle: `${config.name}-cli.bundle.js`,\n outputDefault,\n authRequired,\n toolCount: userToolCount,\n resourceCount: schema.resources.length,\n templateCount: schema.resourceTemplates.length,\n promptCount: schema.prompts.length,\n oauthEnabled: !!oauthConfig,\n skillsEnabled: capabilities.skills || undefined,\n jobsEnabled: capabilities.jobs || undefined,\n workflowsEnabled: capabilities.workflows || undefined,\n };\n }\n\n // 8. Build SEA binaries if enabled\n //\n // For --target cli (cliEnabled === true), the runner script `exec`s only\n // the CLI binary — the standalone server SEA is dead weight (~114 MB, see\n // issue #373). Skip the server-SEA pass entirely in that mode. For\n // --target node (cliEnabled === false), build only the server SEA.\n let seaServerResult: { executablePath: string; executableSize: number } | undefined;\n let seaCliResult: { executablePath: string; executableSize: number } | undefined;\n if (seaEnabled) {\n const { buildSea } = await import('./sea-builder.js');\n\n if (!cliEnabled) {\n // Server-only SEA path (--target node): rebuild bundle as self-contained\n // (inlines all deps) and produce ${name}-bin.\n const seaTempName = `${config.name}.sea-temp`;\n console.log(`${c('cyan', '[build:sea]')} rebuilding server bundle (self-contained)...`);\n const seaBundle = await bundleWithEsbuild(compiledEntry, outDir, config, {\n selfContained: true,\n outputName: seaTempName,\n });\n\n console.log(`${c('cyan', '[build:sea]')} building server SEA binary...`);\n seaServerResult = await buildSea(seaBundle.bundlePath, outDir, config.name);\n fs.unlinkSync(seaBundle.bundlePath);\n console.log(\n `${c('green', '[build:sea]')} server binary: ${path.relative(cwd, seaServerResult.executablePath)} (${formatSize(seaServerResult.executableSize)})`,\n );\n }\n\n if (cliBundlePath) {\n console.log(`${c('cyan', '[build:sea]')} building CLI SEA binary...`);\n seaCliResult = await buildSea(cliBundlePath, outDir, `${config.name}-cli`);\n console.log(\n `${c('green', '[build:sea]')} CLI binary: ${path.relative(cwd, seaCliResult.executablePath)} (${formatSize(seaCliResult.executableSize)})`,\n );\n }\n }\n\n // 9. Write manifest\n const manifestPath = path.join(outDir, `${config.name}.manifest.json`);\n fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), 'utf-8');\n console.log(\n `${c('green', '[build:exec]')} manifest: ${path.relative(cwd, manifestPath)}`,\n );\n\n // 10. Generate runner script (dispatches to CLI bundle or SEA binary)\n const runnerContent = generateRunnerScript(config, !!cliEnabled, !!seaEnabled);\n const runnerPath = path.join(outDir, config.name);\n fs.writeFileSync(runnerPath, runnerContent, { mode: 0o755 });\n console.log(\n `${c('green', '[build:exec]')} runner: ${path.relative(cwd, runnerPath)}`,\n );\n\n // 10. Generate installer script\n const installerContent = generateInstallerScript(config, {\n target: cliEnabled ? 'cli' : 'node',\n seaEnabled: !!seaEnabled,\n });\n const installerPath = path.join(outDir, `install-${config.name}.sh`);\n fs.writeFileSync(installerPath, installerContent, { mode: 0o755 });\n console.log(\n `${c('green', '[build:exec]')} installer: ${path.relative(cwd, installerPath)}`,\n );\n\n // 12. Clean up intermediate compiled files\n const keepFiles = new Set([\n `${config.name}.bundle.js`,\n `${config.name}-cli.bundle.js`,\n `${config.name}.manifest.json`,\n config.name,\n `install-${config.name}.sh`,\n `${config.name}-bin`,\n `${config.name}-cli-bin`,\n '_skills',\n // bin-meta.json (issue #411) — the bin's runtime install command\n // reads this sidecar at execution time, so the cleanup pass MUST NOT\n // delete it. Whitelisted alongside the other emitted artifacts.\n 'bin-meta.json',\n ]);\n\n const allFiles = fs.readdirSync(outDir);\n let cleaned = 0;\n for (const file of allFiles) {\n if (!keepFiles.has(file)) {\n const filePath = path.join(outDir, file);\n const stat = fs.statSync(filePath);\n // Only clean intermediate compiled files; preserve .md and _skills/ directory\n if (stat.isFile() && !file.endsWith('.md')) {\n fs.unlinkSync(filePath);\n cleaned++;\n }\n }\n }\n if (cleaned > 0) {\n console.log(\n `${c('gray', '[build:exec]')} cleaned ${cleaned} intermediate file(s)`,\n );\n }\n\n // 13. Print summary\n console.log(`\\n${c('green', 'Executable build completed.')}`);\n console.log(`\\n${c('bold', 'Output:')}`);\n console.log(` ${path.relative(cwd, bundleResult.bundlePath)} ${c('gray', `(${formatSize(bundleResult.bundleSize)})`)}`);\n if (cliBundlePath) {\n const cliStat = fs.statSync(cliBundlePath);\n console.log(` ${path.relative(cwd, cliBundlePath)} ${c('gray', `(${formatSize(cliStat.size)})`)}`);\n }\n if (seaServerResult) {\n console.log(` ${path.relative(cwd, seaServerResult.executablePath)} ${c('gray', `(${formatSize(seaServerResult.executableSize)})`)}`);\n }\n if (seaCliResult) {\n console.log(` ${path.relative(cwd, seaCliResult.executablePath)} ${c('gray', `(${formatSize(seaCliResult.executableSize)})`)}`);\n }\n console.log(` ${path.relative(cwd, manifestPath)}`);\n console.log(` ${path.relative(cwd, runnerPath)}`);\n console.log(` ${path.relative(cwd, installerPath)}`);\n\n if (cliEnabled) {\n console.log(`\\n${c('gray', 'Run the CLI:')} ./${path.relative(cwd, runnerPath)} --help`);\n console.log(`${c('gray', 'Start server:')} ./${path.relative(cwd, runnerPath)} serve`);\n } else {\n console.log(`\\n${c('gray', 'Run the server:')} ./${path.relative(cwd, runnerPath)}`);\n }\n if (seaServerResult || seaCliResult) {\n console.log(`\\n${c('yellow', 'Note:')} SEA binaries are native executables. Run directly (not via bash).`);\n }\n console.log(`${c('gray', 'Install to system:')} bash ./${path.relative(cwd, installerPath)}`);\n}\n"]}