14 KiB
AGENTS.md - AI Assistant Guide for Oxc
Oxc is a high-performance JavaScript/TypeScript toolchain written in Rust containing:
- Parser (JS/TS with AST), Linter (oxlint), Formatter (oxfmt), Transformer, Minifier
AI Usage Policy for Contributors
IMPORTANT: If you are an AI assistant helping a human contributor:
- Disclose AI usage - Contributors must disclose when AI tools were used to reduce maintainer fatigue
- Full responsibility - The human contributor is responsible for all AI-generated issues or PRs they submit
- Quality standards - Low-quality or unreviewed AI content will be closed immediately
All AI-generated code must be thoroughly reviewed, tested, and understood by the contributor before submission. Code should meet Oxc's performance and quality standards.
- Ban policy - Contributors who submit repeated low-quality ("slop") PRs will be banned without prior warning. Bans may be lifted if you commit to contributing to Oxc in accordance with the policy above. You may request an unban via our Discord.
Repository Structure
Rust workspace with key directories:
crates/- Core functionality (start here when exploring)apps/- Application binaries (oxlint, oxfmt)napi/- Node.js bindingsnpm/- npm packagestasks/- Development tools/automation
Avoid editing generated subdirectories.
Core Crates
oxc_parser- JS/TS parseroxc_ast- AST definitions/utilitiesoxc_semantic- Semantic analysis/symbols/scopesoxc_linter- Linting engine/rulesoxc_formatter- Code formatting (Prettier-like for JS)oxc_formatter_*- Code formatting (Prettier-like for other languages)oxc_transformer- Code transformation (Babel-like)oxc_minifier- Code minificationoxc_codegen- Code generationoxc_isolated_declarations- TypeScript declaration generationoxc_diagnostics- Error reportingoxc_traverse- AST traversal utilitiesoxc_allocator- Memory managementoxc_language_server- LSP server for editor integrationoxc- Main crate
Development Commands
Prerequisites: Rust (MSRV: 1.96), Node.js, pnpm, just
Setup Notes:
- All tools already installed (
cargo-insta,typos-cli,cargo-shear,ast-grep) - Rust components already installed (
clippy,rust-docs,rustfmt) - Use Conventional Commits for commit messages;
.github/workflows/pr.ymlrequires a scoped title likefix(parser): handle trailing comma - Run
just readyafter commits for final checks - You run in an environment where
ast-grepis available; whenever a search requires syntax-aware or structural matching, default toast-grep --lang rust -p '<pattern>'(or set--langappropriately) and avoid falling back to text-only tools likergorgrepunless I explicitly request a plain-text search.
Essential Commands
just fmt # Format code (run after modifications)
just test # Run unit/integration tests
just conformance # Run conformance tests
just ready # Run all checks (use after commits)
cargo lintgen # Regenerate linter rules enum and impls after adding/modifying rules
cargo lint-timings # Update linter timing data after changing linter rule codegen
# Crate-specific updates
just ast # Update generated files (oxc_ast changes)
just minsize # Update size snapshots (oxc_minifier changes)
just allocs # Update allocation snapshots (oxc_parser changes)
# Useful shortcuts
just watch "command" # Watch files and re-run command
just example tool # Run tool example (e.g., just example linter)
More commands can be found in justfile.
Manual Testing & Examples
Run crate examples for quick testing and debugging:
cargo run -p <crate_name> --example <example_name> -- [args]
# Common examples:
cargo run -p oxc_parser --example parser -- test.js
cargo run -p oxc_linter --example linter -- src/
cargo run -p oxc_transformer --example transformer -- input.js
cargo run -p oxc --example compiler --features="full" -- test.js
Modify examples in crates/<crate_name>/examples/ to test specific scenarios.
Code Navigation
Key Locations
- AST: Start with
oxc_ast, useoxc_ast_visitfor traversal - Linting rules:
crates/oxc_linter/src/rules/(visitor pattern) - Parser:
crates/oxc_parser/src/lib.rs, lexer insrc/lexer/ - Tests: Co-located with source, integration in
tests/, usesinstafor snapshots
Conventions
- Use
oxc_allocatorfor memory management - Follow rustfmt config in
.rustfmt.toml - Use
oxc_diagnosticsfor errors with source locations - Performance-critical: avoid unnecessary allocations
Common Tasks
Adding Linting Rule
- Use rule generator:
just new-rule <name>(ESLint rules)- Or plugin-specific:
just new-ts-rule,just new-jest-rule, etc.
- Or plugin-specific:
- Implement using visitor pattern
- Add tests in same module
- Register in appropriate category
Parser Changes
- Research and test grammar changes thoroughly
- Update AST definitions in
oxc_astif needed - Ensure existing tests pass
- Add tests for new features
Working with Transformations
- Understand AST structure first
- Use visitor pattern for traversal
- Handle node ownership/allocator carefully
- Test with various input patterns
Testing
Oxc uses multiple testing approaches tailored to each crate:
- Unit/Integration tests: Standard Rust tests in
tests/directories - Conformance tests: Against external suites (Test262, Babel, TypeScript)
- Snapshot tests: Track failures and expected outputs using
insta
Quick Test Commands
just test # Run all Rust tests
just conformance # Run all conformance tests (alias: cargo coverage)
cargo test -p <crate_name> # Test specific crate
# Conformance for specific tools
cargo coverage -- parser # Parser conformance
cargo coverage -- transformer # Transformer conformance
cargo run -p oxc_transform_conformance # Transformer Babel tests
# NAPI packages
pnpm test # Test all Node.js bindings
Crate-Specific Testing
Each crate follows distinct testing patterns:
oxc_parser
- Conformance only via
tasks/coverage - Command:
cargo coverage -- parser - Suites: Test262, Babel, TypeScript
- Special:
just allocsfor allocation tracking
oxc_linter
- Inline tests in rule files (
src/rules/**/*.rs) - Pattern: Use
Testerhelper with pass/fail cases
#[test]
fn test() {
Tester::new(RuleName::NAME, RuleName::PLUGIN, pass, fail)
.test_and_snapshot();
}
oxc_formatter (and other oxc_formatter_* language crates)
- Read the target crate's
AGENTS.md; it includes the shared formatter policy plus language-specific rules and verification commands
oxc_minifier
- Unit tests in
tests/subdirectories:ecmascript/- Operationspeephole/- Optimizationsmangler/- Name mangling
- Size tracking:
just minsize
oxc_transformer
- Multiple approaches:
- Unit tests:
tests/integrations/ - Conformance:
tasks/transform_conformance/ - Babel plugins:
tasks/transform_conformance/tests/babel-plugin-*/
- Unit tests:
- Commands:
cargo test -p oxc_transformer # Unit tests
cargo run -p oxc_transform_conformance # Conformance
just test-transform --filter <path> # Filter tests
oxc_codegen
- Integration tests in
tests/integration/ - Test files:
js.rs,ts.rs,sourcemap.rs,comments.rs
oxc_isolated_declarations
- Snapshot testing with
insta - Input:
tests/fixtures/*.{ts,tsx} - Output:
tests/snapshots/*.snap - Update:
cargo insta review
oxc_semantic
- Multiple testing approaches:
- Conformance tests (
tests/conformance/) - Contract-as-code tests for symbols and identifier references - Integration tests (
tests/integration/) - Tests for scopes, symbols, modules, classes, CFG - Snapshot tests (
tests/main.rs) - Verifies scoping data correctness (scope trees, bindings, symbols, references) usinginstasnapshots fromfixtures/ - Coverage tests - Via
tasks/coverageusing Test262, Babel, TypeScript suites
- Conformance tests (
- Command:
cargo test -p oxc_semantic - Update snapshots:
cargo insta review
Other Crates
- oxc_traverse: AST traversal -
cargo test -p oxc_traverse - oxc_ecmascript: ECMAScript operations -
cargo test -p oxc_ecmascript - oxc_regular_expression: Regex parsing -
cargo test -p oxc_regular_expression - oxc_syntax: Syntax utilities -
cargo test -p oxc_syntax - oxc_language_server: Editor integration -
cargo test -p oxc_language_server
Conformance Testing Foundation
CRITICAL: These external test suites are the CORE of Oxc's testing strategy, providing thousands of real-world test cases from mature JavaScript ecosystem projects. They ensure Oxc correctly handles the full complexity of JavaScript/TypeScript.
Suites cloned via just submodules:
| Submodule | Description | Location | Used by Crates |
|---|---|---|---|
test262 |
ECMAScript Conformance Suite Official JavaScript test suite from TC39, testing compliance with the ECMAScript specification |
tasks/coverage/test262 |
parser, semantic, codegen, transformer, minifier, estree |
babel |
Babel Test Suite Comprehensive transformation and parsing tests from the Babel compiler, covering modern JavaScript features and edge cases |
tasks/coverage/babel |
parser, semantic, codegen, transformer, minifier |
typescript |
TypeScript Test Suite Microsoft's TypeScript compiler tests, ensuring correct handling of TypeScript syntax and semantics |
tasks/coverage/typescript |
parser, semantic, codegen, transformer, estree |
estree-conformance |
ESTree Conformance Tests Test262, TypeScript, and acorn-jsx suites adapted for ESTree format validation, ensuring correct AST structure |
tasks/coverage/estree-conformance |
estree |
These suites provide:
- Thousands of battle-tested cases from real-world usage
- Edge case coverage that would be impossible to write manually
- Industry standard compliance ensuring compatibility
- Continuous validation against evolving JavaScript standards
Run all conformance tests with cargo coverage or just conformance.
Searching Test Suites
These test suites are pre-cloned and ready to search:
- Test262 (
tasks/coverage/test262/) - ECMAScript spec compliance - Babel (
tasks/coverage/babel/) - Parsing and transformation edge cases - TypeScript (
tasks/coverage/typescript/) - TypeScript syntax and semantics
NOTE: These suites are script-cloned and fully gitignored. ripgrep respects .gitignore, so a plain rg inside them silently returns nothing.
Use rg --no-ignore (or -u) when searching them.
Snapshot Testing
- Uses
instacrate for snapshot testing - Snapshots track failing tests, not passing ones
- Located in
tasks/coverage/snapshots/and conformance directories - Update with
cargo insta reviewafter changes - Formats:
.snap(counts),.snap.md(detailed failures)
NAPI (Node.js Bindings) Testing
NAPI packages use Vitest for testing Node.js bindings:
pnpm run build-test # Build all NAPI packages
pnpm test # Run all NAPI tests
Package-specific commands:
oxc-parser:cd napi/parser && pnpm run build-test && pnpm test(also haspnpm test-browser)oxc-minify:cd napi/minify && pnpm run build-test && pnpm testoxc-transform:cd napi/transform && pnpm run build-test && pnpm test
Tests are TypeScript files in each package's test/ directory.
Where to Add Tests
| Crate | Location |
|---|---|
| Parser | tasks/coverage/misc/pass/ or fail/ |
| Linter | Inline in rule files |
| Formatter | tests/fixtures/ in the formatter crate |
| Minifier | tests/ subdirectories |
| Transformer | tests/integrations/ or Babel fixtures |
| Codegen | tests/integration/ |
| Isolated Declarations | tests/fixtures/*.ts |
| Semantic | tests/ directory |
| NAPI packages | test/ directory (Vitest) |
| Language Server | Inline and /fixtures |
Linter Codegen Changes
When changing linter codegen files such as tasks/linter_codegen/** or generated linter rule runner files under crates/oxc_linter/src/generated/, run cargo lintgen and cargo lint-timings so generated rule metadata and linter timing data stay in sync.
Notes
- Rapidly evolving project - APIs may change
- Performance is critical for all changes
- Maintain JS/TS standard compatibility
- Breaking changes need documentation and discussion
For human contributors see CONTRIBUTING.md and oxc.rs