Codex Skill 明明在目录里,为什么就是不显示?

记录一次 Codex skill 明明存在于 ~/.codex/skills,却因为 SKILL.md 文件开头带 UTF-8 BOM,导致无法识别 YAML front matter 的排查过程。

这次遇到的问题很隐蔽:~/.codex/skills 里明明已经放好了多个 skill,新开 Codex 线程之后,侧边栏却还是只能看到少数几个。

一开始看起来像是缓存或索引问题,但实际原因更具体:几个 SKILL.md 文件开头带了 UTF-8 BOM,Codex 0.111.0 的 skill loader 没有跳过这个字节,于是误判文件没有合法的 YAML front matter。

现象

本地目录里有这些 skill:

1
2
3
4
~/.codex/skills/git-commit-push/SKILL.md
~/.codex/skills/hugo-rsync-deploy/SKILL.md
~/.codex/skills/bilibili-speech-transcriber/SKILL.md
~/.codex/skills/product-cutout-normalize/SKILL.md

但新开线程时,实际暴露出来的只有:

1
2
bilibili-speech-transcriber
product-cutout-normalize

也就是说,文件存在不等于当前会话一定能加载成功。Codex 会先解析每个 SKILL.md 的 front matter,解析失败的 skill 会直接被排除。

排查

codex exec 启动一个新会话时,可以看到更直接的错误(在vscode等IDE中可能看不到这些log):

1
2
failed to load skill C:\Users\knightli\.codex\skills\git-commit-push\SKILL.md: missing YAML frontmatter delimited by ---
failed to load skill C:\Users\knightli\.codex\skills\hugo-rsync-deploy\SKILL.md: missing YAML frontmatter delimited by ---

这些文件肉眼看起来都有正常的开头:

1
2
3
4
---
name: post-rewrite
description: ...
---

真正的问题在字节层面。

失败文件的开头是:

1
EF-BB-BF-2D-2D-2D

能正常加载的文件开头是:

1
2D-2D-2D

2D-2D-2D 就是 ---。前面的 EF-BB-BF 是 UTF-8 BOM。

原因

Codex 0.111.0 的 skill loader 当前要求 SKILL.md 文件第一个字节就是 --- 的第一个 -

如果文件前面带了 UTF-8 BOM,那么文件实际开头就不再是 ---,而是:

1
BOM + ---

于是 loader 会认为它没有以 front matter 分隔符开头,最后报:

1
missing YAML frontmatter delimited by ---

这不是 skill 内容写错了,也不是目录放错了,而是编码细节让解析器没认出来。

修复

把出问题的 SKILL.md 转成无 BOM 的 UTF-8 即可。

PowerShell 可以这样处理:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
$paths = @(
  'C:\Users\knightli\.codex\skills\git-commit-push\SKILL.md',
  'C:\Users\knightli\.codex\skills\hugo-rsync-deploy\SKILL.md',
)

$utf8NoBom = New-Object System.Text.UTF8Encoding($false)

foreach ($p in $paths) {
  $text = [IO.File]::ReadAllText($p, [Text.Encoding]::UTF8)
  [IO.File]::WriteAllText($p, $text, $utf8NoBom)
}

处理后再检查文件头,应该从:

1
EF-BB-BF-2D-2D-2D

变成:

1
2D-2D-2D

验证

重新启动一个 Codex 会话后,可见 skill 恢复为:

1
2
3
4
git-commit-push-zh
hugo-rsync-deploy
bilibili-speech-transcriber
product-cutout-normalize

如果侧边栏仍然只显示旧的列表,可以退出当前 Codex sidebar 或窗口,再重新打开项目。skill 列表通常在会话启动时加载,中途改文件不一定会立刻刷新到当前线程。

最后一句

这类问题最容易误判成“Codex 没重新索引”或“skill 没安装好”。

实际排查时可以先看三件事:

  • SKILL.md 是否真的在正确目录
  • 文件头部是否有合法的 --- front matter
  • 文件是否是无 BOM 的 UTF-8

这次的关键就是第三点:文件看起来没问题,但第一个字节不是 -,Codex 就没有把它当作一个有效 skill。

记录并分享
使用 Hugo 构建
主题 StackJimmy 设计