[BUG] parse-frontmatter.sh returns body content as frontmatter when the markdown body contains ---

Status Open
Maintainer reply None cached
Activity 0 comments · opened Sep 8, 2026

Preflight

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report

Description

The two scripts in plugins/plugin-dev/skills/plugin-settings/scripts/ both pull frontmatter out with sed -n '/^---$/,/^---$/{ /^---$/d; p; }'.

A sed range reopens every time the start pattern matches again, so any --- further down the file starts a second range. Put a horizontal rule in the body of a settings file and whatever follows it gets treated as frontmatter.

I hit this because my settings file had a --- separator in the docs section under the frontmatter, and the plugin kept coming up disabled even though enabled: true was right there at the top.

Steps to Reproduce

.claude/my-plugin.local.md:

---
enabled: true
---

# My Plugin

---

## Config reference

enabled: false

Then run the parser the way its own --help shows:

$ ./plugins/plugin-dev/skills/plugin-settings/scripts/parse-frontmatter.sh .claude/my-plugin.local.md enabled
true
false

Expected

true. Frontmatter is the block between the first two --- markers, so the enabled: false in the config docs shouldn't be part of it.

Actual

Two lines. And since the help text tells you to use it like this:

ENABLED=$(./parse-frontmatter.sh .claude/my-plugin.local.md enabled)
if [ "$ENABLED" = "true" ]; then

the test compares against "true\nfalse", fails, and you get the disabled path with nothing printed to tell you why. That's what cost me the debugging time — it doesn't error, it just answers wrong.

Other things I ran into in the same two files

parse-frontmatter.sh:

  • enabled: false errors with Field 'enabled' not found. The not-found check is [ -z "$VALUE" ], which can't tell a missing key from one whose value is empty or false.
  • The field name goes straight into a grep pattern, so a key like my.field will match a similarly-named key instead.
  • If the closing --- is missing, the range just runs to EOF and the whole file comes back as frontmatter. No error.

validate-settings.sh:

  • Check 3 counts --- anywhere in the file and passes if there are 2+. A file with no frontmatter at all but two horizontal rules in the body validates fine.
  • Check 7 reads the leaked multi-line value, so a file with a plain enabled: true gets warned that it "should be boolean (true/false)".
  • Check 8 skips every --- when finding the body, so horizontal rules get dropped and the "body present (N lines)" count comes out short.

Environment

Repo at main (ab9b2cf). This is in the scripts themselves, so it isn't tied to a particular CLI version.

Fix

Branch: https://github.com/Sagexd08/claude-code/tree/fix/parse-frontmatter-range

Diff: https://github.com/anthropics/claude-code/compare/main...Sagexd08:claude-code:fix/parse-frontmatter-range

Requires the opening --- on line 1 and quits at the closing one, so nothing from the body can get in. Also takes the first match for a key rather than all of them, checks whether the key exists before stripping the value off, and matches key names literally instead of as a regex.

Cases I checked, including the ones that already worked, to make sure nothing regressed: body containing a --- rule, enabled: false, empty value, single and double quoted values, a key with a . in it, no frontmatter, unterminated frontmatter, a no-frontmatter file with two body rules, and a valid file with a body rule. Both scripts pass bash -n and still read the repo's own SKILL.md files (plugin-settings and hookify/writing-rules) correctly. Files with no --- in the body behave the same as before.

I would have sent this as a PR but POST /repos/anthropics/claude-code/pulls gives me a 404 from a fork right now, so the branch is there if someone wants to pull it in, or I can open a PR if external ones get turned back on.

View original on GitHub ↗