Custom Rules Guide
claudelint allows you to define custom validation rules to extend the built-in rule set with your own team-specific or project-specific requirements. For contributing built-in rules, see the Contributing Guide.
Quick Start
- Create a
.claudelint/rules/directory in your project root - Add a custom rule file (
.tsor.js) - Export a
ruleobject that implements the Rule interface - Run
claudelint check-allto load and execute your custom rules
Example custom rule that validates SKILL.md files have cross-references:
import type { Rule } from 'claude-code-lint';
import { hasHeading } from 'claude-code-lint/utils';
export const rule: Rule = {
meta: {
id: 'require-skill-see-also',
name: 'Require Skill See Also',
description: 'SKILL.md must have a ## See Also section for cross-referencing related skills',
category: 'Skills',
severity: 'warn',
fixable: false,
},
validate: async (context) => {
if (!context.filePath.endsWith('SKILL.md')) {
return;
}
if (!hasHeading(context.fileContent, 'See Also', 2)) {
context.report({
message: 'Missing ## See Also section',
line: 1,
fix: 'Add a ## See Also section linking to related skills',
});
}
},
};Directory Structure
Custom rules are automatically discovered in .claudelint/rules/:
your-project/
├── .claudelint/
│ └── rules/
│ ├── team-rule.ts
│ ├── project-rule.ts
│ └── conventions/
│ └── naming-rule.ts
├── CLAUDE.md
└── .claudelintrc.json- Rules can be organized in subdirectories
- Both
.tsand.jsfiles are supported .d.ts,.test.ts, and.spec.tsfiles are automatically excluded
Valid Categories
Custom rules must use one of the built-in categories. The category determines which validator executes your rule.
| Category | Description |
|---|---|
CLAUDE.md | Rules targeting CLAUDE.md configuration files |
Skills | Rules for skill definitions (SKILL.md) |
Settings | Rules for settings files |
Hooks | Rules for hook configurations |
MCP | Rules for MCP server configurations |
Plugin | Rules for plugin manifests |
Commands | Rules for command definitions |
Agents | Rules for agent definitions |
OutputStyles | Rules for output style configurations |
LSP | Rules for LSP server configurations |
Examples
See the Custom Rule Examples page for three practical examples covering pattern matching, auto-fix, and configurable options. All examples are real rules from claudelint's own .claudelint/rules/ directory.
Configuration
Custom rules can be configured in .claudelintrc.json just like built-in rules:
{
"rules": {
"require-skill-see-also": "warn",
"no-user-paths": "error",
"normalize-code-fences": "off"
}
}Testing
Create test cases using a collectIssues helper. See the dogfood rule tests for a working example:
import { rule } from './.claudelint/rules/my-rule';
async function collectIssues(rule, filePath, fileContent) {
const issues = [];
await rule.validate({
filePath,
fileContent,
options: {},
report: (issue) => issues.push(issue),
});
return issues;
}
const issues = await collectIssues(rule, '/test/SKILL.md', 'content missing required section');
expect(issues).toHaveLength(1);Helper Library
claudelint provides utility functions for common validation tasks like heading detection, pattern matching, frontmatter parsing, and file system operations. See the Helper Library Reference for the complete API.
See Also
- Rule System - Rule interface, registry, and validation patterns
- Helper Library Reference - Utility functions for custom rules
- Built-in Rules - Examples of rule implementations
- Contributing Guide - How to contribute rules to claudelint
- Example rules on GitHub - Working custom rules