手写SKILL.md解析器会误读合法YAML
AI 总结
某技能包开发者发现,用于读取 SKILL.md 前置信息的零依赖解析器会误处理多种合法 YAML,包括折叠描述、单引号字符串、尾部注释和嵌套元数据键。与 Node 20.19.2 下的 js-yaml 4.3.2 对比后,解析器甚至可能用嵌套值静默覆盖技能的触发描述。拟议修改将明确拒绝多行标量,正确处理引号和注释,忽略嵌套键,并收紧元数据校验。
深度见解
这些已复现的问题会影响 Claude Code、Cursor、Trae 和 Codex 的技能安装,说明一个简短的前置信息解析器也可能无声地错误配置 AI 编程工具。
我有个给毕业设计写论文用的技能包,一份 SKILL.md 能装给 Claude Code、Cursor、Trae、Codex 四个工具。安装脚本零依赖,读 SKILL.md 头部的 frontmatter 是自己写的二十来行代码。之前写过输出那一侧:拼回 YAML 时要转义。这次看的是读入这一侧:别人照着 YAML 的正常写法写一个技能,我的解析器能不能读对。
结论是有好几种合法的 YAML 写法会被读错,而且校验脚本 check.js 有时候拦下了、但报的原因不对,有时候干脆放过去了。下面所有结果都是我在 Node 20.19.2 上实际跑出来的,对照用的是 js-yaml 4.3.2。
解析器长什么样
function unquote(v) {
if (/^".*"$/.test(v)) { try { return JSON.parse(v) } catch { return v.slice(1, -1) } }
return v
}
function parseSkill(file) {
const raw = fs.readFileSync(file, 'utf8').replace(/\r\n/g, '\n')
const m = raw.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/)
const meta = {}
if (m) for (const line of m[1].split('\n')) {
const i = line.indexOf(':')
if (i > 0) meta[line.slice(0, i).trim()] = unquote(line.slice(i + 1).trim())
}
return { meta, body: m ? m[2] : raw }
}