What happened?
list_skills / get_skill return the literal YAML block-scalar indicator (| or >) as a skill's description when the skill's SKILL.md frontmatter uses a block scalar:
---
name: browse
description: |
Fast headless browser for QA testing and site dogfooding. Navigate any URL...
---
→ catalog entry comes back as "description": "|". Affects every skill authored with description: | or description: >. Single-line description: ... skills are fine. triggers/tools parse correctly, and get_skill still returns the full prose body — so it's a catalog-display issue, not data loss.
What did you expect?
The folded block-scalar content as the one-line description (or, minimally, the body's first prose line via the existing firstProseLine fallback).
Steps to reproduce
- Author a skill whose
SKILL.md frontmatter uses description: | (block scalar) with the text on the indented lines below.
- Enable
mcp.publish_skills and point GBRAIN_SKILLS_DIR at the skills dir.
- Call
list_skills over MCP → that skill's description is "|" (or ">").
Environment
- gbrain version: 0.42.1.0
- OS: macOS 26.5 (Darwin 25.5.0)
- Bun version: 1.3.13
- Database: self-hosted (PGLite)
gbrain doctor --json output
N/A — this is a static-analysis bug in src/core/skill-catalog.ts (frontmatter
description parsing), independent of brain health/connection. doctor reports the
brain connected and healthy; no doctor check covers the list_skills catalog.
Root cause
src/core/skill-catalog.ts:
function parseDescriptionField(raw) {
const m = raw.match(/^description:\s*["']?(.+?)["']?\s*$/m);
if (!m) return undefined;
const v = m[1].trim();
return v.length > 0 ? v : undefined; // returns "|" for `description: |`
}
export function oneLineDescription(raw, body) {
return parseDescriptionField(raw) ?? firstProseLine(body);
}
For description: |, the regex captures | (length 1 > 0), so parseDescriptionField returns "|" and the ?? firstProseLine(body) fallback never fires. Same for > and chomping/indent variants (|-, >2, etc.).
Suggested fix
In parseDescriptionField, when the captured value is a bare block-scalar indicator (|/>, optionally followed by +/-/digits), either:
- (minimal) return
undefined so oneLineDescription falls through to firstProseLine(body), or
- (complete) read the indented continuation lines and fold them into a one-liner.
Happy to send a PR with a test/ case if useful.
What happened?
list_skills/get_skillreturn the literal YAML block-scalar indicator (|or>) as a skill's description when the skill'sSKILL.mdfrontmatter uses a block scalar:→ catalog entry comes back as
"description": "|". Affects every skill authored withdescription: |ordescription: >. Single-linedescription: ...skills are fine.triggers/toolsparse correctly, andget_skillstill returns the full prose body — so it's a catalog-display issue, not data loss.What did you expect?
The folded block-scalar content as the one-line description (or, minimally, the body's first prose line via the existing
firstProseLinefallback).Steps to reproduce
SKILL.mdfrontmatter usesdescription: |(block scalar) with the text on the indented lines below.mcp.publish_skillsand pointGBRAIN_SKILLS_DIRat the skills dir.list_skillsover MCP → that skill'sdescriptionis"|"(or">").Environment
gbrain doctor --jsonoutputRoot cause
src/core/skill-catalog.ts:For
description: |, the regex captures|(length 1 > 0), soparseDescriptionFieldreturns"|"and the?? firstProseLine(body)fallback never fires. Same for>and chomping/indent variants (|-,>2, etc.).Suggested fix
In
parseDescriptionField, when the captured value is a bare block-scalar indicator (|/>, optionally followed by+/-/digits), either:undefinedsooneLineDescriptionfalls through tofirstProseLine(body), orHappy to send a PR with a
test/case if useful.