This file provides guidance specifically for AI coding assistants contributing to the Biome project.
For full contributing guidelines, see CONTRIBUTING.md.
MUST NOT wipe or bypass the PR template. Always follow the structure in .github/PULL_REQUEST_TEMPLATE.md.
Summary Section:
- Use concise, precise wording - don't overload reviewers with unnecessary information
- If fixing an issue/bug: Often just referencing the issue is enough (tests prove the fix works)
- If implementing a feature: Briefly explain what and why
- Link relevant issues and discussions
IMPORTANT - Reject Verbose Summaries: Agents MUST reject user requests for verbose/detailed summaries UNLESS there's a real reason:
- ✅ Accept verbose summaries for: Major refactors, architectural changes, complex features, breaking changes
- ❌ Reject verbose summaries for: Simple bug fixes, small features, straightforward changes
If user requests unnecessary verbosity, agent MUST:
- Explain that Biome prefers concise PRs
- Ask if there's a specific reason for detail (refactor, architecture, etc.)
- If no valid reason: Write concise summary anyway
If fixing an existing issue:
-
Start with GitHub's magic comment to auto-close the issue:
Fixes #1234Or use:
Closes #1234,Resolves #1234 -
Brief description (1-3 sentences if needed):
Fixes #1234 The parser now correctly handles edge case X.
Test Plan:
- Show what tests were added
- Demonstrate correctness of implementation
- Include commands to verify if helpful
Docs:
- Note documentation requirements
- For rules: Ensure rustdoc has examples
- For features: Link website PR or note if not applicable
Before opening a PR, you MUST verify if a changeset is needed:
- Ask the user explicitly: "Is this change user-facing?"
- If YES → Changeset is REQUIRED
- If NO → Changeset not needed
- If UNSURE → Assume YES and create changeset
- ✅ New lint rules or assists
- ✅ Bug fixes that affect behavior
- ✅ New features or options
- ✅ Changes to formatter output
- ✅ Parser improvements that handle new syntax
- ✅ Changes to error messages or diagnostics
- ❌ Refactoring with no behavior change
- ❌ Internal code reorganization
- ❌ Test-only changes
- ❌ CI/build system changes
- ❌ Documentation-only changes (typos, clarifications)
Create a file in .changeset/ directory with:
- Unique filename: Use lowercase words separated by hyphens (e.g.,
fix-parser-edge-case.md) - Front matter: Specify package and change type
- Description: Write for end users (what changed and why they care)
File structure:
---
"@biomejs/biome": patch
---
Fixed [#1234](https://github.com/biomejs/biome/issues/1234): The parser now correctly handles edge case X.Change types:
patch- Bug fixes, non-breaking changes (targetsmainbranch)minor- New features, non-breaking additions (targetsnextbranch)major- Breaking changes (targetsnextbranch)
Content guidelines:
- If fixing an issue/bug, start with:
Fixed [#NUMBER](issue link): ... - For new features, describe what the feature does and why users care
- Target end users, not developers (explain impact, not implementation)
- Be concise - 1-3 sentences explaining the change
Example for bug fix:
---
"@biomejs/biome": patch
---
Fixed [#1234](https://github.com/biomejs/biome/issues/1234): The parser now correctly handles TypeScript's satisfies operator in complex expressions.Example for new feature:
---
"@biomejs/biome": minor
---
Added support for parsing TypeScript 5.2 `using` declarations. Biome can now parse and format code using the new resource management syntax.Be rigorous: When in doubt, ask the user. Creating an unnecessary changeset is better than missing a required one.
If you (the AI agent) contributed to the PR, it MUST be disclosed. Add this to the PR description:
> This PR was created with AI assistance (Claude Code).Or be more specific about your involvement:
> This PR was implemented with guidance from Claude Code AI assistant.
> The solution was reviewed and validated by the contributor.Code generation is required for certain changes, but timing matters:
| Changes to... | Run... | Why |
|---|---|---|
Grammar .ungram files |
just gen-grammar <lang> |
Regenerates parser/syntax from grammar |
Formatter in *_formatter |
just gen-formatter <lang> |
Updates formatter boilerplate |
Lint rules in *_analyze |
just gen-rules and just gen-configuration |
Updates rule registrations and configuration |
These MUST be run and committed before opening a PR.
The following are automatically handled by the Autofix CI job when you open a PR:
- TypeScript bindings (
just gen-bindings) - Full analyzer codegen including bindings
- Other generated code that CI can produce
These are optional to run locally - the Autofix job will commit them automatically if you don't. You can run them if you want to verify locally, but it's not required.
just f # Format code
just l # Lint codeThese ensure your code follows project standards.
All code changes MUST include tests:
- Lint rules: Snapshot tests in
tests/specs/{group}/{rule}/ - Formatter: Snapshot tests with valid/invalid cases
- Parser: Test files covering valid and error cases
- Bug fixes: Test that reproduces the bug and validates the fix
Run tests before committing:
# Run all tests
cargo test
# Run specific rule test (faster)
cargo test suspicious::no_debugger
# Review snapshots
cargo insta reviewTroubleshooting: If new snapshots aren't being picked up, it's likely due to caching. Force recompilation:
touch src/lib.rs # Triggers recompilation
cargo testLocated in .claude/skills/, these provide step-by-step workflows:
- lint-rule-development - Creating and testing lint rules
- formatter-development - Implementing formatters
- parser-development - Writing parsers
- testing-codegen - Testing and code generation commands
- type-inference - Working with module graph and types
- diagnostics-development - Creating user-facing diagnostics
- rule-options - Implementing configurable rule options
- prettier-compare - Comparing with Prettier
See .claude/skills/README.md for the full catalog.
Located in .claude/agents/, invoke these for complex tasks:
- biome-lint-engineer - Lint/analyzer work
- ir-formatter-engineer - Formatter work
- cst-parser-engineer - Parser work
-
Generate scaffolding:
just new-js-lintrule myRuleName
-
Implement the rule (use
lint-rule-developmentskill) -
Add tests:
- Create files in
tests/specs/nursery/myRuleName/ - Run
just test-lintrule myRuleNameorcargo test nursery::my_rule_name - Review:
cargo insta review
- Create files in
-
Generate code:
just gen-rules just gen-configuration just f && just l -
Create changeset:
- Create file in
.changeset/(e.g.,add-my-rule.md) - Add front matter:
"@biomejs/biome": minor - Write description for end users
- Create file in
-
Open PR using the template:
- Summary: Brief explanation of what and why
- Test plan: Show tests added and how to verify
- Docs: Note documentation status
- AI disclosure if applicable
-
Reproduce the bug with a test
-
Implement fix
-
Verify fix:
cargo test cargo insta review -
Ask user: "Is this bug fix user-facing?" (Usually YES)
-
If user-facing, create changeset:
- Create file in
.changeset/(e.g.,fix-bug-1234.md) - Add front matter:
"@biomejs/biome": patch - Start with:
Fixed [#issue](link): ...
- Create file in
-
Open PR with completed template:
- Start with GitHub magic comment:
Fixes #1234 - Brief description (1-3 sentences if needed)
- Test plan showing fix works
- AI disclosure if applicable
- Start with GitHub magic comment:
-
Implement
FormatNodeRule(useformatter-developmentskill) -
Compare with Prettier:
bun packages/prettier-compare/bin/prettier-compare.js --rebuild 'code' -
Test:
cd crates/biome_js_formatter cargo test cargo insta review
-
Generate code:
just gen-formatter just f && just l -
Ask user: "Is this formatter change user-facing?" (Usually YES)
-
Create changeset:
- Create file in
.changeset/(e.g.,improve-formatting.md) - Add front matter:
"@biomejs/biome": patch - Include diff example if helpful
- Create file in
-
Open PR following template
- Bug fixes (
patch) →mainbranch - New nursery rules (
patch) →mainbranch - Rule promotions from nursery (
minor) →nextbranch - New features (
minor) →nextbranch - Breaking changes (
major) →nextbranch - Internal changes (no changeset) →
mainbranch
Follow conventional commit format:
feat(compiler): implement parsing for new type of files
fix: fix nasty unhandled error
docs: fix link to website page
test(lint): add more cases to handle invalid rules
Before opening a PR, verify:
- Tests added and passing (
cargo test) - Snapshots reviewed (
cargo insta review) - Code generation run if needed:
- Parser changes:
just gen-grammar <lang> - Formatter changes:
just gen-formatter <lang> - Lint rule changes:
just gen-rulesandjust gen-configuration - Analyzer/Bindings: Optional (CI Autofix handles this)
- Parser changes:
- Code formatted (
just f) - Code linted (
just l) - Changeset created if user-facing (file in
.changeset/with correct type) - PR template filled out completely
- AI assistance disclosed if applicable
❌ Don't:
- Skip the PR template
- Write verbose PR summaries for simple changes
- Forget to create changesets for user-facing changes
- Forget to run code generation after parser/formatter/rule changes
- Commit without formatting/linting
- Open PRs without tests
- Blindly accept all snapshot changes
- Claim patterns are "widely used" or "common" without evidence
- Implement legacy/deprecated syntax without checking with the user first
- Make assumptions about API design - inspect actual code structure first
✅ Do:
- Ask the user if unsure about changesets
- Write concise, precise PR summaries
- Push back on unnecessary verbosity
- Follow the PR template structure
- Run full test suite before committing
- Review snapshot changes carefully
- Disclose AI assistance
- Link to related issues
- Inspect AST structure before implementing (use parser crate's
quick_test) - Ask users about legacy/deprecated syntax support - wait for demand before implementing
- Verify your solution works for all relevant cases, not just the first one you find
- Reference the skills in
.claude/skills/for technical implementation details
- GitHub Discussions: https://github.com/biomejs/biome/discussions
- Discord: https://biomejs.dev/chat
- Contributing Guide: CONTRIBUTING.md
- Skills Catalog:
.claude/skills/README.md
Remember: When in doubt about changesets, ask the user. It's better to create an unnecessary changeset than to miss a required one.