MCPcopy
hub / github.com/EveryInc/compound-engineering-plugin / writeCodexBundle

Function writeCodexBundle

src/targets/codex.ts:30–172  ·  view source on GitHub ↗
(
  outputRoot: string,
  bundle: CodexBundle,
  options: CodexWriteOptions = {},
)

Source from the content-addressed store, hash-verified

28}
29
30export async function writeCodexBundle(
31 outputRoot: string,
32 bundle: CodexBundle,
33 options: CodexWriteOptions = {},
34): Promise<void> {
35 const codexRoot = resolveCodexRoot(outputRoot, options)
36 await ensureDir(codexRoot)
37
38 const pluginName = bundle.pluginName ? sanitizeCodexPathComponent(bundle.pluginName) : undefined
39 const manifest = pluginName ? await readInstallManifest(codexRoot, pluginName) : null
40 const currentPrompts = bundle.prompts.map((prompt) => `${sanitizePathName(prompt.name)}.md`)
41 const agents = bundle.agents ?? []
42 const agentsRoot = pluginName
43 ? path.join(codexRoot, "agents", pluginName)
44 : path.join(codexRoot, "agents")
45 const currentAgents = agents.map((agent) => `${sanitizePathName(agent.name)}.toml`)
46 assertNoCodexAgentFilenameCollisions(agents)
47
48 if (bundle.prompts.length > 0) {
49 const promptsDir = path.join(codexRoot, "prompts")
50 await cleanupRemovedPrompts(promptsDir, manifest, currentPrompts)
51 for (const prompt of bundle.prompts) {
52 await writeText(path.join(promptsDir, `${sanitizePathName(prompt.name)}.md`), prompt.content + "\n")
53 }
54 } else if (pluginName) {
55 await cleanupRemovedPrompts(path.join(codexRoot, "prompts"), manifest, [])
56 }
57
58 const skillsRoot = pluginName
59 ? path.join(codexRoot, "skills", pluginName)
60 : path.join(codexRoot, "skills")
61 // Include `externallyManagedSkillNames` so agents-only installs (default
62 // `--to codex`) treat skills installed via Codex's native plugin flow as
63 // "current" for cleanup purposes. Without this, `cleanupLegacyAgentSkillDirs`
64 // would see an empty `currentSkills` set and sweep allow-listed names such
65 // as `ce-plan` out of `.codex/skills/<plugin>/` into legacy-backup on every
66 // re-run of `install --to codex`.
67 const currentSkills = Array.from(new Set([
68 ...bundle.skillDirs.map((skill) => sanitizePathName(skill.name)),
69 ...bundle.generatedSkills.map((skill) => sanitizePathName(skill.name)),
70 ...(bundle.externallyManagedSkillNames ?? []).map((name) => sanitizePathName(name)),
71 ]))
72 await cleanupRemovedSkills(skillsRoot, manifest, currentSkills)
73
74 if (bundle.skillDirs.length > 0) {
75 for (const skill of bundle.skillDirs) {
76 const targetDir = path.join(skillsRoot, sanitizePathName(skill.name))
77 await cleanupCurrentManagedSkillDir(targetDir, manifest, sanitizePathName(skill.name))
78 await copySkillDir(
79 skill.sourceDir,
80 targetDir,
81 (content) => transformContentForCodex(content, bundle.invocationTargets, {
82 unknownSlashBehavior: "preserve",
83 }),
84 )
85 }
86 }
87

Callers 2

index.tsFile · 0.90

Calls 15

ensureDirFunction · 0.90
sanitizePathNameFunction · 0.90
writeTextFunction · 0.90
copySkillDirFunction · 0.90
transformContentForCodexFunction · 0.90
copyDirFunction · 0.90
isSafeManagedPathFunction · 0.90
backupFileFunction · 0.90
writeTextSecureFunction · 0.90
resolveCodexRootFunction · 0.85
renderCodexAgentTomlFunction · 0.85

Tested by

no test coverage detected