biome-gritql
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBiome GritQL Custom Lint Rules
Biome GritQL 自定义Lint规则
Create AST-based custom lint rules using Biome's GritQL plugin system.
使用Biome的GritQL插件系统创建基于AST的自定义lint规则。
Quick Start
快速开始
Create a rule file ():
rules/no-use-effect-fetch.gritgritql
`useEffect($callback, $deps)` where {
$callback <: contains `fetch`,
register_diagnostic(
span = $callback,
message = "Don't fetch inside useEffect. Use TanStack Query instead.",
severity = "error"
)
}Add to :
biome.jsonjson
{
"plugins": ["./rules/no-use-effect-fetch.grit"]
}Run: or any equivalent command to run linter in the codebase
bunx biome check创建规则文件():
rules/no-use-effect-fetch.gritgritql
`useEffect($callback, $deps)` where {
$callback <: contains `fetch`,
register_diagnostic(
span = $callback,
message = "Don't fetch inside useEffect. Use TanStack Query instead.",
severity = "error"
)
}添加至:
biome.jsonjson
{
"plugins": ["./rules/no-use-effect-fetch.grit"]
}运行: 或其他等效命令来在代码库中运行linter
bunx biome checkGritQL Syntax
GritQL语法
Basic Pattern Matching
基础模式匹配
gritql
`pattern_to_match` where {
register_diagnostic(
span = $matched_var,
message = "Your message here",
severity = "error" // hint | info | warn | error
)
}make sure to read documentation
gritql
`pattern_to_match` where {
register_diagnostic(
span = $matched_var,
message = "Your message here",
severity = "error" // hint | info | warn | error
)
}请务必阅读文档
Variables
变量
- - captures any single node
$name - - captures arguments
$args - - wildcard (match but don't capture)
$_
- - 捕获任意单个节点
$name - - 捕获参数
$args - - 通配符(匹配但不捕获)
$_
Operators
操作符
| Operator | Meaning |
|---|---|
| matches / contains |
| deep contains |
| regex match |
| negation |
| both conditions |
| either condition |
| 操作符 | 含义 |
|---|---|
| 匹配 / 包含 |
| 深度包含 |
| 正则匹配 |
| 取反 |
| 同时满足条件 |
| 满足任一条件 |
Common Rule Patterns
常见规则模式
Ban a Function Call
禁用函数调用
gritql
`console.log($args)` where {
register_diagnostic(
span = $args,
message = "Remove console.log before committing",
severity = "warn"
)
}gritql
`console.log($args)` where {
register_diagnostic(
span = $args,
message = "Remove console.log before committing",
severity = "warn"
)
}Ban a Hook (React)
禁用Hook(React)
gritql
`useMemo($args)` where {
register_diagnostic(
span = $args,
message = "useMemo unnecessary with React Compiler. Remove it.",
severity = "warn"
)
}gritql
`useMemo($args)` where {
register_diagnostic(
span = $args,
message = "useMemo unnecessary with React Compiler. Remove it.",
severity = "warn"
)
}Ban Dynamic Imports
禁用动态导入
gritql
`await import($path)` where {
register_diagnostic(
span = $path,
message = "Use static imports at the top of the file",
severity = "error"
)
}gritql
`await import($path)` where {
register_diagnostic(
span = $path,
message = "Use static imports at the top of the file",
severity = "error"
)
}Require Pattern in Context
要求上下文模式
gritql
`useState($initial)` where {
not $initial <: contains `atom`,
register_diagnostic(
span = $initial,
message = "Prefer Jotai atoms over useState for shared state",
severity = "info"
)
}gritql
`useState($initial)` where {
not $initial <: contains `atom`,
register_diagnostic(
span = $initial,
message = "Prefer Jotai atoms over useState for shared state",
severity = "info"
)
}CSS Rules
CSS规则
gritql
language css;
`$selector { $props }` where {
$props <: contains `color: $color` as $rule,
not $selector <: r"\.color-.*",
register_diagnostic(
span = $rule,
message = "Use .color-* utility classes instead of explicit colors"
)
}gritql
language css;
`$selector { $props }` where {
$props <: contains `color: $color` as $rule,
not $selector <: r"\.color-.*",
register_diagnostic(
span = $rule,
message = "Use .color-* utility classes instead of explicit colors"
)
}Project Structure
项目结构
project/
├── biome.json
└── rules/
├── no-console-log.grit
├── no-use-memo.grit
├── no-use-callback.grit
├── no-dynamic-import.grit
└── no-fetch-in-effect.gritproject/
├── biome.json
└── rules/
├── no-console-log.grit
├── no-use-memo.grit
├── no-use-callback.grit
├── no-dynamic-import.grit
└── no-fetch-in-effect.gritbiome.json Configuration
biome.json配置
json
{
"$schema": "https://biomejs.dev/schemas/2.0.0/schema.json",
"plugins": [
"./rules/no-console-log.grit",
"./rules/no-use-memo.grit",
"./rules/no-use-callback.grit"
],
"linter": {
"enabled": true
}
}json
{
"$schema": "https://biomejs.dev/schemas/2.0.0/schema.json",
"plugins": [
"./rules/no-console-log.grit",
"./rules/no-use-memo.grit",
"./rules/no-use-callback.grit"
],
"linter": {
"enabled": true
}
}Creating Rules Workflow
规则创建流程
- Identify the pattern to ban/enforce
- Create file in
.gritdirectoryrules/ - Write the GritQL pattern with clear error message
- Add path to plugins array
biome.json - Test with or any equivalent command to run linter in the codebase
bunx biome check
- 确定要禁用/强制执行的模式
- 在目录中创建
rules/文件.grit - 编写带有清晰错误提示的GritQL模式
- 将路径添加至的plugins数组
biome.json - 使用或其他等效命令在代码库中运行linter进行测试
bunx biome check
Guidelines
指导原则
- Keep error messages actionable - tell the user what to do instead
- Use for hard requirements,
severity = "error"for preferences"warn" - Put all files in a
.gritdirectoryrules/ - Name files descriptively: or
no-X.gritprefer-Y.grit - Test rules against real code before committing
- 错误提示要具备可操作性——告诉用户应该怎么做
- 对于硬性要求使用,对于偏好性要求使用
severity = "error""warn" - 将所有文件放在
.grit目录中rules/ - 文件命名要具有描述性:或
no-X.gritprefer-Y.grit - 在提交前针对真实代码测试规则
Why This Matters
为何这很重要
Instructions in CLAUDE.md degrade as context fills up. Linter rules provide immediate, persistent feedback. When Claude violates a pattern, it sees the error and self-corrects - no context drift.
CLAUDE.md中的说明会随着上下文填充而失效。Linter规则能提供即时、持久的反馈。当Claude违反模式时,它会看到错误并自我修正——不会出现上下文漂移问题。