Skip to content

fix(server): recover skill frontmatter Claude Code itself accepts - #7814

Open
Exotic209093 wants to merge 3 commits into
pingdotgg:mainfrom
Exotic209093:fix/claude-skill-frontmatter-leniency
Open

fix(server): recover skill frontmatter Claude Code itself accepts#7814
Exotic209093 wants to merge 3 commits into
pingdotgg:mainfrom
Exotic209093:fix/claude-skill-frontmatter-leniency

Conversation

@Exotic209093

@Exotic209093 Exotic209093 commented Aug 21, 2026

Copy link
Copy Markdown

Summary

Fixes #7757. parseSkillFrontmatter in apps/server/src/provider/Drivers/ClaudeSkills.ts strict-YAML-parses each SKILL.md's frontmatter and drops the entry entirely on any parse error. Claude Code's own frontmatter parser is more lenient: an unquoted scalar description containing a word: sequence (e.g. description: ... via kane-cli: run browser objectives, ...) is valid there, but strict YAML rejects it as an ambiguous nested mapping (mapping values are not allowed here). A skill that demonstrably loads and works in Claude Code was invisible in T3's own scanner and the $ picker — the same cache snapshot showed the contradiction directly: the skill appeared in slashCommands (from the CLI's own probe) while skills stayed [].

Fix

When strict YAML parsing fails, fall back to recovering name/description as flat key: value scalars — the only two fields this scanner reads — instead of dropping the skill. The fallback only kicks in per-line for top-level, unindented keys, and explicitly still treats a value as malformed if it looks like it was attempting real YAML structure that broke (starts with [, {, |, >, &, *, or ! — an unterminated flow collection, block scalar, anchor, alias, or tag). That keeps the existing "genuinely broken YAML" behavior intact (e.g. name: [unclosed still gets dropped, matching Claude Code, which wouldn't load that either) while recovering the specific leniency gap the issue reports.

Test plan

  • Added a regression test reproducing the exact kane-cli frontmatter from the issue; confirmed it fails before the fix (dropped as malformed) and passes after (recovered with the correct name/description).
  • vp test run apps/server/src/provider/Drivers/ClaudeSkills.test.ts — 10 passed, including the existing malformed-YAML test (name: [unclosed) which still correctly drops the skill.
  • vp run --filter t3 typecheck — clean (only pre-existing, unrelated suggestions in other files).
  • vp lint on changed files — clean.

Note

Low Risk
Parser fallback is limited to two scalar skill fields and still drops structurally broken YAML. No auth, data, or API surface changes.

Overview
Skills that Claude Code loads but T3 dropped as malformed YAML now show up in discovery (and the $ picker).

When strict YAML parse fails, parseSkillFrontmatter falls back to reading top-level name/description as flat key: value scalars. That covers unquoted descriptions with a colon (e.g. via kane-cli: run ...). Values that look like broken YAML structure ([, {, |, >, &, *, !) still count as malformed and are skipped.

Adds a regression test for the kane-cli frontmatter from the issue.

Reviewed by Cursor Bugbot for commit f97d0d1. Configure here.

Note

Recover skill frontmatter that ClaudeCode accepts but strict YAML rejects

Adds a lenient fallback to parseSkillFrontmatter so that when strict YAML parsing fails, it still recovers name and description from flat key: value scalars. Values starting with YAML structural tokens ([, {, |, etc.) are rejected to avoid misinterpreting real structure as plain scalars, and trailing # comments are stripped.

  • Covers cases like unquoted descriptions containing colons and broken name fields that cause the whole skill to be skipped.
  • Risk: lenient recovery only triggers on strict-parse failure and returns {kind: 'malformed'} for structurally broken values, so previously-rejected skills are the only ones affected.

Macroscope summarized 98a98ba.

parseSkillFrontmatter strict-YAML-parsed SKILL.md frontmatter and
dropped the entry entirely on any parse failure. Claude Code's own
frontmatter parser is more lenient: an unquoted description containing
a "word: " sequence (e.g. a URL or clause with a colon) is valid there
but strict YAML rejects it as an ambiguous nested mapping. A skill that
demonstrably loads in Claude Code was invisible in T3's own scanner.

Add a fallback that recovers name/description as flat "key: value"
scalars when strict parsing fails, but only when the value doesn't look
like broken YAML syntax (an unterminated flow collection, block scalar,
anchor, alias, or tag) — those still count as malformed, matching
existing behavior for frontmatter Claude Code wouldn't load either.

Fixes pingdotgg#7757
@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: bae4f86b-ed88-456f-a1c0-265cc080f4ed

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Aug 21, 2026
Comment thread apps/server/src/provider/Drivers/ClaudeSkills.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f97d0d156e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/server/src/provider/Drivers/ClaudeSkills.ts
@macroscopeapp

macroscopeapp Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at 98a98ba

Macroscope's review found this PR approvable — Straightforward bug fix that adds lenient fallback parsing for skill frontmatter when strict YAML fails, ensuring T3 discovers the same skills Claude Code accepts. Limited scope, defensive implementation that rejects real YAML errors, and comprehensive test coverage for edge cases.

You can add or adjust custom eligibility rules. Learn more.

Both Macroscope and Codex caught a real gap in the lenient fallback:
it recovered name/description per-line independently, so a document
with one genuinely broken field (e.g. name: [unclosed) alongside a
fine one (description: ...) surfaced the skill anyway with the broken
field silently dropped — exactly the case the fallback was supposed to
exclude, since Claude Code wouldn't load that file at all. A broken
line in a field this scanner doesn't even read had the same gap.

Any top-level line whose value looks like broken YAML structure now
fails the whole document as malformed, regardless of which field it's
in, before recovering name/description from the rest.
@Exotic209093

Copy link
Copy Markdown
Author

Good catch, both of you — the per-line recovery was independent per field, so a document with one genuinely broken line (in a recognized field or not) alongside a fine one still surfaced the skill with the broken bit silently dropped, exactly the case this was supposed to exclude. Fixed: any top-level line with broken-looking YAML structure now fails the whole document as malformed before recovering anything, regardless of which field it's in. Added regression tests for both scenarios.

Comment thread apps/server/src/provider/Drivers/ClaudeSkills.ts Outdated
… rules

Macroscope caught a real gap: the lenient fallback copied everything
after the colon verbatim, so "name: demo # display label" recovered as
"demo # display label" instead of "demo" — no comment stripping, no
quote-escape handling.

Parse the isolated value with the real YAML parser instead of manual
trimming. This also keeps the one case the fallback exists for working
correctly: an unquoted value with its own embedded ": " parses as a
one-entry mapping in isolation (not a string), so it falls through to
the untouched raw text exactly as before.
@Exotic209093

Copy link
Copy Markdown
Author

Good catch — the fallback was copying everything after the colon verbatim, so a trailing YAML comment or quote escaping wasn't handled. Switched to parsing the isolated value with the real YAML parser: it strips comments and unescapes quotes correctly, and the one case this fallback exists for (an unquoted value with its own embedded ": ") still parses as a one-entry mapping in isolation, not a string, so it correctly falls through to the raw text as before.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M 30-99 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Claude skill discovery drops skills with frontmatter Claude Code itself accepts (strict YAML vs CLI leniency), silently

1 participant