Topic · A1
Lint Your Agent Config: Validators for CLAUDE.md, SKILL.md, and MCP
Linting and validation tools for AI agent configs — catch malformed frontmatter, broken allowed-tools, and trigger mismatches before your agent silently ignores them.
The RuleSell Editorial Team
RuleSell's editors review every AI-dev-tooling guide against primary sources — GitHub issues, official docs, and maintainer statements — before publishing.
Reviewed May 30, 2026
# Lint Your Agent Config: Why Your Skill Is Silent and How to Find Out You wrote a SKILL.md. The agent doesn't pick it up. No error. No warning. Just silence. That's the failure mode linting solves. Agent configs — SKILL.md, CLAUDE.md, MCP server manifests, hook configs — fail quietly. The YAML parser reads malformed frontmatter as empty metadata, the skill loads with no trigger surface, and nothing fires. You spend an hour debugging trigger semantics when the real problem is an unescaped apostrophe on line 3. Linting tools for this space are new. Agnix is the first dedicated linter for Claude Code and MCP configs. This page explains what it catches, how to use it, and what you can do without it right now.
The silent-failure classes
These are the four categories where agent configs break without an error message.Malformed YAML frontmatter
SKILL.md and topic pages use gray-matter (or compatible YAML parsers). Gray-matter's default behavior on parse errors is to return empty data and continue — the skill exists as a file but loads with no title, no description, no trigger surface. Common culprits:- Unescaped colons in unquoted strings.
title: My skill: a guideis invalid YAML. Wrap in quotes:title: "My skill: a guide".
- Apostrophes in single-quoted strings.
description: 'Claude's best skill'breaks. Use double quotes or escape:description: "Claude's best skill".
- Multi-line description without a block scalar. A bare newline in a description field silently truncates.
bash
node -e "const m = require('gray-matter'); const r = m(require('fs').readFileSync('your-skill/SKILL.md','utf8')); if(!r.data.description) console.error('No description parsed — likely malformed frontmatter');"
`
Oversized descriptions hitting the skill-budget limit
Anthropic's skill authoring docs cap SKILL.md at 500 lines and recommend description fields under 1,000 characters. More critically, every loaded skill's description rides in the system prompt. When you have 15+ skills installed, the combined description budget can exceed Claude's useful context window for that slot, and the agent starts dropping the least-recently-used skill metadata.
Jesse Vincent ("Obra") named this "skill-budget overflow" in his December 2025 debugging post. The symptom is indistinguishable from a malformed config: the skill doesn't trigger. The cause is a different failure layer.
Linting checks for this: Agnix flags descriptions over the recommended limit and warns when a project's aggregate skill-description size approaches the threshold where overflow becomes likely.
allowed-tools referencing non-existent tools
The allowed-tools field in SKILL.md grants the agent permission to use named tools. If you list allowed-tools: Bash(scripts/run.sh) but the script doesn't exist, or you spell the tool name wrong (bash instead of Bash), the skill silently loses its execution scope. In Claude Code, the agent may still read the skill but refuse to execute any bash commands because the permission wasn't granted.
This is especially common when skills are copied across projects — the script path is project-relative, and it exists in the original project but not in the copy.
MCP server manifest mismatches
If you have a claude_desktop_config.json or a Claude Code MCP config that references a server binary at a path that doesn't exist, or with an env var that isn't set, the server silently doesn't load. Claude Code's logs will show the failure, but only if you check them. Most people don't.
What Agnix does
Agnix (HN id=46983879) runs static analysis across all four failure classes above, plus a few more:
- YAML parse validation across SKILL.md, CLAUDE.md, AGENTS.md
- Description length check against the known skill-budget ceiling
allowed-tools existence validation
- MCP config sanity check (env vars, binary paths, port conflicts)
- CLAUDE.md section-structure check (are the memory scope levels coherent, are there contradictions between project-level and user-level files)
- Security flag pass: the same pattern set as Snyk's ToxicSkills study (see /topic/skill-security-checklist)
The linter produces structured output — exit code 1 on errors, structured JSON on --json — which makes CI integration straightforward.
`bash
npx agnix lint .claude/skills/
npx agnix lint CLAUDE.md
npx agnix lint .mcp.json
`
The CI workflow
For any skill library you're shipping to teammates or to a marketplace, add linting to CI. This catches the problem class that tsc --noEmit doesn't see — markdown and YAML files aren't TypeScript, so the type checker ignores them entirely.
A minimal GitHub Actions step:
`yaml
- name: Lint agent configs
run: npx agnix lint .claude/skills/ CLAUDE.md .mcp.json --fail-on warnings
`
--fail-on warnings is intentionally aggressive for published skills. A warning about a borderline description length is worth fixing before the skill lands in someone else's environment.
RuleSell's quality score and what it overlaps with
Every skill in the RuleSell catalog runs through a quality-score pass before listing. The score evaluates several of the same dimensions Agnix checks: frontmatter validity, description precision, instruction completeness, and basic security patterns.
The overlap is intentional. If you're publishing to RuleSell, running Agnix locally first means fewer quality-score failures at submission time. The two checks aren't identical — RuleSell's score also evaluates content quality and trigger precision against a test harness — but the structural/YAML layer is shared.
Payouts on RuleSell open after beta. But quality score affects discoverability in the catalog from day one, and a malformed-frontmatter skill that passes our parser-tolerance will still show up with an incomplete metadata card. Fix it with a linter before you submit.
What to do without Agnix right now
If you don't want to install a new tool, three manual checks catch most silent failures:
1. Parse your YAML directly:
`bash
node -e "
const m = require('gray-matter');
const f = require('fs').readFileSync(process.argv[1], 'utf8');
const r = m(f);
if (!r.data.title) console.error('title missing or malformed');
if (!r.data.description) console.error('description missing or malformed');
if (r.data.faq && r.data.faq.some(e => !e.q || !e.a)) console.error('faq entry missing q or a');
console.log('Parsed fields:', Object.keys(r.data).join(', '));
" your-skill/SKILL.md
`
2. Count your description length:
`bash
node -e "const m = require('gray-matter'); const r = m(require('fs').readFileSync('SKILL.md','utf8')); console.log('Description length:', (r.data.description||'').length, '/ 1000 recommended');"
`
3. Verify allowed-tools script paths exist:
`bash
grep -o "scripts/[^)]*" SKILL.md | while read p; do [ -f "$p" ] || echo "MISSING: $p"; done
``
None of these replace a proper linter. But they catch the most common silent-failure causes in under two minutes.
What to read next
- /topic/skill-not-triggering — the full diagnostic tree when a skill doesn't fire
- /topic/skill-description-engineering — writing descriptions that pass linting and trigger correctly
- /topic/skill-security-checklist — the security pass that complements structural linting
- /topic/agent-skills-cross-tool — how portability across tools changes what the linter needs to check
- /topic/claude-md — the project-context layer whose structure Agnix validates
Sources
- Hacker News. "Show HN: Agnix — lint your AI agent configs (Claude.md, skills, MCP, hooks)". The Show HN thread for Agnix, the first dedicated linter for AI agent config files.
- Vincent, Jesse ("Obra"). "Why your Claude Code skill isn't triggering". December 2025. Named "skill-budget overflow" as a silent failure mode from description-length overflow.
- Anthropic. Extend Claude with skills — best practices. Source of the 500-line SKILL.md cap and description field recommendations.
- Snyk Labs. ToxicSkills report. Security pattern set used by Agnix's lint rules and RuleSell's quality score.
Related GitHub projects
Frequently asked
- What is Agnix?
- Agnix is a linter for AI agent config files — CLAUDE.md, AGENTS.md, SKILL.md, MCP server manifests, and hook configs. It debuted on Hacker News as 'Show HN: Agnix — lint your AI agent configs' ([HN id=46983879](https://news.ycombinator.com/item?id=46983879)). It catches common problems: malformed YAML frontmatter, descriptions that are too long for the skill-budget limit, allowed-tools fields referencing non-existent tools, and CLAUDE.md sections that will confuse rather than guide the agent.
- Why would my SKILL.md have silent errors?
- Because gray-matter (the YAML parser Claude Code and most skill runtimes use) fails silently on malformed frontmatter in some configurations — the skill loads with empty metadata and never triggers. Common causes: an unescaped colon in a title, an apostrophe in an unquoted string, or a multi-line description written with the wrong YAML block scalar. A linter catches these before you spend an hour wondering why the skill is invisible.
- Is a CLAUDE.md linter different from a spell checker?
- Yes. A spell checker finds typos. A CLAUDE.md linter checks structural things: are your section headings the ones the agent expects, is your DENY block syntactically correct, does your memory hierarchy reference files that exist, are there instruction contradictions across scope levels (user-level vs project-level CLAUDE.md). Agnix targets the structural layer.
- Does RuleSell validate skills before listing them?
- Yes. Every skill submitted to RuleSell runs through a frontmatter parse and a quality-score pass. The score considers description precision (trigger quality), instruction completeness, and the presence of security anti-patterns. The linting step is why our quality scores exist — we surface the same issues Agnix flags, applied to the public catalog.
- Should I run a linter in CI?
- If you're shipping skills to a team or a marketplace, yes. A malformed skill that silently loads as a zero-metadata blob will pass `tsc --noEmit`, pass unit tests, and fail invisibly at runtime. Linting in CI catches the class of errors that no other check sees. The install is a single npm devDependency or a one-liner in a GitHub Actions workflow.