agents-inc 0.161.0 → 0.162.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 (129) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/dist/{chunk-ADDYIMWN.js → chunk-2IMHZEIK.js} +3 -3
  3. package/dist/{chunk-DHRW3MDM.js → chunk-33ZKIYJM.js} +3 -3
  4. package/dist/{chunk-DTCUZL7S.js → chunk-3JDVBHWO.js} +2 -2
  5. package/dist/{chunk-BLGETWYI.js → chunk-3QBOVV6A.js} +2 -2
  6. package/dist/{chunk-ODUACQLV.js → chunk-4KVJJJG2.js} +6 -6
  7. package/dist/{chunk-5MML3K36.js → chunk-4NAWM4OQ.js} +2 -2
  8. package/dist/{chunk-EY7Z34Y4.js → chunk-53XPSAJ4.js} +14 -14
  9. package/dist/chunk-53XPSAJ4.js.map +1 -0
  10. package/dist/{chunk-ZQZHDYHQ.js → chunk-57YWAMNT.js} +7 -7
  11. package/dist/{chunk-3M75HVIM.js → chunk-5J6DO4VW.js} +3 -3
  12. package/dist/{chunk-UMYEY6BA.js → chunk-77YZFVQD.js} +2 -2
  13. package/dist/{chunk-SX57ZIGM.js → chunk-AQSMNUKJ.js} +4 -4
  14. package/dist/{chunk-B7YTQVAF.js → chunk-BR3TNSO3.js} +4 -4
  15. package/dist/{chunk-MED6GNV3.js → chunk-C53RJ7AA.js} +9 -9
  16. package/dist/{chunk-EEFTUZHZ.js → chunk-EN5MEPAS.js} +5 -5
  17. package/dist/{chunk-B3YSTZZC.js → chunk-ES7WGE32.js} +3 -3
  18. package/dist/{chunk-BRHU6J3C.js → chunk-FL2CJ5T5.js} +3 -3
  19. package/dist/{chunk-3TM4FHTG.js → chunk-FXL63LDL.js} +2 -2
  20. package/dist/{chunk-5DWDT6GM.js → chunk-GFO55TMY.js} +10 -5
  21. package/dist/chunk-GFO55TMY.js.map +1 -0
  22. package/dist/{chunk-2MPXMJ2O.js → chunk-H2MDPOLG.js} +5 -5
  23. package/dist/{chunk-A2NA377T.js → chunk-HRVPZMKK.js} +6 -6
  24. package/dist/{chunk-6PVWDTEM.js → chunk-IMTWWA3N.js} +12 -12
  25. package/dist/{chunk-AMZO4YJK.js → chunk-IV42Z63R.js} +2 -2
  26. package/dist/{chunk-AMZO4YJK.js.map → chunk-IV42Z63R.js.map} +1 -1
  27. package/dist/{chunk-XA4SWA2Z.js → chunk-J2YG7P7L.js} +32 -6
  28. package/dist/{chunk-XA4SWA2Z.js.map → chunk-J2YG7P7L.js.map} +1 -1
  29. package/dist/{chunk-YOVUXONB.js → chunk-K26SBQLO.js} +4 -4
  30. package/dist/{chunk-EQSMVZGS.js → chunk-L65XGQKR.js} +8 -8
  31. package/dist/{chunk-264XDRU7.js → chunk-MI7LKLD7.js} +2 -2
  32. package/dist/{chunk-HB3YIAFD.js → chunk-MSUTHS2V.js} +2 -2
  33. package/dist/{chunk-W2RXRWDB.js → chunk-QM3ZNOWJ.js} +2 -2
  34. package/dist/{chunk-3H42U56X.js → chunk-RMMEYCEA.js} +2 -2
  35. package/dist/{chunk-LZPRLHUE.js → chunk-S6GX7IJ2.js} +6 -6
  36. package/dist/{chunk-T4RVCFWN.js → chunk-T2RPUNYP.js} +3 -3
  37. package/dist/{chunk-YSQ76LWG.js → chunk-UNASGGW2.js} +46 -27
  38. package/dist/chunk-UNASGGW2.js.map +1 -0
  39. package/dist/{chunk-WVCF7KFV.js → chunk-VEBEGZUV.js} +5 -5
  40. package/dist/{chunk-AO6DXJUK.js → chunk-VEONZFTL.js} +3 -3
  41. package/dist/{chunk-DGXW2ZFY.js → chunk-VFZF7LVY.js} +3 -3
  42. package/dist/{chunk-N6CILY5A.js → chunk-WIJM6BX6.js} +2 -2
  43. package/dist/{chunk-EERGAAGE.js → chunk-X6KXPRKI.js} +4 -4
  44. package/dist/{chunk-QKMT6OOP.js → chunk-XSM3IBMG.js} +2 -2
  45. package/dist/{chunk-F6LS2BQD.js → chunk-ZFPQM63K.js} +71 -9
  46. package/dist/{chunk-F6LS2BQD.js.map → chunk-ZFPQM63K.js.map} +1 -1
  47. package/dist/commands/build/marketplace.js +7 -7
  48. package/dist/commands/build/plugins.js +7 -7
  49. package/dist/commands/compile.js +10 -10
  50. package/dist/commands/doctor.js +10 -10
  51. package/dist/commands/edit.js +37 -37
  52. package/dist/commands/edit.js.map +1 -1
  53. package/dist/commands/eject.js +10 -10
  54. package/dist/commands/init.js +36 -36
  55. package/dist/commands/list.js +8 -8
  56. package/dist/commands/new/marketplace.js +7 -7
  57. package/dist/commands/search.js +15 -14
  58. package/dist/commands/search.js.map +1 -1
  59. package/dist/commands/share.js +22 -16
  60. package/dist/commands/share.js.map +1 -1
  61. package/dist/commands/uninstall.js +11 -11
  62. package/dist/commands/update.js +6 -6
  63. package/dist/components/common/removal-plan-confirm.js +2 -2
  64. package/dist/components/common/select-list.js +2 -2
  65. package/dist/components/wizard/category-grid.js +4 -4
  66. package/dist/components/wizard/checkbox-grid.js +4 -4
  67. package/dist/components/wizard/domain-selection.js +9 -9
  68. package/dist/components/wizard/run-wizard-session.js +26 -26
  69. package/dist/components/wizard/scroll-affordance.js +2 -2
  70. package/dist/components/wizard/skill-agent-summary.js +5 -5
  71. package/dist/components/wizard/source-grid.js +5 -5
  72. package/dist/components/wizard/stack-selection.js +7 -7
  73. package/dist/components/wizard/step-agents.js +8 -8
  74. package/dist/components/wizard/step-build.js +7 -7
  75. package/dist/components/wizard/step-confirm.js +9 -9
  76. package/dist/components/wizard/step-sources.js +8 -8
  77. package/dist/components/wizard/step-stack.js +8 -8
  78. package/dist/components/wizard/summary-panel.js +8 -8
  79. package/dist/components/wizard/toast.js +2 -2
  80. package/dist/components/wizard/wizard-layout.js +12 -12
  81. package/dist/components/wizard/wizard-tabs.js +2 -2
  82. package/dist/components/wizard/wizard.js +25 -25
  83. package/dist/hooks/init.js +36 -36
  84. package/dist/load-agent-defs-57YKPVQW.js +13 -0
  85. package/dist/recompile-project-agents-IQD3HRRS.js +17 -0
  86. package/dist/{source-loader-TSF5VS6V.js → source-loader-KAWB76OH.js} +4 -4
  87. package/dist/stores/wizard-store.js +4 -4
  88. package/package.json +2 -2
  89. package/dist/chunk-5DWDT6GM.js.map +0 -1
  90. package/dist/chunk-EY7Z34Y4.js.map +0 -1
  91. package/dist/chunk-YSQ76LWG.js.map +0 -1
  92. package/dist/load-agent-defs-LDSND43G.js +0 -13
  93. package/dist/recompile-project-agents-GQLODH24.js +0 -17
  94. /package/dist/{chunk-ADDYIMWN.js.map → chunk-2IMHZEIK.js.map} +0 -0
  95. /package/dist/{chunk-DHRW3MDM.js.map → chunk-33ZKIYJM.js.map} +0 -0
  96. /package/dist/{chunk-DTCUZL7S.js.map → chunk-3JDVBHWO.js.map} +0 -0
  97. /package/dist/{chunk-BLGETWYI.js.map → chunk-3QBOVV6A.js.map} +0 -0
  98. /package/dist/{chunk-ODUACQLV.js.map → chunk-4KVJJJG2.js.map} +0 -0
  99. /package/dist/{chunk-5MML3K36.js.map → chunk-4NAWM4OQ.js.map} +0 -0
  100. /package/dist/{chunk-ZQZHDYHQ.js.map → chunk-57YWAMNT.js.map} +0 -0
  101. /package/dist/{chunk-3M75HVIM.js.map → chunk-5J6DO4VW.js.map} +0 -0
  102. /package/dist/{chunk-UMYEY6BA.js.map → chunk-77YZFVQD.js.map} +0 -0
  103. /package/dist/{chunk-SX57ZIGM.js.map → chunk-AQSMNUKJ.js.map} +0 -0
  104. /package/dist/{chunk-B7YTQVAF.js.map → chunk-BR3TNSO3.js.map} +0 -0
  105. /package/dist/{chunk-MED6GNV3.js.map → chunk-C53RJ7AA.js.map} +0 -0
  106. /package/dist/{chunk-EEFTUZHZ.js.map → chunk-EN5MEPAS.js.map} +0 -0
  107. /package/dist/{chunk-B3YSTZZC.js.map → chunk-ES7WGE32.js.map} +0 -0
  108. /package/dist/{chunk-BRHU6J3C.js.map → chunk-FL2CJ5T5.js.map} +0 -0
  109. /package/dist/{chunk-3TM4FHTG.js.map → chunk-FXL63LDL.js.map} +0 -0
  110. /package/dist/{chunk-2MPXMJ2O.js.map → chunk-H2MDPOLG.js.map} +0 -0
  111. /package/dist/{chunk-A2NA377T.js.map → chunk-HRVPZMKK.js.map} +0 -0
  112. /package/dist/{chunk-6PVWDTEM.js.map → chunk-IMTWWA3N.js.map} +0 -0
  113. /package/dist/{chunk-YOVUXONB.js.map → chunk-K26SBQLO.js.map} +0 -0
  114. /package/dist/{chunk-EQSMVZGS.js.map → chunk-L65XGQKR.js.map} +0 -0
  115. /package/dist/{chunk-264XDRU7.js.map → chunk-MI7LKLD7.js.map} +0 -0
  116. /package/dist/{chunk-HB3YIAFD.js.map → chunk-MSUTHS2V.js.map} +0 -0
  117. /package/dist/{chunk-W2RXRWDB.js.map → chunk-QM3ZNOWJ.js.map} +0 -0
  118. /package/dist/{chunk-3H42U56X.js.map → chunk-RMMEYCEA.js.map} +0 -0
  119. /package/dist/{chunk-LZPRLHUE.js.map → chunk-S6GX7IJ2.js.map} +0 -0
  120. /package/dist/{chunk-T4RVCFWN.js.map → chunk-T2RPUNYP.js.map} +0 -0
  121. /package/dist/{chunk-WVCF7KFV.js.map → chunk-VEBEGZUV.js.map} +0 -0
  122. /package/dist/{chunk-AO6DXJUK.js.map → chunk-VEONZFTL.js.map} +0 -0
  123. /package/dist/{chunk-DGXW2ZFY.js.map → chunk-VFZF7LVY.js.map} +0 -0
  124. /package/dist/{chunk-N6CILY5A.js.map → chunk-WIJM6BX6.js.map} +0 -0
  125. /package/dist/{chunk-EERGAAGE.js.map → chunk-X6KXPRKI.js.map} +0 -0
  126. /package/dist/{chunk-QKMT6OOP.js.map → chunk-XSM3IBMG.js.map} +0 -0
  127. /package/dist/{load-agent-defs-LDSND43G.js.map → load-agent-defs-57YKPVQW.js.map} +0 -0
  128. /package/dist/{recompile-project-agents-GQLODH24.js.map → recompile-project-agents-IQD3HRRS.js.map} +0 -0
  129. /package/dist/{source-loader-TSF5VS6V.js.map → source-loader-KAWB76OH.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/cli/lib/agents/list-compiled-agents.ts","../src/cli/lib/agents/agent-provenance.ts","../../compile/src/agent-source.ts","../src/cli/lib/agents/agent-fetcher.ts","../src/cli/lib/agents/agent-recompiler.ts","../src/cli/lib/agents/write-compiled-agents.ts","../src/cli/lib/compiler.ts","../src/cli/lib/agents/agent-plugin-compiler.ts"],"sourcesContent":["import path from \"path\";\nimport { partition } from \"remeda\";\nimport { glob, readFileOptional, remove } from \"../../utils/fs\";\nimport { isAgentName } from \"../../utils/type-guards\";\nimport { hasProvenanceMarker } from \"./agent-provenance\";\nimport type { AgentName } from \"../../types\";\n\n/** Compiled-agent basenames in a directory, split by whether this CLI compiled them. */\nexport type AgentProvenanceSplit = {\n /** Files carrying the provenance marker — provably written by this CLI. */\n marked: string[];\n /** Everything else in the directory, the user's own agents among them. */\n unmarked: string[];\n};\n\n/** Lists compiled-agent markdown filenames (e.g. \"web-developer.md\") in a directory. */\nexport async function listAgentMdFiles(agentsDir: string): Promise<string[]> {\n return glob(\"*.md\", agentsDir);\n}\n\n/**\n * Splits the agent files in a directory by the provenance marker each compiled agent carries.\n *\n * This is the only thing that identifies this CLI's own output once the configuration naming\n * it is gone, so the split errs one way by construction: a file that cannot be read yields no\n * marker and lands in `unmarked`, because \"cannot prove it is ours\" and \"is not ours\" call for\n * the same answer — leave it alone.\n */\nexport async function splitAgentsByProvenance(agentsDir: string): Promise<AgentProvenanceSplit> {\n const files = await listAgentMdFiles(agentsDir);\n const classified = await Promise.all(files.map((file) => readAgentProvenance(agentsDir, file)));\n const [marked, unmarked] = partition(classified, (agent) => agent.compiledHere);\n\n return { marked: marked.map(agentName), unmarked: unmarked.map(agentName) };\n}\n\ntype ClassifiedAgent = { name: string; compiledHere: boolean };\n\nasync function readAgentProvenance(agentsDir: string, file: string): Promise<ClassifiedAgent> {\n const content = await readFileOptional(path.join(agentsDir, file));\n return { name: path.basename(file, \".md\"), compiledHere: hasProvenanceMarker(content) };\n}\n\nfunction agentName(agent: ClassifiedAgent): string {\n return agent.name;\n}\n\n/** Lists compiled-agent names (filenames without the `.md` extension) in a directory. */\nexport async function listCompiledAgentNames(agentsDir: string): Promise<AgentName[]> {\n const files = await listAgentMdFiles(agentsDir);\n // Boundary cast: compiled .md filenames are agent names by convention; custom\n // agents from marketplace stacks may not be members of the AgentName union.\n return files.map((f) => path.basename(f, \".md\") as AgentName);\n}\n\n/**\n * Removes stale CLI-compiled agent files from `agentsDir`: deletes any `.md`\n * whose basename is a built-in CLI agent name (`isAgentName`) that is NOT in\n * `keep`. The built-in-name check protects hand-authored agents (whose basename\n * is not a built-in name) — it is never the removal criterion. Only call this\n * when `keep` is the COMPLETE set of agents that should live in `agentsDir`.\n */\nexport async function pruneStaleCompiledAgents(\n agentsDir: string,\n keep: ReadonlySet<AgentName>,\n): Promise<void> {\n // A non-built-in basename is a hand-authored agent — always preserved.\n const isStaleCompiledAgent = (file: string): boolean => {\n const name = path.basename(file, \".md\");\n return isAgentName(name) && !keep.has(name);\n };\n\n const files = await listAgentMdFiles(agentsDir);\n await Promise.all(\n files.filter(isStaleCompiledAgent).map((file) => remove(path.join(agentsDir, file))),\n );\n}\n","import path from \"path\";\nimport { z } from \"zod\";\n\nimport { PROJECT_ROOT, STANDARD_FILES } from \"../../consts\";\nimport { readFile } from \"../../utils/fs\";\n\n/** The one field the marker needs from this CLI's own manifest. */\nconst ownPackageJsonSchema = z.object({ version: z.string().min(1) });\n\n/**\n * The provenance marker every compiled agent carries lives in `@workspace/compile/agent-source`,\n * beside the renderer that stamps it — the editor's output preview draws the same first body line\n * and must not compute it a second way. What stays here is the half that reads this CLI's own\n * manifest, which a browser has no equivalent of.\n */\nexport {\n hasProvenanceMarker,\n provenanceMarker,\n stampProvenanceMarker,\n} from \"@workspace/compile/agent-source\";\n\nlet ownVersion: Promise<string> | undefined;\n\n/**\n * This CLI's own published version, read once per process from the package manifest beside\n * the code — the same `PROJECT_ROOT` the bundled agent partials and templates resolve from,\n * so the version in a marker is the version of the compiler that wrote it.\n */\nexport function cliVersion(): Promise<string> {\n ownVersion ??= readOwnVersion();\n return ownVersion;\n}\n\nasync function readOwnVersion(): Promise<string> {\n const manifestPath = path.join(PROJECT_ROOT, STANDARD_FILES.PACKAGE_JSON);\n const raw: unknown = JSON.parse(await readFile(manifestPath));\n\n const parsed = ownPackageJsonSchema.safeParse(raw);\n if (!parsed.success) {\n throw new Error(`Could not read this CLI's own version from ${manifestPath}`);\n }\n return parsed.data.version;\n}\n","import type { Liquid } from \"liquidjs\"\n\nimport { diagnostics } from \"./diagnostics.js\"\nimport { DEFAULT_PLUGIN_NAME, EJECT_SOURCE } from \"./paths.js\"\nimport type {\n AgentConfig,\n CompiledAgentData,\n PluginSkillRef,\n Skill,\n} from \"./types.js\"\n\n/**\n * Everything that turns a resolved sub-agent into the markdown an install writes,\n * with two things left behind in the CLI because they read the machine: the five\n * `readFile`s that fetch an agent's partials off disk, and `cliVersion()`, which\n * reads the CLI's own manifest. Both arrive here as data — {@link AgentFiles} and\n * the `version` argument of {@link renderAgent} — which is what lets a browser\n * render the same bytes from the vendored corpus.\n */\n\n/** Pattern matching Liquid template delimiters that could enable template injection */\nconst LIQUID_SYNTAX_PATTERN = /\\{\\{|\\}\\}|\\{%|%\\}/g\n\n/**\n * Strips Liquid template syntax (`{{`, `}}`, `{%`, `%}`) from a string value.\n * Prevents template injection when user-controlled data is passed to the Liquid engine.\n *\n * @param value - Input string that may contain Liquid syntax\n * @param fieldName - Name of the field (for warning messages)\n * @returns Sanitized string with Liquid delimiters removed\n */\nexport function sanitizeLiquidSyntax<T extends string>(\n value: T,\n fieldName: string\n): T {\n if (!LIQUID_SYNTAX_PATTERN.test(value)) return value\n LIQUID_SYNTAX_PATTERN.lastIndex = 0\n const sanitized = value.replace(LIQUID_SYNTAX_PATTERN, \"\")\n diagnostics().warn(\n `Stripped Liquid template syntax from '${fieldName}' — possible template injection attempt`\n )\n // Boundary cast: .replace() widens the branded string T; stripping characters keeps it in T's domain\n return sanitized as T\n}\n\nfunction sanitizeStringArray(values: string[], fieldName: string): string[] {\n return values.map((v) => sanitizeLiquidSyntax(v, fieldName))\n}\n\nfunction sanitizeSkills(skills: Skill[]): Skill[] {\n return skills.map((s) => ({\n ...s,\n id: sanitizeLiquidSyntax(s.id, \"skill.id\"),\n description: sanitizeLiquidSyntax(s.description, \"skill.description\"),\n usage: sanitizeLiquidSyntax(s.usage, \"skill.usage\"),\n ...(s.pluginRef !== undefined && {\n pluginRef: sanitizeLiquidSyntax(s.pluginRef, \"skill.pluginRef\"),\n }),\n }))\n}\n\n/**\n * Sanitizes user-controlled metadata fields in compiled agent data to prevent\n * Liquid template injection. Strips `{{`, `}}`, `{%`, `%}` from agent\n * metadata and skill metadata before template rendering.\n *\n * Content fields (identity, playbook, output, criticalRequirementsTop,\n * criticalReminders) are passed through unchanged — LiquidJS does not\n * re-evaluate template syntax inside variable values, so double-curlies\n * in content (e.g. GitHub Actions `${{ secrets.X }}`) are safe.\n */\nexport function sanitizeCompiledAgentData(\n data: CompiledAgentData\n): CompiledAgentData {\n const sanitizedAgent: AgentConfig = {\n ...data.agent,\n name: sanitizeLiquidSyntax(data.agent.name, \"agent.name\"),\n title: sanitizeLiquidSyntax(data.agent.title, \"agent.title\"),\n description: sanitizeLiquidSyntax(\n data.agent.description,\n \"agent.description\"\n ),\n tools: sanitizeStringArray(data.agent.tools, \"agent.tools\"),\n ...(data.agent.disallowedTools !== undefined && {\n disallowedTools: sanitizeStringArray(\n data.agent.disallowedTools,\n \"agent.disallowedTools\"\n ),\n }),\n ...(data.agent.model !== undefined && {\n model: sanitizeLiquidSyntax(data.agent.model, \"agent.model\"),\n }),\n ...(data.agent.effort !== undefined && {\n effort: sanitizeLiquidSyntax(data.agent.effort, \"agent.effort\"),\n }),\n ...(data.agent.permissionMode !== undefined && {\n permissionMode: sanitizeLiquidSyntax(\n data.agent.permissionMode,\n \"agent.permissionMode\"\n ),\n }),\n }\n\n const sanitizedSkills = sanitizeSkills(data.skills)\n const sanitizedPreloaded = sanitizeSkills(data.preloadedSkills)\n const sanitizedDynamic = sanitizeSkills(data.dynamicSkills)\n const sanitizedPreloadedIds = data.preloadedSkillIds.map((id) =>\n sanitizeLiquidSyntax(id, \"preloadedSkillId\")\n )\n\n return {\n agent: sanitizedAgent,\n identity: data.identity,\n playbook: data.playbook,\n output: data.output,\n criticalRequirementsTop: data.criticalRequirementsTop,\n criticalReminders: data.criticalReminders,\n skills: sanitizedSkills,\n preloadedSkills: sanitizedPreloaded,\n dynamicSkills: sanitizedDynamic,\n preloadedSkillIds: sanitizedPreloadedIds,\n }\n}\n\n/** The five markdown partials a sub-agent is assembled from, however they were fetched. */\nexport type AgentFiles = Pick<\n CompiledAgentData,\n | \"identity\"\n | \"playbook\"\n | \"output\"\n | \"criticalRequirementsTop\"\n | \"criticalReminders\"\n>\n\n/**\n * The template context for one sub-agent.\n *\n * The preloaded/dynamic split PRESERVES the order `agent.skills` arrives in, and\n * that order is `config.ts`'s stack key order — so the emitted rows of the\n * sub-agent's skill-activation table are decided by the config writer's\n * canonicalisation rather than by anything here.\n */\nexport function buildAgentTemplateContext(\n name: string,\n agent: AgentConfig,\n files: AgentFiles,\n mapSkill: (skill: Skill) => Skill = (skill) => skill\n): CompiledAgentData {\n const skills = agent.skills.map(mapSkill)\n const preloadedSkills = skills.filter((s) => s.preloaded)\n const dynamicSkills = skills.filter((s) => !s.preloaded)\n const preloadedSkillIds = preloadedSkills.map((s) => s.pluginRef ?? s.id)\n\n diagnostics().verbose(\n `Skills for ${name}: ${preloadedSkills.length} preloaded, ${dynamicSkills.length} dynamic`\n )\n\n return {\n agent,\n ...files,\n skills,\n preloadedSkills,\n dynamicSkills,\n preloadedSkillIds,\n }\n}\n\n/**\n * The per-skill pluginRef decision. A skill renders as `${id}:${id}` only\n * when it has an explicit non-eject source on its SkillReference — i.e. it was\n * installed from a marketplace. `undefined` source (user-authored local skills\n * with no SkillConfig entry) and `\"eject\"` both fall through to bare id.\n */\nexport function pluginRefFor(skill: Skill): { pluginRef?: PluginSkillRef } {\n if (skill.source === undefined || skill.source === EJECT_SOURCE) return {}\n return { pluginRef: `${skill.id}:${skill.id}` as const }\n}\n\n/**\n * The provenance marker every compiled agent carries: an HTML comment on the first line\n * after the frontmatter, naming the generator, its version, and the fact that the file is\n * rewritten rather than edited.\n *\n * **A body comment, deliberately not a frontmatter field.** Claude Code documents sixteen\n * supported frontmatter keys and says nothing about how it treats an unknown one, so a\n * stricter release could reject every agent this CLI has ever written. The body is free-form\n * by contract, which makes a marker there safe, greppable, versioned, and the do-not-edit\n * notice at the same time.\n *\n * The version is informational — {@link hasProvenanceMarker} matches on the marker's SHAPE,\n * so an agent compiled by any release is recognised by any other. Matching the exact text\n * would sweep only the agents the running version happened to write.\n */\nconst MARKER_OPEN = `<!-- Generated by ${DEFAULT_PLUGIN_NAME} v`\nconst MARKER_NOTICE = \" — do not edit; compile rewrites this file\"\nconst MARKER_CLOSE = \" -->\"\n\nconst FRONTMATTER_FENCE = \"---\"\n\nexport function provenanceMarker(version: string): string {\n return `${MARKER_OPEN}${version}${MARKER_NOTICE}${MARKER_CLOSE}`\n}\n\n/** Whether a line is a marker this CLI wrote, at any version and under any wording. */\nfunction isProvenanceMarker(line: string): boolean {\n return line.startsWith(MARKER_OPEN) && line.endsWith(MARKER_CLOSE)\n}\n\n/**\n * The index of the first body line: past the closing frontmatter fence when there is one,\n * and the top of the file when there is not — a template override may render no frontmatter,\n * and the marker still needs a defined home.\n */\nfunction bodyStartIndex(lines: readonly string[]): number {\n if (lines[0] !== FRONTMATTER_FENCE) return 0\n const closingFence = lines.indexOf(FRONTMATTER_FENCE, 1)\n if (closingFence === -1) return 0\n return closingFence + 1\n}\n\n/**\n * Whether this CLI compiled the agent file this content came from.\n *\n * The marker's POSITION is part of the claim: an agent that merely quotes the line further\n * down (a prompt about this very feature, say) is the user's, and a sweep reading that as\n * provenance would delete a file nothing here wrote.\n */\nexport function hasProvenanceMarker(content: string): boolean {\n const lines = content.split(\"\\n\")\n const firstBodyLine = lines[bodyStartIndex(lines)]\n return firstBodyLine !== undefined && isProvenanceMarker(firstBodyLine)\n}\n\n/**\n * The same content carrying exactly one provenance marker, on the first line after the\n * frontmatter.\n *\n * Idempotent by replacement rather than by insertion: content that already carries a marker\n * has that line rewritten, so stamping twice at one version is a fixed point and a version\n * bump moves the line instead of stacking a second one beside it.\n */\nexport function stampProvenanceMarker(\n content: string,\n version: string\n): string {\n const lines = content.split(\"\\n\")\n const bodyStart = bodyStartIndex(lines)\n const replacedLines = hasProvenanceMarker(content) ? 1 : 0\n\n return [\n ...lines.slice(0, bodyStart),\n provenanceMarker(version),\n ...lines.slice(bodyStart + replacedLines),\n ].join(\"\\n\")\n}\n\n/** The template every compiled sub-agent is rendered from, by name rather than by path. */\nconst AGENT_TEMPLATE = \"agent\"\n\n/**\n * Renders the agent template and stamps the result with the provenance marker.\n *\n * Every compile entry point renders through here, so there is no path that writes a compiled\n * agent this CLI cannot later recognise as its own — which is what `uninstall` reads back\n * when the configuration naming the agents is gone. The stamp replaces rather than inserts,\n * so a template that emits the marker itself still produces exactly one.\n *\n * `version` is an argument because the CLI reads it from its own `package.json` and a browser\n * has no manifest to read; the editor passes `CORPUS_CLI_VERSION`, the release the corpus was\n * vendored at.\n */\nexport async function renderAgent(\n engine: Liquid,\n data: CompiledAgentData,\n version: string\n): Promise<string> {\n // Boundary cast: liquidjs types renderFile as `Promise<any>` because a template\n // can render to any value. The agent template renders a markdown file, and both\n // callers have declared `Promise<string>` since they were written.\n const rendered = (await engine.renderFile(\n AGENT_TEMPLATE,\n sanitizeCompiledAgentData(data)\n )) as string\n return stampProvenanceMarker(rendered, version)\n}\n","import path from \"path\";\nimport { directoryExists } from \"../../utils/fs\";\nimport { verbose } from \"../../utils/logger\";\nimport { PROJECT_ROOT, DIRS } from \"../../consts\";\nimport { fetchFromSource, type FetchOptions } from \"../loading\";\nimport { loadProjectSourceConfig } from \"../configuration\";\nimport type { AgentSourcePaths } from \"../../types\";\n\nexport async function getAgentDefinitions(remoteSource?: string): Promise<AgentSourcePaths> {\n if (remoteSource) {\n return fetchAgentDefinitionsFromRemote(remoteSource);\n }\n return getLocalAgentDefinitions();\n}\n\nexport async function getLocalAgentDefinitions(): Promise<AgentSourcePaths> {\n const agentsDir = path.join(PROJECT_ROOT, DIRS.agents);\n\n if (!(await directoryExists(agentsDir))) {\n throw new Error(\n `Agent partials not found at '${agentsDir}'. Ensure the CLI is properly installed.`,\n );\n }\n\n verbose(`Agent partials loaded from CLI: ${agentsDir}`);\n\n return {\n agentsDir,\n sourcePath: PROJECT_ROOT,\n };\n}\n\nexport async function fetchAgentDefinitionsFromRemote(\n source: string,\n options: FetchOptions & { agentsDir?: string } = {},\n): Promise<AgentSourcePaths> {\n verbose(`Fetching agent partials from remote: ${source}`);\n\n const result = await fetchFromSource(source, { subdir: \"\" });\n\n // ABORT on an unreadable config. It names the directory the fetched repository keeps its agent\n // partials in; defaulting past it compiles agents from whatever happens to sit at `DIRS.agents`,\n // or reports partials missing from a repository that has them.\n const sourceProjectConfig = options.agentsDir\n ? undefined\n : await loadProjectSourceConfig(result.path);\n if (sourceProjectConfig?.agentsDir) {\n verbose(`Using agentsDir from source config: ${sourceProjectConfig.agentsDir}`);\n }\n const agentsDirRelPath = options.agentsDir ?? sourceProjectConfig?.agentsDir ?? DIRS.agents;\n\n const agentsDir = path.join(result.path, agentsDirRelPath);\n\n if (!(await directoryExists(agentsDir))) {\n throw new Error(`Agent partials not found at '${agentsDir}'`);\n }\n\n verbose(`Agent partials fetched from: ${result.path}`);\n\n return {\n agentsDir,\n sourcePath: result.path,\n };\n}\n","import { partition } from \"remeda\";\nimport { writeCompiledAgentsByScope, type AgentWriteOutcome } from \"./write-compiled-agents\";\nimport { listCompiledAgentNames } from \"./list-compiled-agents\";\nimport path from \"path\";\n\nimport { getErrorMessage } from \"../../utils/errors\";\nimport type {\n AgentDefinition,\n AgentName,\n CompileAgentConfig,\n CompileConfig,\n ProjectConfig,\n SkillDefinitionMap,\n SkillScope,\n} from \"../../types\";\n\nimport { buildCompileAgents } from \"../installation/local-installer\";\nimport { ensureDir } from \"../../utils/fs\";\nimport { verbose } from \"../../utils/logger\";\nimport { typedEntries, typedFromEntries, typedKeys } from \"../../utils/typed-object\";\nimport { createLiquidEngine } from \"../compiler\";\nimport { loadProjectConfig, effectivelyExcludedSkillIds } from \"../configuration\";\nimport { loadAllAgents, loadProjectAgents } from \"../loading\";\nimport { getPluginAgentsDir } from \"../plugins\";\nimport { discoverAllPluginSkills } from \"../plugins/plugin-discovery\";\nimport { resolveAgents } from \"../resolver\";\n\nexport type RecompileAgentsOptions = {\n pluginDir: string;\n sourcePath: string;\n agents?: AgentName[];\n skills?: SkillDefinitionMap;\n projectDir?: string;\n outputDir?: string;\n /** When provided, routes agents by scope: global agents to ~/.claude/agents/, project agents to outputDir */\n agentScopeMap?: Map<AgentName, SkillScope>;\n};\n\nexport type RecompileAgentsResult = {\n compiled: AgentName[];\n /**\n * The subset of `compiled` whose file this pass actually wrote. `compiled` is\n * every agent that came through the pass with a correct file at the end of it;\n * `rewritten` is the ones whose content moved, so `compiled minus rewritten` is\n * the count a summary reports as unchanged.\n */\n rewritten: AgentName[];\n failed: AgentName[];\n warnings: string[];\n};\n\nasync function getExistingAgentNames(pluginDir: string): Promise<AgentName[]> {\n return listCompiledAgentNames(getPluginAgentsDir(pluginDir));\n}\n\ntype ResolveAgentNamesParams = {\n specifiedAgents?: AgentName[];\n projectConfig: ProjectConfig | null;\n allAgents: Partial<Record<AgentName, AgentDefinition>>;\n outputDir?: string;\n pluginDir: string;\n};\n\nasync function resolveAgentNames(params: ResolveAgentNamesParams): Promise<AgentName[]> {\n const { specifiedAgents, projectConfig, allAgents, outputDir, pluginDir } = params;\n\n if (specifiedAgents) {\n return specifiedAgents;\n }\n\n // A present config is authoritative over its agent roster — even when empty.\n // `agents: []` means \"no agents\", so it must NOT fall through to the\n // all-agents branch below; that branch exists only for the config-LESS case.\n if (projectConfig) {\n const agentNames = projectConfig.agents.map((a) => a.name);\n verbose(`Using agents from config: ${agentNames.join(\", \")}`);\n return agentNames;\n }\n\n if (outputDir) {\n const names = typedKeys<AgentName>(allAgents);\n verbose(`Using all available agents from source: ${names.join(\", \")}`);\n return names;\n }\n\n return getExistingAgentNames(pluginDir);\n}\n\n/** Splits write outcomes into the recompile result; logs each success at verbose level. */\nfunction buildRecompileResult(\n outcomes: AgentWriteOutcome[],\n priorWarnings: string[],\n): RecompileAgentsResult {\n const [succeeded, failedOutcomes] = partition(\n outcomes,\n (outcome): outcome is Extract<AgentWriteOutcome, { ok: true }> => outcome.ok,\n );\n succeeded.forEach((outcome) =>\n verbose(\n ` ${outcome.rewritten ? \"Rewrote\" : \"Unchanged\"}: ${outcome.name} (${outcome.scope} -> ${outcome.targetDir})`,\n ),\n );\n return {\n compiled: succeeded.map((outcome) => outcome.name),\n rewritten: succeeded.filter((outcome) => outcome.rewritten).map((outcome) => outcome.name),\n failed: failedOutcomes.map((outcome) => outcome.name),\n warnings: [\n ...priorWarnings,\n ...failedOutcomes.map(\n (outcome) => `Failed to compile ${outcome.name}: ${getErrorMessage(outcome.error)}`,\n ),\n ],\n };\n}\n\nexport function filterExcludedEntries(config: ProjectConfig): ProjectConfig {\n const excludedIds = effectivelyExcludedSkillIds(config.skills);\n const activeSkills = config.skills.filter((s) => !s.excluded);\n const activeAgents = config.agents.filter((a) => !a.excluded);\n\n // Also remove excluded skill refs from stack assignments. A config with no stack keeps\n // none — the key stays absent rather than becoming an explicit `undefined`.\n const filteredStack =\n config.stack === undefined\n ? {}\n : {\n stack: Object.fromEntries(\n typedEntries(config.stack).map(([agentName, agentStack]) => [\n agentName,\n Object.fromEntries(\n typedEntries(agentStack).map(([category, assignments]) => [\n category,\n assignments.filter((a) => !excludedIds.has(a.id)),\n ]),\n ),\n ]),\n ),\n };\n\n return { ...config, skills: activeSkills, agents: activeAgents, ...filteredStack };\n}\n\nexport async function recompileAgents(\n options: RecompileAgentsOptions,\n): Promise<RecompileAgentsResult> {\n const { pluginDir, sourcePath, skills: providedSkills, projectDir, outputDir } = options;\n\n const configDir = projectDir ?? pluginDir;\n const loadedConfig = await loadProjectConfig(configDir);\n const projectConfig = loadedConfig?.config ?? null;\n\n // Filter excluded entries once at the entry point — callees receive clean data\n const filteredConfig = projectConfig ? filterExcludedEntries(projectConfig) : null;\n\n const builtinAgents = await loadAllAgents(sourcePath);\n const projectAgents = projectDir ? await loadProjectAgents(projectDir) : {};\n\n // Priority: project agents > built-in agents\n const allAgents: Partial<Record<AgentName, AgentDefinition>> = {\n ...builtinAgents,\n ...projectAgents,\n };\n\n const agentNames = await resolveAgentNames({\n ...(options.agents !== undefined && { specifiedAgents: options.agents }),\n projectConfig: filteredConfig,\n allAgents,\n ...(outputDir !== undefined && { outputDir }),\n pluginDir,\n });\n\n if (agentNames.length === 0) {\n return { compiled: [], rewritten: [], failed: [], warnings: [\"No agents found to recompile\"] };\n }\n\n verbose(`Recompiling ${agentNames.length} agents in ${outputDir ?? pluginDir}`);\n\n // When skills are not provided, discover from all plugin directories.\n const pluginSkills: SkillDefinitionMap =\n providedSkills ?? (await discoverAllPluginSkills(projectDir ?? pluginDir));\n\n const allConfigAgents = filteredConfig ? buildCompileAgents(filteredConfig, allAgents) : {};\n\n // Restrict to only the agents we're compiling (agentNames).\n // buildCompileAgents returns entries for ALL agents in the config, but when\n // scopeFilter is active, we only want the agents matching that scope.\n // Without this filter, a project pass would compile global agents without\n // their stack (since the project config omits global agent stack entries)\n // and overwrite correctly compiled global agent files.\n const [knownAgents, missingAgents] = partition(agentNames, (name) =>\n Boolean(allConfigAgents[name] || allAgents[name]),\n );\n const missingWarnings = missingAgents.map(\n (name) => `Agent \"${name}\" not found in source definitions`,\n );\n const configAgents = typedFromEntries<AgentName, CompileAgentConfig>(\n knownAgents.map((name) => [name, allConfigAgents[name] ?? {}]),\n );\n\n const compileConfig: CompileConfig = {\n name: filteredConfig?.name || path.basename(pluginDir),\n description: filteredConfig?.description || \"Recompiled plugin\",\n agents: configAgents,\n };\n\n const engine = await createLiquidEngine(projectDir);\n const resolvedAgents = await resolveAgents(allAgents, pluginSkills, compileConfig, sourcePath);\n\n const agentsDir = outputDir ?? getPluginAgentsDir(pluginDir);\n await ensureDir(agentsDir);\n\n const outcomes = await writeCompiledAgentsByScope({\n resolvedAgents,\n sourcePath,\n engine,\n projectAgentsDir: agentsDir,\n ...(options.agentScopeMap !== undefined && { agentScopeMap: options.agentScopeMap }),\n });\n return buildRecompileResult(outcomes, missingWarnings);\n}\n","import os from \"os\";\nimport path from \"path\";\nimport type { Liquid } from \"liquidjs\";\nimport { compileAgentForPlugin } from \"../compiler.js\";\nimport { resolveInstallPaths } from \"../installation/install-base-dir.js\";\nimport { writeFile, fileExists, readFile } from \"../../utils/fs.js\";\nimport { typedEntries } from \"../../utils/typed-object.js\";\nimport type { AgentConfig, AgentName, SkillScope } from \"../../types/index.js\";\n\nexport type AgentWriteOutcome =\n | {\n name: AgentName;\n ok: true;\n scope: SkillScope;\n targetDir: string;\n /**\n * Whether this pass actually wrote the file. False means the compiled output\n * matched what was already on disk, so nothing was written — which is what\n * lets a recompile summary tell a real one from a no-op instead of counting\n * the roster it walked.\n */\n rewritten: boolean;\n }\n | { name: AgentName; ok: false; error: unknown };\n\n/**\n * Whether the target already holds exactly this content, making a write a no-op.\n *\n * Skipping that write is what gives \"unchanged\" a meaning a caller can check: an\n * agent reported unchanged keeps its mtime, and an mtime is the only trace a\n * rewrite-with-identical-bytes leaves anywhere.\n */\nasync function holdsExactly(filePath: string, content: string): Promise<boolean> {\n return (await fileExists(filePath)) && (await readFile(filePath)) === content;\n}\n\n/**\n * Where an agent goes when `agentScopeMap` has nothing to say about it — either because the caller\n * passed no map at all (`agents-inc update` recompiles that way) or because this agent is not in\n * the one it passed (a hand-authored agent under `.claude/agents/` has no config row).\n *\n * This is a ROUTING answer, not a selection default: `\"project\"` here means \"the directory the\n * caller named in `projectAgentsDir`\", which for an unrouted write is the only defensible target.\n * It is deliberately NOT `DEFAULT_SELECTION_OPTIONS.scope` from `@workspace/matrix` — that constant\n * says what an untouched *pick* installs as, and adopting it here would relocate the agents of every\n * caller that never asked for global routing into the user's `~/.claude/agents`.\n */\nconst UNROUTED_AGENT_SCOPE: SkillScope = \"project\";\n\n/**\n * Compiles each resolved agent and writes it to its scope's agents directory:\n * global agents to `~/.claude/agents/`, project agents to `projectAgentsDir`.\n * Per-agent failures are collected as outcomes — callers own the policy\n * (recompile reports and continues; install hard-errors).\n *\n * Neither directory is created up front. `writeFile` makes a target's parent on\n * the way past, so a directory appears exactly when an agent routes into it —\n * which is what keeps a wholly project-scoped pass from leaving an empty\n * `~/.claude/agents/` behind in a home that has no global install.\n */\nexport async function writeCompiledAgentsByScope(params: {\n resolvedAgents: Partial<Record<AgentName, AgentConfig>>;\n sourcePath: string;\n engine: Liquid;\n projectAgentsDir: string;\n agentScopeMap?: Map<AgentName, SkillScope>;\n}): Promise<AgentWriteOutcome[]> {\n const globalAgentsDir = resolveInstallPaths(os.homedir(), \"global\").agentsDir;\n\n const outcomes: AgentWriteOutcome[] = [];\n for (const [name, agent] of typedEntries<AgentName, AgentConfig>(params.resolvedAgents)) {\n try {\n const output = await compileAgentForPlugin(name, agent, params.sourcePath, params.engine);\n const scope = params.agentScopeMap?.get(name) ?? UNROUTED_AGENT_SCOPE;\n const targetDir = scope === \"global\" ? globalAgentsDir : params.projectAgentsDir;\n const targetPath = path.join(targetDir, `${name}.md`);\n const rewritten = !(await holdsExactly(targetPath, output));\n if (rewritten) await writeFile(targetPath, output);\n outcomes.push({ name, ok: true, scope, targetDir, rewritten });\n } catch (error) {\n outcomes.push({ name, ok: false, error });\n }\n }\n return outcomes;\n}\n","import { Liquid } from \"liquidjs\";\nimport path from \"path\";\nimport {\n buildAgentTemplateContext,\n pluginRefFor,\n renderAgent,\n type AgentFiles,\n} from \"@workspace/compile/agent-source\";\nimport { readFile, readFileOptional, directoryExists } from \"../utils/fs\";\nimport { verbose } from \"../utils/logger\";\nimport {\n CLAUDE_DIR,\n CLAUDE_SRC_DIR,\n DIRS,\n PROJECT_ROOT,\n STANDARD_FILES,\n STANDARD_DIRS,\n} from \"../consts\";\nimport { cliVersion } from \"./agents/agent-provenance\";\nimport \"./compile-seat.js\";\nimport type { AgentConfig, AgentName } from \"../types\";\n\n/**\n * What survives here is the half of a compile that reads the machine: the five `readFile`s that\n * fetch an agent's partials off disk, and the layered template roots a project can override. The\n * rendering itself — the template context, the injection sanitiser and the provenance stamp — is\n * `@workspace/compile/agent-source`, so the editor's output preview draws the bytes this writes\n * rather than a second implementation of them.\n */\nexport {\n buildAgentTemplateContext,\n sanitizeCompiledAgentData,\n sanitizeLiquidSyntax,\n} from \"@workspace/compile/agent-source\";\n\nasync function readAgentFiles(\n name: AgentName,\n agent: AgentConfig,\n projectRoot: string,\n): Promise<AgentFiles> {\n const agentSourceRoot = agent.sourceRoot || projectRoot;\n const agentBaseDir = agent.agentBaseDir || DIRS.agents;\n const agentDir = path.join(agentSourceRoot, agentBaseDir, agent.path || name);\n\n const identity = await readFile(path.join(agentDir, STANDARD_FILES.IDENTITY_MD));\n const playbook = await readFile(path.join(agentDir, STANDARD_FILES.PLAYBOOK_MD));\n const criticalRequirementsTop = await readFileOptional(\n path.join(agentDir, STANDARD_FILES.CRITICAL_REQUIREMENTS_MD),\n \"\",\n );\n const criticalReminders = await readFileOptional(\n path.join(agentDir, STANDARD_FILES.CRITICAL_REMINDERS_MD),\n \"\",\n );\n\n const agentPath = agent.path || name;\n const parts = agentPath.split(\"/\");\n const category = parts[0] || name;\n const categoryDir = path.join(agentSourceRoot, agentBaseDir, category);\n\n let output = await readFileOptional(path.join(agentDir, STANDARD_FILES.OUTPUT_MD), \"\");\n if (!output) {\n output = await readFileOptional(path.join(categoryDir, STANDARD_FILES.OUTPUT_MD), \"\");\n }\n\n return { identity, playbook, output, criticalRequirementsTop, criticalReminders };\n}\n\n/**\n * Creates a Liquid template engine with a layered template root hierarchy.\n *\n * Template resolution order (first match wins):\n * 1. Project-local templates: `{projectDir}/.claude-src/agents/_templates/`\n * 2. Legacy templates: `{projectDir}/.claude/templates/`\n * 3. Built-in templates: `{PROJECT_ROOT}/src/agents/_templates/`\n *\n * The browser-side twin is `createEngineFromTemplates` in `@workspace/compile/engine`, which\n * builds the same engine over the vendored corpus instead of over directories. Every option\n * below is duplicated there, because a render that resolved filters or variables differently\n * would produce a different file from the same data.\n *\n * @param projectDir - Optional project directory for local template overrides\n * @returns Configured Liquid engine with `.liquid` extension and strict filters\n */\nexport async function createLiquidEngine(projectDir?: string): Promise<Liquid> {\n const roots: string[] = [];\n\n if (projectDir) {\n const srcTemplatesDir = path.join(\n projectDir,\n CLAUDE_SRC_DIR,\n STANDARD_DIRS.AGENTS,\n path.basename(DIRS.templates),\n );\n if (await directoryExists(srcTemplatesDir)) {\n roots.push(srcTemplatesDir);\n verbose(`Using local templates from: ${srcTemplatesDir}`);\n }\n\n const legacyTemplatesDir = path.join(projectDir, CLAUDE_DIR, STANDARD_DIRS.TEMPLATES);\n if (await directoryExists(legacyTemplatesDir)) {\n roots.push(legacyTemplatesDir);\n verbose(`Using legacy templates from: ${legacyTemplatesDir}`);\n }\n }\n\n roots.push(path.join(PROJECT_ROOT, DIRS.templates));\n\n return new Liquid({\n root: roots,\n extname: \".liquid\",\n strictVariables: false,\n strictFilters: true,\n });\n}\n\nexport async function compileAgentForPlugin(\n name: AgentName,\n agent: AgentConfig,\n fallbackRoot: string,\n engine: Liquid,\n): Promise<string> {\n verbose(`Compiling agent: ${name}`);\n\n const files = await readAgentFiles(name, agent, fallbackRoot);\n\n // Per-skill pluginRef attachment. Each skill's own `source` decides\n // whether it renders as `${id}:${id}` (plugin-installed) or bare id (ejected).\n // This correctly handles mixed-mode agents where some skills are plugin and\n // others are ejected. Missing `source` (user-authored local skills with no\n // SkillConfig entry) falls through to bare id — the expected case, not a\n // silent fallback.\n const data = buildAgentTemplateContext(name, agent, files, (skill) => ({\n ...skill,\n ...pluginRefFor(skill),\n }));\n\n return renderAgent(engine, data, await cliVersion());\n}\n","import path from \"path\";\nimport { getErrorMessage } from \"../../utils/errors\";\nimport { readFile, ensureDir, copy } from \"../../utils/fs\";\nimport { log, verbose, warn } from \"../../utils/logger\";\nimport {\n generateAgentPluginManifest,\n writePluginManifest,\n getPluginManifestPath,\n} from \"../plugins\";\nimport { listAgentMdFiles } from \"./list-compiled-agents\";\nimport { computeStringHash, determinePluginVersion, writeContentHash } from \"../versioning\";\nimport { extractFrontmatter } from \"../../utils/frontmatter\";\nimport type { AgentFrontmatter, PluginManifest } from \"../../types\";\nimport { agentFrontmatterValidationSchema, formatZodIssues } from \"../schemas\";\n\nexport type AgentPluginOptions = {\n agentPath: string;\n outputDir: string;\n};\n\nexport type CompiledAgentPlugin = {\n pluginPath: string;\n manifest: PluginManifest;\n agentName: string;\n};\n\nfunction parseAgentFrontmatter(\n content: string,\n filePath: string,\n): Pick<AgentFrontmatter, \"name\" | \"description\"> | null {\n const raw = extractFrontmatter(content);\n if (!raw) {\n return null;\n }\n\n const result = agentFrontmatterValidationSchema.safeParse(raw);\n if (!result.success) {\n warn(`Invalid agent frontmatter in ${filePath}: ${formatZodIssues(result.error.issues)}`);\n return null;\n }\n\n return { name: result.data.name, description: result.data.description };\n}\n\nexport async function compileAgentPlugin(\n options: AgentPluginOptions,\n): Promise<CompiledAgentPlugin> {\n const { agentPath, outputDir } = options;\n const fileName = path.basename(agentPath);\n\n const content = await readFile(agentPath);\n const frontmatter = parseAgentFrontmatter(content, agentPath);\n\n if (!frontmatter) {\n throw new Error(\n `Agent '${fileName}' has invalid or missing YAML frontmatter. ` +\n `Required fields: 'name' and 'description'. File: ${agentPath}`,\n );\n }\n\n const agentName = frontmatter.name;\n\n verbose(`Compiling agent plugin: ${agentName} from ${agentPath}`);\n\n const pluginDir = path.join(outputDir, `agent-${agentName}`);\n const agentsDir = path.join(pluginDir, \"agents\");\n\n await ensureDir(pluginDir);\n await ensureDir(agentsDir);\n\n const newHash = computeStringHash(content);\n const { version, contentHash } = await determinePluginVersion(\n newHash,\n pluginDir,\n getPluginManifestPath,\n );\n\n const manifest = generateAgentPluginManifest({\n agentName,\n description: frontmatter.description,\n version,\n });\n\n await writePluginManifest(pluginDir, manifest);\n\n await writeContentHash(pluginDir, contentHash, getPluginManifestPath);\n\n verbose(` Wrote plugin.json for ${agentName} (v${version})`);\n\n await copy(agentPath, path.join(agentsDir, `${agentName}.md`));\n verbose(` Copied agent ${fileName} -> agents/${agentName}.md`);\n\n return {\n pluginPath: pluginDir,\n manifest,\n agentName,\n };\n}\n\nexport async function compileAllAgentPlugins(\n agentsDir: string,\n outputDir: string,\n): Promise<CompiledAgentPlugin[]> {\n const results: CompiledAgentPlugin[] = [];\n\n const agentMdFiles = await listAgentMdFiles(agentsDir);\n\n for (const agentFile of agentMdFiles) {\n const agentPath = path.join(agentsDir, agentFile);\n\n try {\n const result = await compileAgentPlugin({\n agentPath,\n outputDir,\n });\n results.push(result);\n log(` [OK] agent-${result.agentName}`);\n } catch (error) {\n const errorMessage = getErrorMessage(error);\n warn(`Failed to compile agent from '${agentFile}': ${errorMessage}`);\n }\n }\n\n return results;\n}\n\nexport function printAgentCompilationSummary(results: CompiledAgentPlugin[]): void {\n log(`\\nCompiled ${results.length} agent plugins:`);\n for (const result of results) {\n log(` - agent-${result.agentName} (v${result.manifest.version})`);\n }\n}\n"],"mappings":"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","names":["path","path","path","path","partition","path","path","path","path","path","partition","agentName","path","path","path","agentName"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/cli/commands/init.tsx","../src/cli/lib/permission-checker.tsx"],"sourcesContent":["import React from \"react\";\n\nimport { Flags, type Interfaces } from \"@oclif/core\";\nimport { Box, Text, useApp } from \"ink\";\nimport { render } from \"../components/render.js\";\n\nimport { BaseCommand } from \"../base-command.js\";\nimport { type WizardResultV2 } from \"../components/wizard/wizard.js\";\nimport { runWizardSession } from \"../components/wizard/run-wizard-session.js\";\nimport { useTerminalDimensions } from \"../components/hooks/use-terminal-dimensions.js\";\nimport { type SourceLoadResult } from \"../lib/loading/index.js\";\nimport {\n loadSource,\n loadAgentDefs,\n copyLocalSkills,\n writeProjectConfig,\n compileAgentsAllScopes,\n type CompilationResult,\n type SkillCopyResult,\n discoverInstalledSkills,\n} from \"../lib/operations/index.js\";\nimport { fetchSeedConfig } from \"../lib/seed/fetch-seed.js\";\nimport {\n registerExternalSkills,\n writeExternalSkills,\n type ExternalSkillInstall,\n} from \"../lib/seed/external-skills.js\";\nimport { seedToWizardResult, type SeedMapping } from \"../lib/seed/seed-to-wizard.js\";\nimport { getInstallationInfo } from \"../lib/plugins/plugin-info.js\";\nimport { loadProjectConfig } from \"../lib/configuration/project-config.js\";\nimport { resolveBranding } from \"../lib/configuration/config.js\";\nimport {\n type InstallMode,\n detectInstallation,\n detectGlobalInstallation,\n detectProjectInstallation,\n deriveInstallMode,\n resolveInstallPaths,\n buildAgentScopeMap,\n isHomeDirectory,\n INSTALL_MODE_LABELS,\n INSTALL_MODE_DESCRIPTIONS,\n} from \"../lib/installation/index.js\";\nimport { checkPermissions } from \"../lib/permission-checker.js\";\nimport {\n ASCII_LOGO,\n CLAUDE_SRC_DIR,\n CLI_INVOKE_COMMAND,\n DEFAULT_BRANDING,\n EDITOR_URL,\n EDIT_PROJECT_SETUP_FLAG,\n EJECT_SOURCE,\n STANDARD_FILES,\n editorConfigUrl,\n} from \"../consts.js\";\nimport { clearTerminalScreen } from \"../utils/terminal.js\";\nimport { SelectList, type SelectListItem } from \"../components/common/select-list.js\";\nimport { promptValue } from \"../components/common/prompt-confirm.js\";\nimport { Spinner } from \"../components/common/spinner.js\";\nimport { getErrorMessage } from \"../utils/errors.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport { openUrl } from \"../utils/open-url.js\";\nimport type { AgentName, MergedSkillsMatrix, SkillScope } from \"../types/index.js\";\nimport { type StartupMessage } from \"../utils/logger.js\";\nimport {\n INCOMPLETE_WORK_RECOVERY,\n STATUS_MESSAGES,\n agentsNotCompiled,\n carriedSkillsWritten,\n globalScopedAgentsHint,\n initSucceeded,\n sharedConfigExistingInstall,\n sharedConfigGlobalInstall,\n skippedUnknownAgents,\n skippedUnknownSkills,\n} from \"../utils/messages.js\";\nimport type { SeedPayload } from \"@workspace/matrix/seed\";\n\nconst DASHBOARD_OPTIONS = [\n { label: \"Edit\", value: \"edit\" },\n { label: \"Compile\", value: \"compile\" },\n { label: \"Doctor\", value: \"doctor\" },\n { label: \"List\", value: \"list\" },\n] as const satisfies readonly SelectListItem<string>[];\n\n/** The commands offered by the project dashboard (single source: DASHBOARD_OPTIONS). */\nexport type DashboardCommand = (typeof DASHBOARD_OPTIONS)[number][\"value\"];\n\n/**\n * The dashboard's title: {@link ASCII_LOGO} for an installation resting on the shipped branding,\n * and the configured name in its place for one that white-labels it.\n *\n * **The logo gives way rather than sitting above the name, because it spells the shipped name.**\n * `branding.name` replaces a heading everywhere else it is read — every configured leg of\n * `commands/branding-name-reaches-headings` asserts {@link DEFAULT_BRANDING.NAME} is ABSENT — so\n * painting `AGENTS INC` in block capitals above `Northwind` would leave the vendor's name at the\n * most prominent surface the product has, which is the one thing white-labelling is for.\n *\n * The default path is untouched by construction: {@link resolveBranding} answers\n * {@link DEFAULT_BRANDING.NAME} for a configuration with no `branding` key, so an unbranded\n * install takes the logo arm. A configuration naming the shipped name explicitly takes it too —\n * it asked for the shipped name and gets the shipped presentation of it.\n */\nconst DashboardTitle: React.FC<{ name: string }> = ({ name }) =>\n name === DEFAULT_BRANDING.NAME ? <Text>{ASCII_LOGO}</Text> : <Text bold>{name}</Text>;\n\ntype DashboardProps = {\n /** Everything the screen paints, exactly as {@link formatDashboardText} is handed it. */\n data: DashboardData;\n onSelect: (command: DashboardCommand) => void;\n onCancel: () => void;\n};\n\nexport const Dashboard: React.FC<DashboardProps> = ({ data, onSelect, onCancel }) => {\n const { exit } = useApp();\n const { rows: terminalHeight } = useTerminalDimensions();\n\n return (\n <Box flexDirection=\"column\" height={terminalHeight}>\n <Box marginBottom={1}>\n <DashboardTitle name={data.name} />\n </Box>\n <Box marginBottom={1}>\n <Text>{dashboardCountLines(data).join(\"\\n\")}</Text>\n </Box>\n <SelectList\n items={DASHBOARD_OPTIONS}\n onSelect={(command) => {\n onSelect(command);\n exit();\n }}\n onCancel={() => {\n onCancel();\n exit();\n }}\n />\n </Box>\n );\n};\n\n/**\n * What this installation is, as the lines both dashboards paint between the title and the menu.\n *\n * **Shared because the two paths had diverged, not for reuse.** `showDashboard` branches on\n * `process.stdin.isTTY`, and only the text branch drew these — so the screen a person sits in\n * front of was less informative than the output they get by piping it, and no assertion could see\n * it, because each path was only ever compared against itself. One producer is what makes the two\n * unable to drift apart again.\n */\nexport function dashboardCountLines(data: DashboardData): string[] {\n const lines = [\n ` Skills: ${data.skillCount} installed`,\n ` Agents: ${data.agentCount} compiled`,\n ` Mode: ${INSTALL_MODE_LABELS[data.mode]}`,\n ];\n if (data.source) {\n lines.push(` Marketplace: ${data.source}`);\n }\n return lines;\n}\n\n/** Formats the dashboard summary as plain text lines (for non-interactive/test output). */\nexport function formatDashboardText(data: DashboardData): string {\n return [\n data.name,\n \"\",\n ...dashboardCountLines(data),\n \"\",\n ` [Edit] [Compile] [Doctor] [List]`,\n ].join(\"\\n\");\n}\n\n/**\n * Shows the project dashboard and returns the selected command (or null if cancelled).\n * In non-interactive environments (no TTY), prints the summary text and returns null.\n */\nexport async function showDashboard(\n projectDir: string,\n log?: (message: string) => void,\n): Promise<DashboardCommand | null> {\n const data = await getDashboardData(projectDir);\n\n // Non-interactive: print text summary and exit (CI, piped, tests)\n if (!process.stdin.isTTY) {\n const output = log ?? console.log;\n output(formatDashboardText(data));\n return null;\n }\n\n // First-wins resolution via promptValue; clearOnResolve repaints a clean\n // terminal before unmount (dashboard occupies the full height).\n const selectedCommand = await promptValue<DashboardCommand | null>(\n (resolve) => (\n <Dashboard\n data={data}\n onSelect={(command) => resolve(command)}\n onCancel={() => resolve(null)}\n />\n ),\n { onExit: null, clearOnResolve: true },\n );\n\n clearTerminalScreen();\n\n return selectedCommand;\n}\n\n/**\n * Why the dashboard is on screen.\n *\n * `\"init\"` — the user ran `cc init` in an already-installed directory. That is a request\n * to set this project up, so choosing Edit continues the setup: it must materialise the\n * project even if the wizard changes nothing.\n *\n * `\"standalone\"` — the bare `cc` dashboard. Edit is just an editor there; a pass with no\n * changes is an inspection and must leave the filesystem untouched.\n */\nexport type DashboardOrigin = \"init\" | \"standalone\";\n\n/** The extra argv a dashboard selection needs to carry its origin into the command. */\nfunction dashboardCommandArgv(command: DashboardCommand, origin: DashboardOrigin): string[] {\n if (command !== \"edit\" || origin !== \"init\") return [];\n return [`--${EDIT_PROJECT_SETUP_FLAG}`];\n}\n\n/**\n * Shared dashboard entry: when the project is already initialized, shows the\n * dashboard and runs the chosen command. Returns true when the project was\n * initialized (dashboard shown), false otherwise. Never exits the process —\n * callers decide (the init hook exits SUCCESS at its own call site).\n */\nexport async function runDashboardFlow(\n projectDir: string,\n config: Interfaces.Config,\n origin: DashboardOrigin,\n log?: (message: string) => void,\n): Promise<boolean> {\n const installation = await detectInstallation(projectDir);\n if (!installation) return false;\n\n const selectedCommand = await showDashboard(projectDir, log);\n if (selectedCommand) {\n await config.runCommand(selectedCommand, dashboardCommandArgv(selectedCommand, origin));\n }\n return true;\n}\n\n/**\n * What `init` decided to install, and the little each producer knows that the shared spine does\n * not. Keeping these on the value rather than branching on a flag downstream is what stops the\n * two paths growing separate copies of the install sequence.\n */\n/**\n * The marketplace this run was pointed at, as oclif hands it over.\n *\n * `marketplace` is a required key holding `string | undefined` rather than\n * `marketplace?: string` because that is what oclif produces: a non-required flag still gets\n * its key written on the parse result, set to `undefined` when it was not passed. Under\n * `exactOptionalPropertyTypes` the two are different types, and `?` would be describing a\n * producer that never omits the key.\n */\ntype SourceFlags = { marketplace: string | undefined };\n\ntype Selection = {\n result: WizardResultV2;\n sourceResult: SourceLoadResult;\n /**\n * The marketplace this selection was actually loaded from, which the shared spine records in\n * the written config. Carried on the value because a shared id may name one the command line\n * did not, and the install has to record where its skills really came from either way.\n */\n sourceFlags: SourceFlags;\n /** Whether a person is at the terminal, so the permission notice may wait for them. */\n interactive: boolean;\n /** What to say if the selection turns out to be empty — only the producer knows why it is. */\n emptyMessage: string;\n};\n\n/**\n * Whether a decoded selection would write anything into the user's own ~/.claude. Skills and\n * sub-agents are asked separately because either can be globally scoped on its own: a shared\n * configuration can pin every skill to the project and still send a sub-agent home, and the\n * reverse.\n */\nfunction writesGlobalContent(result: WizardResultV2): boolean {\n return (\n result.skills.some((skill) => skill.scope === \"global\") ||\n result.agentConfigs.some((agent) => agent.scope === \"global\")\n );\n}\n\n/**\n * Which marketplace a shared configuration installs from.\n *\n * A payload names the one its skills were fetched from, because a skill id carries whose skill it\n * is and never where that repository lives — so without the ref the load walks on to the default\n * public catalogue and installs a different repository's skill under the same id.\n *\n * `--marketplace` still outranks it: naming one is an instruction about THIS install, while the\n * payload's ref is a record of where the sharer's came from. A payload that names none leaves the\n * flag undefined, which puts the load back on the rungs it has always walked.\n */\nfunction sharedConfigSourceFlags(flags: SourceFlags, payload: SeedPayload): SourceFlags {\n return { marketplace: flags.marketplace ?? payload.marketplace };\n}\n\nexport default class Init extends BaseCommand {\n /**\n * The name this run prints itself under, resolved once on {@link install}'s spine because the\n * closing line is printed several calls below it. Same shape and same reason as `uninstall`'s\n * field: a plain `string` holding the shipped default rather than an optional every reader\n * would have to answer for.\n */\n private brandingName: string = DEFAULT_BRANDING.NAME;\n\n static summary = `Initialize ${DEFAULT_BRANDING.NAME} in this project`;\n static description =\n \"Interactive wizard to set up skills and agents. Supports Plugin Mode (native install) and Eject Mode (copy to .claude/).\";\n\n static examples = [\n {\n description: \"Start the setup wizard\",\n command: \"<%= config.bin %> <%= command.id %>\",\n },\n {\n description: \"Initialize from a custom marketplace\",\n command: \"<%= config.bin %> <%= command.id %> --marketplace github:org/marketplace\",\n },\n ];\n\n static flags = {\n marketplace: Flags.string({\n char: \"m\",\n description: \"Skills marketplace path or URL\",\n required: false,\n }),\n from: Flags.string({\n description: \"Install a configuration shared from agentsinc.sh by its id, without the wizard\",\n helpValue: \"<id>\",\n }),\n ui: Flags.boolean({\n description:\n \"Open agentsinc.sh instead of the terminal — the id --from names, or the catalogue\",\n default: false,\n }),\n };\n\n /**\n * The command in two statements: do the work, then answer for it.\n *\n * {@link install} owns every path through the setup and returns however it likes; the exit\n * code is decided once, here, after the last of them. Deciding it inside would mean deciding\n * it at each of that method's endings, and an ending added later would inherit the exit-0\n * default silently — which is the defect this pair exists to close. `edit` is two statements\n * for the same reason.\n */\n async run(): Promise<void> {\n await this.install();\n this.exitIfWorkIncomplete();\n }\n\n /**\n * The editor, opened on whatever `--from` named — or on nothing when it named nothing.\n *\n * **One rule, both commands (owner ruling 2026-08-24): `--ui` opens the command's SUBJECT, and\n * `--from` is what supplies one.** `edit --ui` alone opens this installation because that is\n * `edit`'s subject; `init --ui` alone opens the catalogue because a fresh directory has none.\n * Given an id, either opens that id — which is what makes a shared configuration something a\n * recipient can look at rather than only apply blind.\n *\n * No publish happens here and none is needed. `edit --ui` mints an id because an installation\n * is not a configuration the store holds yet; an id already IS one, so this is\n * `editorConfigUrl` and nothing else — no network, no marketplace, no catalogue load.\n *\n * The link is PRINTED first and opened second. Over a pipe, in CI, and on a machine with no\n * desktop session there is no browser to be anybody's — a link nobody can copy is the whole\n * loss, so opening one is the convenience on top and a failure to open is a warning beside a\n * link that still works.\n */\n private async openEditor(id: string | undefined): Promise<void> {\n const url = id === undefined ? EDITOR_URL : editorConfigUrl(id);\n\n this.log(id === undefined ? `Build it at ${url}` : `Open it at ${url}`);\n if (id === undefined) {\n this.log(`Then install what it gives you with '${CLI_INVOKE_COMMAND} init --from <id>'.`);\n } else {\n this.log(`To install it here instead, run '${CLI_INVOKE_COMMAND} init --from ${id}'.`);\n }\n\n if (!process.stdin.isTTY) return;\n\n const opened = await openUrl(url);\n if (!opened.ok) this.warn(opened.error);\n }\n\n /**\n * One spine, two producers. The wizard and a shared id differ only in *where the selection\n * comes from* — everything after it (the empty guard, the install pipeline) is identical, so it\n * lives here once rather than being written twice and drifting.\n */\n private async install(): Promise<void> {\n const { flags } = await this.parse(Init);\n const projectDir = process.cwd();\n\n // Above `ensureConfigReadable`, and above every read below it, because this route touches no\n // installation at all. A config too broken to load must not stop someone reaching the other\n // front door, and an id somebody shared is not this directory's business either.\n if (flags.ui) return this.openEditor(flags.from);\n\n // Every route below reads the configs first — to show a dashboard, to refuse a shared id, or\n // to inline the global one. One that exists but cannot be read is recreated, not installed\n // over, and saying so here is what keeps the raw loader error off the screen.\n await this.ensureConfigReadable(projectDir);\n\n // Read once on the spine, because the closing line is printed several calls below it. The\n // degrade arm of `resolveBrandingName` cannot fire here: the line above has already refused\n // every config this would read.\n this.brandingName = await this.resolveBrandingName(projectDir);\n\n // Only a bare `init` is diverted to the dashboard. An id is an explicit instruction to install\n // *that* configuration, so it overrides an existing installation instead.\n if (!flags.from && (await this.showDashboardIfInitialized(projectDir))) return;\n\n const selection = flags.from\n ? await this.selectionFromSharedConfig(flags.from, flags, projectDir)\n : await this.selectionFromWizard(flags, projectDir);\n\n if (!selection) this.exit(EXIT_CODES.CANCELLED);\n\n // On the spine rather than in either producer: a broken constraint is a fact about the\n // selection, not about where it came from, and `edit` reports the same fact the same way\n // the moment the wizard hands it one. Both producers run the same validator over the same\n // matrix — the wizard over what was chosen, `--from` over what survived the decode — so\n // what is said here is this catalog's verdict either way.\n this.reportValidationErrors(selection.result.validation);\n\n // A sub-agent is installable on its own — it has front-matter, a prompt and a compiled file\n // without owning a single skill — so only a selection with neither is nothing to install.\n if (selection.result.skills.length === 0 && selection.result.selectedAgents.length === 0) {\n // The producer supplies the wording because only it knows why empty means what it means:\n // nothing chosen, versus a payload this catalog cannot install.\n this.error(selection.emptyMessage, { exit: EXIT_CODES.ERROR });\n }\n\n await this.handleInstallation(\n selection.result,\n selection.sourceResult,\n selection.sourceFlags,\n selection.interactive,\n );\n }\n\n /** The interactive producer: load the source, run the wizard, return what was chosen. */\n private async selectionFromWizard(\n flags: SourceFlags,\n projectDir: string,\n ): Promise<Selection | null> {\n // The blank global config is created by writeProjectConfig() once the\n // wizard succeeds, never before it renders: a cancelled init must leave no\n // artifact that the next run could mistake for an existing installation.\n const isGlobalRoot = isHomeDirectory(projectDir);\n\n const { sourceResult, startupMessages } = await this.loadWizardInputsUnderSpinner(flags);\n\n const result = await this.runWizard(startupMessages, isGlobalRoot);\n if (!result) return null;\n\n return {\n result,\n sourceResult,\n sourceFlags: flags,\n // A person is already at the terminal, so the permission notice can wait for them.\n interactive: true,\n emptyMessage: \"No skills selected\",\n };\n }\n\n /**\n * Everything the wizard needs, loaded behind a spinner that comes down whichever way the\n * await ends.\n *\n * The cleanup is a `finally` because a source that cannot be loaded refuses the run from\n * inside this await, and oclif would otherwise paint its error under an Ink tree still\n * repainting over it. Never a `catch`: the throw reaches oclif untouched, or both the\n * error rendering and the exit code change with it.\n */\n private async loadWizardInputsUnderSpinner(flags: SourceFlags): Promise<{\n sourceResult: SourceLoadResult;\n startupMessages: StartupMessage[];\n }> {\n const { unmount, clear: clearSpinner } = render(\n <Spinner label={STATUS_MESSAGES.LOADING_SKILLS} />,\n );\n try {\n return await this.loadSourceOrFail(flags);\n } finally {\n clearSpinner();\n unmount();\n }\n }\n\n /**\n * The `--from <id>` producer: fetch and map, no wizard. Nothing here may assume a TTY — running\n * headless is most of why the flag exists.\n *\n * It is also greenfield-only, which is what two of the three refusals are: a shared\n * configuration is installed whole, so anything it would have to install over has to be\n * uninstalled first. The third is about the LOCATION rather than what is already in it — a\n * global installation holds only global-scoped content, and this is the one producer that never\n * asked. All three fire before anything is written.\n */\n private async selectionFromSharedConfig(\n id: string,\n flags: SourceFlags,\n projectDir: string,\n ): Promise<Selection> {\n await this.refuseInstalledProject(projectDir);\n\n this.log(`Fetching configuration ${id}...`);\n const fetched = await fetchSeedConfig(id);\n if (!fetched.ok) {\n this.error(fetched.error, { exit: EXIT_CODES.ERROR });\n }\n\n const sourceFlags = sharedConfigSourceFlags(flags, fetched.payload);\n const { sourceResult } = await this.loadSourceOrFail(sourceFlags);\n // Before the decode, because a skill the payload CARRIES answers to no catalogue: unseated,\n // its id is skipped like any other unknown one and its content is never read.\n const carriedSkills = this.registerExternalSkillsOrFail(\n fetched.payload,\n sourceResult.matrix,\n projectDir,\n );\n const { result, skippedSkillIds, skippedAgentNames } = this.decodeSeedOrFail(\n fetched.payload,\n sourceResult.matrix,\n );\n\n // The location refusal is `BaseCommand`'s, because `edit --from` reaches the same\n // contradiction through the other door and an invariant enforced on one producer is enforced\n // nowhere. It runs before {@link refuseBlockingGlobalInstall} because it needs no filesystem\n // probe to answer: where the install root is, and what the payload said, is all of it.\n this.refuseProjectScopedContentAtHome(result, projectDir);\n await this.refuseBlockingGlobalInstall(result);\n\n // After the refusals and before the install: every refusal on this path fires with nothing\n // written, and the copy step that follows finds these skills already where they belong.\n await this.writeCarriedSkills(carriedSkills);\n\n // Named, not counted. \"3 skills were skipped\" cannot be acted on; the ids can, and this is the\n // one moment the user can tell whether what they shared is what they are getting. Worded once,\n // in `messages.ts`, because `edit --from` reports the same skips about the same wire.\n if (skippedSkillIds.length > 0) this.warn(skippedUnknownSkills(skippedSkillIds));\n if (skippedAgentNames.length > 0) this.warn(skippedUnknownAgents(skippedAgentNames));\n\n if (result.skills.length > 0) {\n this.log(\n `Installing ${result.skills.length} skill(s) across ${result.selectedAgents.length} sub-agent(s)\\n`,\n );\n }\n\n return {\n result,\n sourceResult,\n sourceFlags,\n interactive: false,\n emptyMessage: `Configuration '${id}' contains no skills this catalog can install.`,\n };\n }\n\n /**\n * Refuses to install a shared configuration into a directory that already has one.\n *\n * Project-scoped detection rather than `detectInstallation`, whose global fallback would refuse\n * every clean project on a machine with a global install — including for a payload that never\n * goes near it. Whether a global install is in the way is a question about the PAYLOAD, and\n * {@link refuseBlockingGlobalInstall} is where it is asked.\n *\n * This runs before the fetch: there is nothing to learn from the network about a directory that\n * is already spoken for.\n */\n private async refuseInstalledProject(projectDir: string): Promise<void> {\n const installation = await detectProjectInstallation(projectDir);\n if (!installation) return;\n\n this.error(sharedConfigExistingInstall(installation.configPath), { exit: EXIT_CODES.ERROR });\n }\n\n /**\n * The other half of the same rule. A payload carrying global-scoped skills or sub-agents writes\n * into the user's own ~/.claude, so an installation there is in its way even when this project\n * is spotless. A payload with nothing global cannot reach that far and is never refused for it.\n */\n private async refuseBlockingGlobalInstall(result: WizardResultV2): Promise<void> {\n if (!writesGlobalContent(result)) return;\n\n const globalInstallation = await detectGlobalInstallation();\n if (!globalInstallation) return;\n\n this.error(sharedConfigGlobalInstall(globalInstallation.configPath), {\n exit: EXIT_CODES.ERROR,\n });\n }\n\n /**\n * The decode refuses a payload the config model has nowhere to write (see `seedToWizardResult`).\n * That is a failure of this command, reported with this command's exit code rather than left to\n * surface as an unhandled throw.\n */\n private decodeSeedOrFail(payload: SeedPayload, matrix: MergedSkillsMatrix): SeedMapping {\n try {\n return seedToWizardResult(payload, matrix);\n } catch (error) {\n this.handleError(error);\n }\n }\n\n /**\n * Seats the catalogue entries the payload carries with it, or refuses the run.\n *\n * The refusal is `registerExternalSkills`' own — a carried skill asked for as a plugin, which\n * no marketplace serves — and is reported with this command's exit code for the same reason the\n * decode's is.\n */\n private registerExternalSkillsOrFail(\n payload: SeedPayload,\n matrix: MergedSkillsMatrix,\n projectDir: string,\n ): ExternalSkillInstall[] {\n try {\n return registerExternalSkills(payload, matrix, projectDir);\n } catch (error) {\n this.handleError(error);\n }\n }\n\n /** Writes the skills the payload brought with it, and says which they were. */\n private async writeCarriedSkills(carried: ExternalSkillInstall[]): Promise<void> {\n if (carried.length === 0) return;\n\n await writeExternalSkills(carried);\n // Named rather than counted, like the skips: these are the entries no catalogue can explain,\n // so this line is the only place the user learns what arrived with the configuration itself.\n this.log(carriedSkillsWritten(carried.map((skill) => skill.id)));\n }\n\n private async showDashboardIfInitialized(projectDir: string): Promise<boolean> {\n return runDashboardFlow(projectDir, this.config, \"init\", (msg) => this.log(msg));\n }\n\n private async loadSourceOrFail(\n flags: SourceFlags,\n ): Promise<{ sourceResult: SourceLoadResult; startupMessages: StartupMessage[] }> {\n try {\n const loaded = await loadSource({\n // The one load that may CHOOSE a marketplace rather than read the stored one.\n caller: \"init\",\n ...(flags.marketplace !== undefined && { sourceFlag: flags.marketplace }),\n projectDir: process.cwd(),\n captureStartupMessages: true,\n });\n return { sourceResult: loaded.sourceResult, startupMessages: loaded.startupMessages };\n } catch (error) {\n this.error(getErrorMessage(error), {\n exit: EXIT_CODES.ERROR,\n });\n }\n }\n\n /**\n * `init`'s wizard opens on an empty selection, and can open on nothing else: it is reached\n * only once {@link showDashboardIfInitialized} has found no installation, and that check\n * falls back to the home directory — so a global roster to hydrate from would have diverted\n * this run to the dashboard before the wizard was built. Hydrating a saved selection is\n * `edit`'s job, and `Edit.runEditWizard` is where it happens.\n */\n private async runWizard(\n startupMessages: StartupMessage[],\n isGlobalRoot: boolean,\n ): Promise<WizardResultV2 | null> {\n return runWizardSession({\n hydrate: { isEditingFromGlobalScope: isGlobalRoot },\n props: {\n version: this.config.version,\n logo: ASCII_LOGO,\n startupMessages,\n },\n onCancel: () => this.log(\"Setup cancelled\"),\n clearTerminal: () => this.clearTerminal(),\n });\n }\n\n private async handleInstallation(\n result: WizardResultV2,\n sourceResult: SourceLoadResult,\n flags: SourceFlags,\n /**\n * Whether the caller can hold the terminal. The permission notice is an Ink app with no exit\n * of its own, so `waitUntilExit()` only ever resolves because a person is there to end it —\n * which is fine after the wizard and a hang everywhere else. `--from` sets this false: it has\n * to complete over a pipe and in CI.\n */\n interactive = true,\n ): Promise<void> {\n const projectDir = process.cwd();\n const activeSkills = result.skills.filter((s) => !s.excluded);\n const installMode = deriveInstallMode(activeSkills);\n const ejectedSkills = activeSkills.filter((s) => s.origin === EJECT_SOURCE);\n const pluginSkills = activeSkills.filter((s) => s.origin !== EJECT_SOURCE);\n\n this.logInstallPlan(installMode, ejectedSkills, pluginSkills);\n\n // Resolve marketplace up front — BEFORE any filesystem mutation. If\n // resolution fails in mixed mode, the hard-error must fire before\n // `copyEjectSkillsStep` copies anything to `.claude/skills/`, otherwise\n // we leave an orphaned half-install with no config.ts to recognise it.\n const resolvedMarketplace =\n pluginSkills.length > 0\n ? await this.requireMarketplaceOrExit(\n sourceResult,\n \"install plugin skills\",\n (marketplace) => this.log(`Registering marketplace \"${marketplace}\"...`),\n )\n : null;\n\n const copyResult =\n installMode === \"eject\" || installMode === \"mixed\"\n ? await this.copyEjectSkillsStep(ejectedSkills, projectDir, sourceResult, installMode)\n : null;\n\n if (resolvedMarketplace !== null) {\n await this.installPluginSkillsReported(\n pluginSkills,\n resolvedMarketplace,\n projectDir,\n sourceResult.matrix,\n );\n }\n // The shared install reporter hard-errors on any failure, so reaching here with\n // a resolved marketplace means plugin mode fully succeeded.\n const pluginModeSucceeded = resolvedMarketplace !== null;\n\n try {\n const { configResult, compileResult, agentScopeMap } = await this.writeConfigAndCompile(\n result,\n sourceResult,\n flags,\n );\n this.reportSuccess(\n configResult,\n compileResult,\n agentScopeMap,\n installMode,\n pluginModeSucceeded,\n copyResult,\n );\n\n await this.showPermissionNotice(projectDir, interactive);\n } catch (error) {\n this.handleError(error);\n }\n }\n\n /**\n * The permission notice, where there is one to show. It is an Ink app with no exit of its own,\n * so `waitUntilExit()` only ever resolves because a person is there to end it — which is fine\n * after the wizard and a hang everywhere else. Without a terminal to hold, one frame is\n * rendered and let go: the notice is information, not a prompt, so there is nothing to answer\n * and nothing to wait for.\n */\n private async showPermissionNotice(projectDir: string, interactive: boolean): Promise<void> {\n const permissionWarning = await checkPermissions(projectDir);\n if (!permissionWarning) return;\n\n if (!interactive) {\n const { unmount } = render(permissionWarning);\n unmount();\n return;\n }\n\n const { waitUntilExit } = render(permissionWarning);\n await waitUntilExit();\n }\n\n private logInstallPlan(\n installMode: InstallMode,\n ejectedSkills: WizardResultV2[\"skills\"],\n pluginSkills: WizardResultV2[\"skills\"],\n ): void {\n this.log(\"\\n\");\n this.log(`Selected ${ejectedSkills.length + pluginSkills.length} skills`);\n this.log(\n `Install mode: ${\n installMode === \"mixed\"\n ? `${INSTALL_MODE_LABELS.mixed} (${ejectedSkills.length} eject, ${pluginSkills.length} plugin)`\n : INSTALL_MODE_DESCRIPTIONS[installMode]\n }`,\n );\n }\n\n private async copyEjectSkillsStep(\n localSkills: WizardResultV2[\"skills\"],\n projectDir: string,\n sourceResult: SourceLoadResult,\n installMode: InstallMode,\n ): Promise<SkillCopyResult> {\n this.log(\"Copying skills to local directory...\");\n const copyResult = await copyLocalSkills(localSkills, projectDir, sourceResult);\n\n if (installMode === \"mixed\") {\n if (copyResult.projectCopied.length > 0 && copyResult.globalCopied.length > 0) {\n this.log(\n `Copied ${copyResult.totalCopied} local skills (${copyResult.projectCopied.length} project, ${copyResult.globalCopied.length} global)`,\n );\n } else if (copyResult.globalCopied.length > 0) {\n this.log(`Copied ${copyResult.globalCopied.length} local skills to ~/.claude/skills/`);\n } else {\n this.log(`Copied ${copyResult.projectCopied.length} local skills to .claude/skills/`);\n }\n } else {\n this.log(`Copied ${copyResult.totalCopied} skills to .claude/skills/\\n`);\n }\n\n return copyResult;\n }\n\n private async writeConfigAndCompile(\n result: WizardResultV2,\n sourceResult: SourceLoadResult,\n flags: SourceFlags,\n ): Promise<{\n configResult: Awaited<ReturnType<typeof writeProjectConfig>>;\n compileResult: CompilationResult;\n agentScopeMap: Map<AgentName, SkillScope>;\n }> {\n this.log(\"Generating configuration...\");\n const configResult = await writeProjectConfig({\n wizardResult: result,\n sourceResult,\n projectDir: process.cwd(),\n ...(flags.marketplace !== undefined && { sourceFlag: flags.marketplace }),\n });\n\n if (configResult.wasMerged) {\n this.log(`Merged with existing config at ${configResult.existingConfigPath}`);\n }\n\n this.log(`Configuration saved (${configResult.config.agents.length} agents)\\n`);\n this.reportUnassignedSkills(configResult.config);\n\n this.log(STATUS_MESSAGES.COMPILING_AGENTS);\n const cwd = process.cwd();\n const agentDefs = await loadAgentDefs();\n const { allSkills } = await discoverInstalledSkills(cwd);\n const agentScopeMap = buildAgentScopeMap(configResult.config);\n const compileResult = await compileAgentsAllScopes({\n projectDir: cwd,\n sourcePath: agentDefs.sourcePath,\n skills: allSkills,\n agentScopeMap,\n });\n this.reportCompilation(compileResult);\n\n this.reportPropagatedRecompile(configResult.propagation);\n\n return { configResult, compileResult, agentScopeMap };\n }\n\n /**\n * What the compile pass did, including the half this command used to drop.\n *\n * It read `compiled` and nothing else, so a pass that lost a sub-agent printed a number that\n * looked perfectly right — `compiled` counts successes, so it is correct either way — and the\n * failures reached no surface at all: no count, no reason, no exit code. A user's FIRST\n * install could silently land a roster missing a sub-agent.\n *\n * The compile is the last thing `init` does, so a failure here cannot be answered by aborting:\n * the skills are on disk and `config.ts` and `config-types.ts` describe them. What is owed is\n * the account, which {@link BaseCommand.exitIfWorkIncomplete} prints and answers for.\n */\n private reportCompilation(compileResult: CompilationResult): void {\n const { compiled, failed, warnings } = compileResult;\n const summary = `Compiled ${compiled.length} agents`;\n\n if (failed.length === 0) {\n this.log(`${summary}\\n`);\n return;\n }\n\n this.log(`${summary} (${failed.length} failed)\\n`);\n for (const warning of warnings) {\n this.warn(warning);\n }\n // Recorded off `failed` rather than off the warnings just printed: `warnings` also carries\n // entries that are not failures — a scope with nothing to compile contributes one on every\n // project-context run — and the ending must not file those as work owed.\n this.recordIncompleteWork(agentsNotCompiled(failed), INCOMPLETE_WORK_RECOVERY.RECOMPILE);\n }\n\n private reportSuccess(\n configResult: Awaited<ReturnType<typeof writeProjectConfig>>,\n compileResult: CompilationResult,\n agentScopeMap: Map<AgentName, SkillScope>,\n installMode: InstallMode,\n pluginModeSucceeded: boolean,\n copyResult: SkillCopyResult | null,\n ): void {\n // A run with work owed ends on the failure account instead — `initialized successfully!`\n // over a roster missing a sub-agent is the claim being withdrawn, not a line beside it.\n // Where the install landed is still reported below: that is what the account is about.\n if (!this.hasIncompleteWork) this.log(`${initSucceeded(this.brandingName)}\\n`);\n\n const isEjectOutput =\n installMode === \"eject\" || (installMode === \"mixed\" && !pluginModeSucceeded);\n if (isEjectOutput && copyResult && copyResult.totalCopied > 0) {\n this.reportSkillsCopied(copyResult);\n }\n this.reportAgentsCompiled(compileResult.compiled, agentScopeMap);\n this.reportConfiguration(configResult.configPath, agentScopeMap);\n }\n\n /**\n * Names the config that actually holds this install's assignments, and where a\n * recompile of them has to be run from.\n *\n * Split by the same `agentScopeMap` the two reporters above split on, because the\n * same scope decides both. A project config's `stack` is filtered down to\n * project-scoped agents on the way out, so a wholly GLOBAL install leaves it\n * carrying no assignment at all — naming it sends the user to a file with nothing\n * in it — and `compile` in this cwd runs the PROJECT pass, which recompiles no\n * global agent. At the home root both scopes resolve to one file and one pass, so\n * there is nothing to split and the project wording stands.\n */\n private reportConfiguration(\n projectConfigPath: string,\n agentScopeMap: Map<AgentName, SkillScope>,\n ): void {\n const cwd = process.cwd();\n const paths = {\n global: resolveInstallPaths(cwd, \"global\").configPath,\n project: projectConfigPath,\n };\n const split = splitAgentScopes(cwd, agentScopeMap);\n\n this.log(\"Configuration:\");\n for (const configPath of configsHoldingAssignments(split, paths)) {\n this.log(` ${configPath}`);\n }\n this.log(\"\");\n\n this.log(\"To customize agent-skill assignments:\");\n for (const [index, step] of customizationSteps(split, paths.global).entries()) {\n this.log(` ${index + 1}. ${step}`);\n }\n this.log(\"\");\n }\n\n /**\n * Reports where the skills actually landed. `copyLocalSkills` splits by scope,\n * so a default install driven from a project directory writes every skill\n * under HOME — reporting the project path there names a directory that was\n * never written.\n *\n * This block is a filesystem listing, so the entries are the on-disk directory\n * names — skill ids, not display names. `copySkillsToLocalFlattened` names each\n * destination directory after `skill.id`, so a user can copy any line and `cd`\n * into it.\n */\n private reportSkillsCopied(copyResult: SkillCopyResult): void {\n const cwd = process.cwd();\n const groups = isHomeDirectory(cwd)\n ? [\n {\n dir: resolveInstallPaths(cwd, \"project\").skillsDir,\n copied: [...copyResult.globalCopied, ...copyResult.projectCopied],\n },\n ]\n : [\n { dir: resolveInstallPaths(cwd, \"global\").skillsDir, copied: copyResult.globalCopied },\n { dir: resolveInstallPaths(cwd, \"project\").skillsDir, copied: copyResult.projectCopied },\n ].filter((group) => group.copied.length > 0);\n\n for (const group of groups) {\n this.log(\"Skills copied to:\");\n this.log(` ${group.dir}`);\n for (const copied of group.copied) {\n this.log(` ${copied.skillId}/`);\n }\n this.log(\"\");\n }\n }\n\n /**\n * Reports where the agents actually landed, mirroring the scope split\n * `compileAgentsAllScopes` performs: one pass at the home root, otherwise a\n * global pass under HOME and a project pass under the project directory.\n */\n private reportAgentsCompiled(\n compiled: AgentName[],\n agentScopeMap: Map<AgentName, SkillScope>,\n ): void {\n const cwd = process.cwd();\n const groups = isHomeDirectory(cwd)\n ? [{ dir: resolveInstallPaths(cwd, \"project\").agentsDir, agents: compiled }]\n : [\n {\n dir: resolveInstallPaths(cwd, \"global\").agentsDir,\n agents: compiled.filter((name) => agentScopeMap.get(name) === \"global\"),\n },\n {\n dir: resolveInstallPaths(cwd, \"project\").agentsDir,\n agents: compiled.filter((name) => agentScopeMap.get(name) !== \"global\"),\n },\n ].filter((group) => group.agents.length > 0);\n\n for (const group of groups) {\n this.log(\"Agents compiled to:\");\n this.log(` ${group.dir}`);\n for (const agentName of group.agents) {\n this.log(` ${agentName}.md`);\n }\n this.log(\"\");\n }\n }\n}\n\n/** The two config files an install can write, as the closing block refers to them. */\ntype ConfigPaths = { global: string; project: string };\n\n/** How this install's sub-agents fall across the two scopes, seen from the directory it ran in. */\ntype AgentScopeSplit = { globalAgentCount: number; isGlobalOnly: boolean };\n\n/**\n * At the home root the two scopes resolve to ONE config file and ONE compile pass, so there\n * is nothing to split and the split reports none — which is what leaves the project wording\n * standing there unchanged. Same fork `reportAgentsCompiled` makes over the same question.\n */\nfunction splitAgentScopes(cwd: string, agentScopeMap: Map<AgentName, SkillScope>): AgentScopeSplit {\n if (isHomeDirectory(cwd)) return { globalAgentCount: 0, isGlobalOnly: false };\n\n const scopes = [...agentScopeMap.values()];\n const globalAgentCount = scopes.filter((scope) => scope === \"global\").length;\n return {\n globalAgentCount,\n isGlobalOnly: globalAgentCount > 0 && globalAgentCount === scopes.length,\n };\n}\n\n/**\n * The config file(s) this install's assignments actually landed in. A wholly global install\n * has none in the project file — the writer filters its `stack` down to project-scoped\n * agents — so naming it would send the user to a file with nothing in it.\n */\nfunction configsHoldingAssignments(split: AgentScopeSplit, paths: ConfigPaths): string[] {\n if (split.isGlobalOnly) return [paths.global];\n if (split.globalAgentCount > 0) return [paths.global, paths.project];\n return [paths.project];\n}\n\n/**\n * What changing an assignment takes, in the order it takes it. The compile step is the half\n * that has to be scope-aware: `compile` run in a project directory performs the PROJECT pass\n * only, so it recompiles no global agent — which `globalScopedAgentsHint` already says, in\n * the words `compile` itself says it in when it lands in the mirror image of this state.\n */\nfunction customizationSteps(split: AgentScopeSplit, globalConfigPath: string): string[] {\n if (split.isGlobalOnly) {\n return [`Edit ${globalConfigPath}`, globalScopedAgentsHint(split.globalAgentCount)];\n }\n\n return [\n `Edit ${CLAUDE_SRC_DIR}/${STANDARD_FILES.CONFIG_TS}`,\n `Run '${CLI_INVOKE_COMMAND} compile' to regenerate agents`,\n ...(split.globalAgentCount > 0 ? [globalScopedAgentsHint(split.globalAgentCount)] : []),\n ];\n}\n\nexport type DashboardData = {\n /**\n * The name the dashboard is titled with — `branding.name` where the configuration supplies one\n * and {@link DEFAULT_BRANDING.NAME} otherwise. Carried on the data rather than read by either\n * consumer so {@link formatDashboardText} stays a pure function of what it is handed, and so\n * the one place that reaches a configuration is the one that already loads it.\n *\n * **Both of {@link showDashboard}'s branches read it, and that is the invariant to keep.** This\n * field was resolved for the piped branch alone for as long as it was, while the `Dashboard`\n * component was handed only its callbacks and painted {@link ASCII_LOGO} — so the dashboard a\n * person actually sees was the one surface `branding.name` never reached, and every spec on the\n * subject drove through a pipe and could not see it.\n */\n name: string;\n skillCount: number;\n agentCount: number;\n mode: InstallMode;\n source?: string;\n};\n\n/**\n * Gathers dashboard data from the installation and project config.\n *\n * Both counts come from the same scope-aware installation so the summary cannot\n * mix a project-only figure with a global one — a default install driven from a\n * project directory puts every skill and agent under HOME.\n */\nexport async function getDashboardData(projectDir: string): Promise<DashboardData> {\n // ABORT is the posture on `resolveBranding`, and it is the one already in force: the\n // `loadProjectConfig` beside it raises for the same file, so a configuration that cannot be\n // evaluated fails this call whether branding is read or not. Nothing is degraded here that was\n // not already, and the dashboard is only reached once an installation has been detected.\n const [info, loaded, branding] = await Promise.all([\n getInstallationInfo(),\n loadProjectConfig(projectDir),\n resolveBranding(projectDir),\n ]);\n\n const activeSkills = loaded?.config.skills.filter((s) => !s.excluded);\n const skillCount = info?.skillCount ?? 0;\n const agentCount = info?.agentCount ?? 0;\n const mode = info?.mode ?? (activeSkills ? deriveInstallMode(activeSkills) : \"eject\");\n const source = loaded?.config.marketplace;\n\n return {\n name: branding.name,\n skillCount,\n agentCount,\n mode,\n ...(source !== undefined && { source }),\n };\n}\n","import React from \"react\";\nimport { z } from \"zod\";\n\nimport { Text, Box } from \"ink\";\nimport path from \"path\";\n\nimport { CLAUDE_DIR, CLI_COLORS, MAX_CONFIG_FILE_SIZE, STANDARD_FILES } from \"../consts\";\nimport { fileExists, readFileSafe } from \"../utils/fs\";\nimport { warn } from \"../utils/logger\";\nimport { settingsFileSchema } from \"./schemas\";\n\ntype SettingsFile = z.infer<typeof settingsFileSchema>;\ntype PermissionConfig = NonNullable<SettingsFile[\"permissions\"]>;\n\n/**\n * Reads one settings file's permissions block; undefined when absent, malformed, or empty.\n *\n * settings.json belongs to Claude Code, which adds keys on its own release schedule. This CLI\n * consumes `permissions` and owns nothing else in the file, so it stays silent about every other\n * field rather than warning about settings it has no standing to judge.\n */\nasync function readSettingsPermissions(filePath: string): Promise<PermissionConfig | undefined> {\n if (!(await fileExists(filePath))) return undefined;\n try {\n const content = await readFileSafe(filePath, MAX_CONFIG_FILE_SIZE);\n const raw: unknown = JSON.parse(content);\n const result = settingsFileSchema.safeParse(raw);\n const parsed: SettingsFile = result.success ? result.data : {};\n return parsed.permissions;\n } catch {\n warn(`Malformed settings file at '${filePath}' — skipping`);\n return undefined;\n }\n}\n\n/** Permissions from the first settings file that defines them — settings.local.json wins. */\nasync function loadPermissions(projectRoot: string): Promise<PermissionConfig | undefined> {\n const settingsPath = path.join(projectRoot, CLAUDE_DIR, STANDARD_FILES.SETTINGS_JSON);\n const localSettingsPath = path.join(projectRoot, CLAUDE_DIR, STANDARD_FILES.SETTINGS_LOCAL_JSON);\n\n for (const filePath of [localSettingsPath, settingsPath]) {\n const permissions = await readSettingsPermissions(filePath);\n if (permissions) return permissions;\n }\n return undefined;\n}\n\nexport async function checkPermissions(projectRoot: string): Promise<React.ReactElement | null> {\n const permissions = await loadPermissions(projectRoot);\n\n if (!permissions) {\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={CLI_COLORS.WARNING} padding={1}>\n <Text bold color={CLI_COLORS.WARNING}>\n Permission Notice\n </Text>\n <Text>No permissions configured in .claude/settings.json</Text>\n <Text>Agents will prompt for approval on each tool use.</Text>\n <Text> </Text>\n <Text>For autonomous operation, add to .claude/settings.json:</Text>\n <Text> </Text>\n <Text color={CLI_COLORS.DIM}>{\"{\"}</Text>\n <Text color={CLI_COLORS.DIM}>{' \"permissions\": {'}</Text>\n <Text color={CLI_COLORS.DIM}>{' \"allow\": ['}</Text>\n <Text color={CLI_COLORS.DIM}>{' \"Read(*)\",'}</Text>\n <Text color={CLI_COLORS.DIM}>{' \"Bash(git *)\",'}</Text>\n <Text color={CLI_COLORS.DIM}>{' \"Bash(bun *)\"'}</Text>\n <Text color={CLI_COLORS.DIM}>{\" ]\"}</Text>\n <Text color={CLI_COLORS.DIM}>{\" }\"}</Text>\n <Text color={CLI_COLORS.DIM}>{\"}\"}</Text>\n </Box>\n );\n }\n\n const hasRestrictiveBash = permissions.deny?.some(\n (rule) => rule === \"Bash(*)\" || rule === \"Bash\",\n );\n const hasNoAllows = !permissions.allow || permissions.allow.length === 0;\n\n if (hasRestrictiveBash || hasNoAllows) {\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={CLI_COLORS.WARNING} padding={1}>\n <Text bold color={CLI_COLORS.WARNING}>\n Permission Warnings\n </Text>\n {hasRestrictiveBash && (\n <Text>\n ⚠ Bash is denied in permissions. Some agents require Bash for git, testing, and build\n commands.\n </Text>\n )}\n {hasNoAllows && (\n <Text>⚠ No allow rules configured. Agents will prompt for each tool use.</Text>\n )}\n </Box>\n );\n }\n\n return null;\n}\n"],"mappings":"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","names":["Box","Text","jsx","jsxs","Text","Box"]}