The files that tell an AI coding tool how to behave look like documentation. In practice they act more like code—except code usually gives you an error when it does not run.
I spent a long time wiring skills, hooks, memory, agent definitions, plugin manifests, and MCP servers across Claude Code, Cursor, Copilot, Codex, OpenCode, and other tools. The formats differ, but one failure pattern repeats: an invalid file often remains perfectly quiet.
Silence is the dangerous part
If ESLint cannot read its config, the process fails. If a skill has malformed frontmatter, the agent may simply never discover it. The user sees a mediocre result and blames the model, without knowing that the instructions were absent from the interaction.
The same thing happens in the other direction. A destructive skill can be discoverable when it should require explicit invocation. A hook can name the wrong event and never run. An MCP tool can be present in a config but unusable because its schema or transport is invalid.
The worst configuration error is not the one that crashes. It is the one that makes the system look merely less capable.
The failures cluster into a few families
Skills that disappear
- Frontmatter is absent, malformed, or uses fields the tool does not understand.
- The name violates the platform's identifier rules.
- The description contains no useful activation language.
- A path or model value belongs to another tool's format.
Hooks that are decorative
- The event name is close to correct but not exact.
- The command field is missing or points to a file that does not exist.
- A dangerous command runs without the guard the author assumed was present.
Instructions that fight each other
CLAUDE.mdsays to run npm whileAGENTS.mdsays pnpm.- A repository rule allows a tool that a global rule denies.
- The same policy is copied across formats and drifts differently in each one.
Memory that spends context without changing behavior
- Generic advice repeats what the base model already knows.
- Important constraints are buried between pages of low-value prose.
- Instruction files exceed a tool's useful or documented limits.
So I built a linter
agnix treats agent configuration as a real software surface. It walks a repository, identifies configuration by both path and content, applies rules for the relevant tool, and emits ordinary diagnostics with locations, severity, evidence, and fixes.
npx agnix .
The output is deliberately boring. A configuration problem should look like every other development problem you already know how to fix:
SKILL.md:3:1 error: invalid skill name "Review-Code"
help: use lowercase letters and hyphens
.cursor/rules/testing.mdc:1:1 error: missing frontmatter
help: add description, globs, and alwaysApply
.claude/settings.json:12:5 error: script not found
help: create ./scripts/lint.sh or correct the path
Safe mechanical fixes can be applied automatically. Changes that could alter meaning remain explicit.
agnix --fix-safe .
A rule needs a source, not a vibe
The fastest way for a linter in this ecosystem to become harmful is to confuse preference with validity. Vendor formats change constantly. Some fields are required, some are recommendations, and some “best practices” are just popular repetition.
agnix rules link back to official specifications, vendor documentation, research, or a reproducible failure. Severity follows that evidence. A broken required field is not presented with the same confidence as a context-engineering recommendation.
This distinction also keeps the tool narrow. agnix should tell you when what you wrote will not work, is unsafe, or conflicts with another layer. It should not decide what your agent is allowed to believe.
One engine, many fragile formats
The current rule set spans the configuration surfaces around the major coding tools:
- Claude Code: skills, agents, hooks, plugins, settings, and memory.
- Codex:
AGENTS.md, configuration, skills, plugins, and MCP. - Cursor: scoped rules, legacy formats, globs, and frontmatter.
- GitHub Copilot: global and path-scoped instructions.
- OpenCode, Gemini CLI, Cline, Kiro, Windsurf, and others: their native instruction and agent formats.
- Cross-platform checks: contradictory commands, permissions, and duplicated policy.
The Rust core also powers an LSP, editor integrations, an MCP server, a GitHub Action, and an in-browser playground. The same validation should be available while writing a file, in CI, and to the agent modifying its own configuration.
Why this layer deserves engineering
Agent configuration is becoming the interface between a developer's intent and a growing amount of automated work. It determines which context enters a run, which tools can execute, which checks happen, and when a system is allowed to publish or delete.
At the same time, every vendor invented a different format and release cadence. Without validation, teams end up with parallel instruction stacks that are almost aligned and quietly diverging.
We already lint source code, build files, infrastructure, schemas, workflows, and prose. The layer that shapes an AI agent's behavior should not be the exception.
agnix does not make an agent correct. It removes one particularly frustrating reason for it to be wrong: the configuration never worked in the first place.