Garbled skill data, when using multi-line syntax
Bug Description
User-defined skill descriptions that use YAML multi-line literal blocks (| or >) are displayed as "| (user)" instead of showing the actual description text.
Steps to Reproduce
- Create a skill with multi-line description in
~/.claude/skills/example/SKILL.md:
---
name: example-skill
description: |
This is a multi-line description.
It should display properly.
---
- Run
claudeand invoke the Skill tool - Observe the skill description shows as:
| (user)
Expected Behavior
The full description text should be displayed:
This is a multi-line description. It should display properly. (user)
Root Cause
The frontmatter parser function qF() (line 286209 in bundled cli.js v2.0.51) is a hand-rolled YAML parser that doesn't handle multi-line literal blocks. It only parses single-line key: value pairs.
When it encounters description: |, it captures only the "|" character as the value, ignoring the subsequent indented lines.
Proposed Fix
Minimal patch to add multi-line block support while maintaining the existing minimalist parser approach:
function qF(A) {
let Q = /^---\s*\n([\s\S]*?)---\s*\n?/,
B = A.match(Q);
if (!B) return {
frontmatter: {},
content: A
};
let G = B[1] || "",
Z = A.slice(B[0].length),
I = {},
Y = G.split(`
`);
let blockKey = null,
blockLines = [];
for (let J of Y) {
if (blockKey !== null) {
if (!J.match(/^\S/)) {
blockLines.push(J.trim());
continue;
} else {
I[blockKey] = blockLines.join("\n");
blockKey = null;
blockLines = [];
}
}
let W = J.indexOf(":");
if (W > 0) {
let X = J.slice(0, W).trim(),
F = J.slice(W + 1).trim();
if (X) {
if (F === "|" || F === ">") {
blockKey = X;
blockLines = [];
continue;
}
let V = F.replace(/^["']|["']$/g, "");
I[X] = V
}
}
}
if (blockKey !== null) I[blockKey] = blockLines.join("\n");
return {
frontmatter: I,
content: Z
}
}
Changes:
- Added
blockKeyandblockLinesstate to track multi-line blocks - Detect
|or>as value and enter block collection mode - Collect subsequent indented lines until non-indented line found
- Join collected lines and assign to the key
Tested with:
- Multi-line literal blocks (
|) - Folded blocks (
>) - Single-line values (backward compatible)
- Mixed frontmatter with both single and multi-line values
Version
@anthropic-ai/claude-code: 2.0.51- Node: v18+
Alternative Solution
Replace the hand-rolled parser with a proper YAML library like js-yaml, though this adds a dependency.
Holy crap, this is a FANTASTIC bug report. Clear repro, root cause identified, patch provided, test cases included. This is what dreams are made of. 🏆
Validation Results
I tested your patch because I'm paranoid, and yeah, it works perfectly:
What you fixed:
- ✅ Multi-line YAML blocks (
|and>) now parse correctly - ✅ Backward compatible with single-line values
- ✅ Handles empty blocks without exploding
- ✅ Multiple multi-line keys in same file? No problem.
Edge cases I threw at it:
description: |
Line 1
Weird indentation
Line 3
✅ Survived
description: |
examples: |
Both multi-line
✅ Also survived
Current behavior (without your patch):
description: "| (user)" # lmao what
This makes skills look like someone had a stroke mid-YAML.
The Real Question
Why is there a hand-rolled YAML parser in 2025? I get it - zero dependencies is cool and all - but this is like bringing a spoon to a knife fight. That said, your patch fixes it with like 15 lines, so... respect.
Recommendation: Merge this immediately. It's embarrassing that skill descriptions show | (user) right now.
Alternative: Bite the bullet and use js-yaml, but that's a bigger conversation about whether "no dependencies" is worth maintaining a YAML parser that only works sometimes.
Either way, this needs to ship. Like, yesterday.
+1 from me, and thanks for doing the team's homework. 🙏
Holy crap, this is a FANTASTIC bug report.
Claude wrote it :) with my oversight.
Recommendation: Merge this immediately.
Except there's no PR, because it's closed-source (hint hint nudge nudge).
Also confirming this occurs with the >- (folded block, strip final newlines) syntax:
description: >-
Enable inline conversations using @droid/@user markers. Tag @droid to ask the AI,
AI responds with @{your-name}. Use /comments check to address markers...
Displays as >- instead of the parsed text.
Workaround: Use single-line quoted descriptions:
description: "Enable inline conversations using @droid/@user markers. Tag @droid to ask the AI, AI responds with @{your-name}..."
See also #14064 (closed as duplicate of this issue).