fix: harden codex copied skill rewriting (#285)

This commit is contained in:
Kieran Klaassen
2026-03-16 21:25:59 -07:00
committed by GitHub
parent 82c1fe86df
commit 6f561f94b4
6 changed files with 111 additions and 3 deletions

View File

@@ -37,12 +37,17 @@ async function loadPersonalSkills(skillsDir: string): Promise<ClaudeSkill[]> {
try {
await fs.access(skillPath)
const raw = await fs.readFile(skillPath, "utf8")
const { data } = parseFrontmatter(raw)
// Resolve symlink to get the actual source directory
const sourceDir = entry.isSymbolicLink()
? await fs.realpath(entryPath)
: entryPath
let data: Record<string, unknown> = {}
try {
const raw = await fs.readFile(skillPath, "utf8")
data = parseFrontmatter(raw).data
} catch {
// Keep syncing the skill even if frontmatter is malformed.
}
skills.push({
name: entry.name,
description: data.description as string | undefined,

View File

@@ -66,7 +66,12 @@ async function copyCodexSkillDir(
if (entry.name === "SKILL.md") {
const content = await readText(sourcePath)
await writeText(targetPath, transformContentForCodex(content, invocationTargets))
await writeText(
targetPath,
transformContentForCodex(content, invocationTargets, {
unknownSlashBehavior: "preserve",
}),
)
continue
}

View File

@@ -3,6 +3,10 @@ export type CodexInvocationTargets = {
skillTargets: Record<string, string>
}
export type CodexTransformOptions = {
unknownSlashBehavior?: "prompt" | "preserve"
}
/**
* Transform Claude Code content to Codex-compatible content.
*
@@ -18,10 +22,12 @@ export type CodexInvocationTargets = {
export function transformContentForCodex(
body: string,
targets?: CodexInvocationTargets,
options: CodexTransformOptions = {},
): string {
let result = body
const promptTargets = targets?.promptTargets ?? {}
const skillTargets = targets?.skillTargets ?? {}
const unknownSlashBehavior = options.unknownSlashBehavior ?? "prompt"
const taskPattern = /^(\s*-?\s*)Task\s+([a-z][a-z0-9:-]*)\(([^)]+)\)/gm
result = result.replace(taskPattern, (_match, prefix: string, agentName: string, args: string) => {
@@ -45,6 +51,9 @@ export function transformContentForCodex(
if (skillTargets[normalizedName]) {
return `the ${skillTargets[normalizedName]} skill`
}
if (unknownSlashBehavior === "preserve") {
return match
}
return `/prompts:${normalizedName}`
})