eslint-plugin-claude
v0.5.0
Published
An ESLint plugin that lints Claude Code configuration files.
Maintainers
Readme
eslint-plugin-claude
An ESLint plugin that lints Claude Code configuration files
It checks skills, commands and hooks against the Claude Code docs. It runs on
@eslint/markdown and
@eslint/json.
Install
pnpm add -D eslint @eslint/markdown @eslint/json eslint-plugin-claudeRequires ESLint 10, @eslint/markdown 8, @eslint/json 2 and Node ^22.13.0 || >=24. The two
language plugins are peers, so your project and this plugin use the same copy.
Usage
// eslint.config.js
import { defineConfig } from 'eslint/config'
import claude from 'eslint-plugin-claude'
export default defineConfig([{ plugins: { claude }, extends: ['claude/recommended'] }])Each rule brings its own files glob and language, and a rule can add a second language and
glob. The config registers markdown and json, so you need no other setup. Rule IDs take the form claude/<rule>.
Configs
| Config | Rules |
|--------|-------|
| recommended | The rules whose source is the Claude Code docs. |
| strict | recommended, plus each rule that is still off, at warn. Use it to test the full rule set. |
Rules
The rules are in groups by the type of file that they check. The groups follow the rule inventory.
Skills and commands
| Rule | Checks | recommended | strict |
|------|--------|---------------|----------|
| claude/skill-description-max-length | The length of description plus when_to_use in a SKILL.md | warn | warn |
| claude/command-legacy-format | A command file is the legacy form of a skill | warn | warn |
| claude/skill-frontmatter-position | The frontmatter of a skill or command starts on line 1 | error | error |
| claude/skill-frontmatter-schema | The fields, types and values of skill frontmatter | error | error |
| claude/skill-fork-fields-require-context | agent and background need context: fork | error | error |
| claude/skill-invocation-unreachable | A skill that neither Claude nor the user can invoke | error | error |
| claude/skill-reserved-name | A skill or command name that Claude Code reserves | error | error |
| claude/skill-plugin-vars-outside-plugin | Plugin variables in a skill that is not in a plugin | error | error |
| claude/skill-inject-bang-position | A ! command placeholder after a non-space character | error | error |
| claude/skill-allowed-tools-ineffective | A tool in allowed-tools or disallowed-tools that has no effect | error | error |
| claude/skill-allowed-tools-broad | An unscoped grant in allowed-tools, such as a bare Bash or a whole MCP server | error | error |
| claude/skill-plugin-root-shadowed | A SKILL.md at a plugin root that has skills/ or a skills key | error | error |
| claude/skill-file-layout | A skill in a folder, in a file named SKILL.md | error | error |
| claude/skill-reference-exists | A relative link or ${CLAUDE_SKILL_DIR} path in a SKILL.md that names a file which is not there | error | error |
| claude/skill-agent-exists | The agent of a skill or command names a built-in agent, an agent file, or a plugin agent | error | error |
| claude/skill-name-unique | Two skills or commands in one scope with the same command name | error | error |
| claude/skill-paths-glob-valid | A paths glob that Claude Code cannot use | error | error |
Subagents and output styles
| Rule | Checks | recommended | strict |
|------|--------|---------------|----------|
| claude/agent-frontmatter-valid | The frontmatter of a local subagent file loads: line 1, YAML, name, description | error | error |
| claude/agent-frontmatter-schema | The fields, types and values of subagent frontmatter | error | error |
| claude/agent-plugin-ignored-fields | permissionMode, hooks, mcpServers and initialPrompt in a plugin agent | error | error |
| claude/agent-mcp-servers-schema | The mcpServers list of a local subagent | error | error |
| claude/agent-permission-mode-bypass | permissionMode: bypassPermissions in a local subagent | error | error |
| claude/agent-memory-grants-write | memory in a subagent whose tools list leaves out Write or Edit | error | error |
| claude/agent-tools-known | Each entry of tools and disallowedTools names a tool that Claude Code knows | error | error |
| claude/agent-tools-unavailable | A tool in tools that Claude Code removes from the subagent | error | error |
| claude/agent-teams-no-project-config | A .md or .json file under .claude/teams/ | error | error |
| claude/output-style-frontmatter-valid | The frontmatter of an output style starts on line 1 and parses | error | error |
| claude/output-style-frontmatter-schema | The fields and types of output style frontmatter | error | error |
Hooks
| Rule | Checks | recommended | strict |
|------|--------|---------------|----------|
| claude/hooks-event-name-known | Each hook event name in hooks.json, settings and plugin.json is one that Claude Code knows | error | error |
Permissions and sandbox
| Rule | Checks | recommended | strict |
|------|--------|---------------|----------|
| claude/permissions-rule-syntax | Each permission rule is Tool or Tool(specifier) | error | error |
| claude/permissions-unknown-tool | Each permission rule names a tool that Claude Code knows | error | error |
| claude/permissions-tool-name-glob | An allow rule has a tool-name glob only after mcp____ | error | error |
| claude/permissions-specifier-unsupported | A tool that takes no specifier has none in a permission rule | error | error |
| claude/permissions-path-rule-tool | A path rule is for Edit or Read, the tools that Claude Code consults | error | error |
| claude/permissions-mcp-rule-parens | An mcp__ permission rule has no parentheses | error | error |
| claude/permissions-param-rule | A parameter rule does not name the primary input field of its tool | error | error |
| claude/permissions-skill-rule | A Skill(prefix *) allow rule whose prefix stops short of anthropic-skills | error | error |
Contributing
See CONTRIBUTING.md.
License
MIT
