fix(targets): nest colon-separated command names into directories

On Windows/NTFS, colons are reserved for alternate data streams, so
filenames like "ce:plan.md" are invalid. Split colon-separated command
names into nested directories (e.g. "ce:plan" -> "ce/plan.md"),
matching the approach already used by the Qwen target.

Applied to opencode, droid, and gemini targets.

Fixes #226

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Matt Van Horn
2026-03-10 16:58:42 -07:00
parent e426799f85
commit a84682cd35
3 changed files with 31 additions and 3 deletions

View File

@@ -9,7 +9,16 @@ export async function writeDroidBundle(outputRoot: string, bundle: DroidBundle):
if (bundle.commands.length > 0) {
await ensureDir(paths.commandsDir)
for (const command of bundle.commands) {
await writeText(path.join(paths.commandsDir, `${command.name}.md`), command.content + "\n")
// Split colon-separated names into nested directories (e.g. "ce:plan" -> "ce/plan.md")
// to avoid colons in filenames which are invalid on Windows/NTFS
const parts = command.name.split(":")
if (parts.length > 1) {
const nestedDir = path.join(paths.commandsDir, ...parts.slice(0, -1))
await ensureDir(nestedDir)
await writeText(path.join(nestedDir, `${parts[parts.length - 1]}.md`), command.content + "\n")
} else {
await writeText(path.join(paths.commandsDir, `${command.name}.md`), command.content + "\n")
}
}
}

View File

@@ -20,7 +20,16 @@ export async function writeGeminiBundle(outputRoot: string, bundle: GeminiBundle
if (bundle.commands.length > 0) {
for (const command of bundle.commands) {
await writeText(path.join(paths.commandsDir, `${command.name}.toml`), command.content + "\n")
// Split colon-separated names into nested directories (e.g. "ce:plan" -> "ce/plan.toml")
// to avoid colons in filenames which are invalid on Windows/NTFS
const parts = command.name.split(":")
if (parts.length > 1) {
const nestedDir = path.join(paths.commandsDir, ...parts.slice(0, -1))
await ensureDir(nestedDir)
await writeText(path.join(nestedDir, `${parts[parts.length - 1]}.toml`), command.content + "\n")
} else {
await writeText(path.join(paths.commandsDir, `${command.name}.toml`), command.content + "\n")
}
}
}

View File

@@ -75,7 +75,17 @@ export async function writeOpenCodeBundle(outputRoot: string, bundle: OpenCodeBu
}
for (const commandFile of bundle.commandFiles) {
const dest = path.join(openCodePaths.commandDir, `${commandFile.name}.md`)
// Split colon-separated names into nested directories (e.g. "ce:plan" -> "ce/plan.md")
// to avoid colons in filenames which are invalid on Windows/NTFS
const parts = commandFile.name.split(":")
let dest: string
if (parts.length > 1) {
const nestedDir = path.join(openCodePaths.commandDir, ...parts.slice(0, -1))
await ensureDir(nestedDir)
dest = path.join(nestedDir, `${parts[parts.length - 1]}.md`)
} else {
dest = path.join(openCodePaths.commandDir, `${commandFile.name}.md`)
}
const cmdBackupPath = await backupFile(dest)
if (cmdBackupPath) {
console.log(`Backed up existing command file to ${cmdBackupPath}`)