
Ultracite
- 338 installs
- 202 repo stars
- Updated August 4, 2026
- secondsky/claude-skills
ultracite is a code-quality skill that assists Ultracite-related review tasks for developers who need to enforce or improve code standards before shipping changes.
About
ultracite is a developer skill intended to help with Ultracite-related development tasks, typically used as part of a code quality and review workflow. ultracite can be applied when developers want to standardize changes, catch quality issues early, or align code with a chosen set of conventions before merging and releasing. ultracite is useful when a codebase relies on repeatable checks that should be applied consistently across many files, such as formatting, validation, or structured change review steps. Developers reach for ultracite when they need an agent to focus on quality gates and produce actionable edits or recommendations tied to code artifacts rather than broad advice.
- ultracite
Ultracite by the numbers
- 338 all-time installs (skills.sh)
- +14 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #1,235 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/secondsky/claude-skills --skill ultraciteAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 338 |
|---|---|
| repo stars | ★ 202 |
| Last updated | August 4, 2026 |
| Repository | secondsky/claude-skills ↗ |
How do I enforce code quality checks?
Use ultracite for development tasks
Who is it for?
ultracite is best for developers who use Ultracite tooling and want consistent quality and review workflows before merging.
Skip if: ultracite is not for projects that do not use Ultracite or that already have fully automated quality gates without manual intervention.
When should I use this skill?
Invoke when a developer asks to run Ultracite checks, standardize code style, or apply quality gates before merging and release.
What you get
Quality check outputs, standardized changes, and code review recommendations tied to specific files and diffs.
- quality review outputs
Files
Ultracite Skill
Fast, zero-config linting and formatting for modern JavaScript/TypeScript projects
Overview
Ultracite is a unified linting and formatting solution that supports multiple providers: Biome (default, Rust-based), ESLint+Prettier+Stylelint, and Oxlint+Oxfmt. It provides framework-specific presets and zero-configuration defaults, replacing traditional ESLint+Prettier setups with a faster, simpler alternative. Ultracite operates invisibly in the background, automatically formatting code and applying fixes on every save.
Version 7 Changes: Multi-provider architecture, preset path migration, MCP server support, AI hooks Version 6 Changes: Framework-specific presets introduced (React, Next.js, Vue, Svelte, etc.)
Core Goals
1. Lightning-Fast Performance: Leverages Biome's Rust implementation for instant linting/formatting 2. Zero-Config Design: Ships with 200+ sensible defaults optimized for modern TypeScript development 3. Simplicity & Invisibility: Operates with minimal user interaction 4. Type Safety: Enforces TypeScript strict mode and comprehensive null/undefined handling 5. Tool Compatibility: Works alongside other development tools without conflicts
Key Benefits vs Alternatives
vs ESLint + Prettier:
- 10-100x faster performance (Rust vs JavaScript)
- Single tool instead of two
- Zero configuration needed
- Auto-fixes on save by default
- Built-in TypeScript strict mode
vs Biome alone:
- 200+ preconfigured rules
- Framework-specific presets (React, Next.js, Vue, Svelte)
- AI editor integration (Cursor, Claude Code, Copilot)
- Git hook integrations
- Migration tooling
When to Use This Skill
✅ Ideal Projects
Use Ultracite when:
- Starting a new JavaScript/TypeScript project
- Building with React, Next.js, Vue, Svelte, or other modern frameworks
- Working in monorepos (Turborepo, Nx, Lerna)
- Teams want consistent formatting without bikeshedding
- Performance is critical (large codebases, CI/CD optimization)
- Migrating from ESLint + Prettier to a faster solution
- Using AI coding assistants (Cursor, Claude Code, Windsurf)
- TypeScript projects requiring strict type safety
- Projects with accessibility requirements (ARIA, semantic HTML)
⚠️ Consider Alternatives When
Limited framework support:
- Need Angular/Ember-specific rules (Biome support is basic)
- Require advanced CSS linting (Stylelint still recommended)
Specialized requirements:
- Need specific ESLint plugins not replicated in Biome
- Require property ordering in CSS (Stylelint feature)
- Team has extensive custom ESLint configurations
Legacy projects:
- Large codebases with custom ESLint rules (migration effort required)
- Projects with extensive Prettier customization
For detailed limitations and workarounds, see: references/limitations-and-workarounds.md
Interactive Components
This skill provides interactive commands and autonomous agents for streamlined workflows:
Commands
/ultracite:doctor- Validate project setup, check for v6→v7 preset paths, detect conflicts/ultracite:migrate- Interactive migration wizard (ESLint/Prettier → Ultracite, v6→v7 upgrade)
Agents
config-validator- Analyze biome.jsonc for syntax, preset paths, rule conflicts, performancemigration-assistant- Guide ESLint/Prettier migrations with rule mapping and gap analysis
See README.md for complete interactive features documentation.
Choosing a Provider
Ultracite v7 supports three linting providers. Choose based on your needs:
🚀 Biome (Default) - Recommended for most projects
- Speed: Fastest (10-100x faster than ESLint)
- Setup: Zero-config with 200+ preset rules
- Best for: New projects, TypeScript-first development, performance-critical builds
- Limitations: Fewer rules than ESLint, basic CSS/SCSS support
🔧 ESLint + Prettier + Stylelint - Recommended for maximum compatibility
- Speed: Slower but mature ecosystem
- Setup: Requires more configuration
- Best for: Projects with existing ESLint plugins, advanced CSS/SCSS linting needs
- Limitations: JavaScript-based (slower), requires multiple tools
⚡ Oxlint + Oxfmt - Recommended for maximum speed
- Speed: Fastest linting (even faster than Biome for linting only)
- Setup: Type-aware linting with TypeScript integration
- Best for: Large TypeScript codebases, type-safety-critical projects
- Limitations: Newer ecosystem, fewer rules than ESLint
Provider selection during init:
bun x ultracite init --linter biome # Default
bun x ultracite init --linter eslint # ESLint + Prettier + Stylelint
bun x ultracite init --linter oxlint # Oxlint + OxfmtLoad provider-specific documentation:
- Biome:
references/provider-biome.md - ESLint:
references/provider-eslint.md - Oxlint:
references/provider-oxlint.md
Version Migration Guide
Upgrading from v6 to v7
Breaking Change: Preset paths have changed in v7.
v6 paths (old):
{
"extends": ["ultracite/core", "ultracite/react"]
}v7 paths (new):
{
"extends": ["ultracite/biome/core", "ultracite/biome/react"]
}Migration steps: 1. Update ultracite package: bun update ultracite 2. Update preset paths in biome.jsonc (add /biome/ segment) 3. Run npx ultracite doctor to validate configuration 4. Test linting: npx ultracite check .
New v7 features:
- Multi-provider support (Biome, ESLint, Oxlint)
- MCP server integration for AI assistants
- AI hooks (auto-format after AI edits)
- Type-aware linting (Oxlint)
ultracite doctordiagnostics command
Load full v7 migration guide: references/v7-migration.md
Upgrading from v5 to v6
Key Change: Framework-specific presets introduced.
v5 approach (old):
{
"extends": ["ultracite/core"]
}v6 approach (new):
{
"extends": ["ultracite/core", "ultracite/react"] // Framework preset
}Load full v6 migration guide: references/v6-migration.md
Project Suitability Assessment
When this skill is invoked, scan the project and assess:
1. Check existing tooling:
# Check for ESLint
ls -la .eslintrc* eslint.config.* package.json | grep eslint
# Check for Prettier
ls -la .prettierrc* prettier.config.* package.json | grep prettier
# Check for Biome
ls -la biome.json* package.json | grep biome2. Identify framework:
- Check
package.jsonforreact,next,vue,svelte, etc. - Recommend appropriate preset
3. Assess project size:
- Large projects (1000+ files) benefit most from Rust performance
- Small projects may not notice speed difference
4. Check TypeScript config:
- If
tsconfig.jsonexists, note that Ultracite requiresstrictNullChecks: true - Warn if disabled (will generate many warnings)
5. Recommend or warn:
✅ RECOMMENDED: This TypeScript + React project is ideal for Ultracite
- 500+ files will benefit from Rust performance
- React preset available
- Can replace existing ESLint + Prettier setup
⚠️ CONSIDER: This project uses advanced ESLint plugins
- Custom rule: eslint-plugin-custom-security
- May need to retain ESLint for these specific rules
- Could use Ultracite for formatting onlyInstallation & Setup
Prerequisites
- Node.js v14.18+ (v18+ recommended)
- Package manager: Bun (preferred), npm, pnpm, or yarn
package.jsonfile in project root
Quick Start (Interactive)
# Using Bun (preferred for speed)
bun x ultracite init
# With provider selection (v7+)
bun x ultracite init --linter biome # Default, fastest
bun x ultracite init --linter eslint # ESLint + Prettier + Stylelint
bun x ultracite init --linter oxlint # Oxlint + Oxfmt (type-aware)
# Using npm
npx ultracite init
# Using pnpm
pnpm dlx ultracite init
# Using yarn
yarn dlx ultracite initThe interactive setup will: 1. Prompt for provider selection (Biome, ESLint, Oxlint) - v7+ only 2. Install Ultracite and provider dependencies 3. Prompt for framework selection (React, Next.js, Vue, etc.) 4. Ask about editor setup (VS Code, Cursor, etc.) 5. Offer AI agent rules installation (Cursor, Claude Code, Copilot) 6. Prompt for Git hook integration (Husky, Lefthook, lint-staged) 7. Offer to migrate from existing tools (ESLint, Prettier) 8. Create/merge configuration file (biome.jsonc, .eslintrc.js, etc.) 9. Update .vscode/settings.json for editor integration 10. Enable strictNullChecks in tsconfig.json (if TypeScript)
Non-Interactive Setup (CI/Automation)
# Auto-detect settings, skip prompts
bunx ultracite init --quiet
# Specify options explicitly (v7+)
bunx ultracite init \
--linter biome \
--pm bun \
--frameworks react,next \
--editors vscode \
--agents cursor,claude \
--integrations husky \
--migrate eslint,prettier \
--quietAvailable flags:
--linter: Provider selection (biome, eslint, oxlint) - v7+ only--pm: Package manager (bun, npm, pnpm, yarn)--frameworks: react, next, solid, vue, qwik, angular, remix, svelte--editors: vscode, zed--agents: cursor, claude, cline, copilot, windsurf, etc.--integrations: husky, lefthook, lint-staged--migrate: eslint, prettier, biome--quiet: Skip all prompts (auto-enabled whenCI=true)
Manual Setup (Advanced)
# 1. Install dependencies
bun add -D ultracite @biomejs/biome
# 2. Create biome.jsonc
cat > biome.jsonc << 'EOF'
{
"$schema": "https://biomejs.dev/schemas/2.3.8/schema.json",
"extends": ["ultracite/core"]
}
EOF
# 3. Create VS Code settings
mkdir -p .vscode
cat > .vscode/settings.json << 'EOF'
{
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"quickfix.biome": "explicit",
"source.organizeImports.biome": "explicit"
}
}
EOF
# 4. Enable TypeScript strict mode
# Add to tsconfig.json:
{
"compilerOptions": {
"strictNullChecks": true
}
}Verify Installation
# Check installation
bunx ultracite doctor
# Expected output:
# ✔ Biome is installed
# ✔ Configuration file found: biome.jsonc
# ✔ Editor integration configured
# ✔ TypeScript strict mode enabledConfiguration
Basic Configuration
File structure:
project-root/
├── biome.jsonc # Main configuration
├── .vscode/settings.json # VS Code integration
├── tsconfig.json # TypeScript config (strictNullChecks required)
└── package.jsonMinimal biome.jsonc:
{
"$schema": "https://biomejs.dev/schemas/2.3.8/schema.json",
"extends": ["ultracite/core"],
// Optional: Add framework preset
// "extends": ["ultracite/core", "ultracite/react"],
// Optional: Customize rules
"linter": {
"rules": {
"suspicious": {
"noConsoleLog": "off" // Disable specific rule
}
}
},
// Optional: Exclude files
"files": {
"ignore": ["dist", "build", "coverage", "**/*.generated.ts"]
}
}Framework Presets
- `ultracite/react`: React Hooks, JSX a11y, component best practices
- `ultracite/nextjs`: React + Next.js App Router, image optimization, document structure
- `ultracite/vue`: Vue 3 Composition API, template syntax, reactivity
- `ultracite/svelte`: Svelte 4/5 syntax, reactive declarations
Usage:
{
"extends": ["ultracite/core", "ultracite/react"]
}Core Preset
The ultracite/core preset includes 200+ rules across 7 categories:
- Accessibility: ARIA validation, semantic HTML, keyboard navigation
- Correctness: Type safety, unused code removal, exhaustive dependencies
- Performance: Code optimization, barrel file warnings
- Security: Prevents
eval(), XSS risks, unsafe patterns - Style: Consistent patterns,
constpreference, import organization - Suspicious: Catches loose equality, debugger statements, typos
- Complexity: Cognitive complexity limits
Formatting defaults: 2 spaces, 80 chars/line, LF endings, single quotes
For detailed framework presets, rule descriptions, and advanced configuration, see: references/configuration-guide.md
Usage
IDE Integration (Recommended)
VS Code Setup:
1. Install Biome extension: biomejs.biome 2. Verify .vscode/settings.json:
{
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"quickfix.biome": "explicit",
"source.organizeImports.biome": "explicit"
}
}3. Disable conflicting extensions (ESLint, Prettier)
Features:
- Auto-format on save
- Auto-fix on save (removes unused imports, fixes order, applies strict equality)
- Format on paste
- Problems panel for unfixable issues
- Quick fixes via lightbulb indicators
CLI Usage
Check code (lint only):
bunx ultracite check
bunx ultracite check src/
bunx ultracite check --diagnostic-level error # Only errorsFix code (auto-fix):
bunx ultracite check --write
bunx ultracite check --write src/Format code (format only):
bunx ultracite format --write
bunx ultracite format --write src/Package.json scripts:
{
"scripts": {
"lint": "ultracite check",
"lint:fix": "ultracite check --write",
"format": "ultracite format --write"
}
}Git Hook Integrations
Ultracite auto-detects and integrates with:
- Husky: Node.js-based hook manager
- Lefthook: Fast Go-based hook manager
- lint-staged: Runs linters on staged files only
Quick setup:
# Husky
bunx ultracite init --integrations husky
# Lefthook
bunx ultracite init --integrations lefthook
# lint-staged
bunx ultracite init --integrations lint-stagedExample `.husky/pre-commit`:
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
ultracite check --staged --writeFor complete Git hook setup guides (Husky, Lefthook, lint-staged), see: references/git-hooks-setup.md
AI Editor Rules
Ultracite generates AI editor rules that teach AI assistants about your linting/formatting standards.
Supported editors:
- Cursor (
.cursorrules) - Claude Code (
.windsurfrules) - GitHub Copilot (
.github/copilot-instructions.md) - Continue.dev (
.continuerules) - Codeium (
.codeiumrules) - Zed (
.zedrules)
Generate rules:
bunx ultracite generate-ai-rules
bunx ultracite generate-ai-rules --all # All editors
bunx ultracite generate-ai-rules --editor=cursor # Specific editorFor complete AI editor integration guide and customization, see: references/ai-editor-integration.md
Monorepo Support
Ultracite optimizes for monorepos with:
- Shared base configurations
- Package-specific overrides
- Turborepo/Nx caching integration
- Performance optimization for large workspaces
Example monorepo structure:
monorepo/
├── biome.json # Shared base config
├── apps/
│ └── web/
│ └── biome.json # Next.js-specific overrides
└── packages/
└── ui/
└── biome.json # React-specific overridesFor complete monorepo setup, Turborepo/Nx integration, and performance tips, see: references/monorepo-configuration.md
Migration from ESLint/Prettier/Biome
Automatic migration:
bunx ultracite migrate eslint
bunx ultracite migrate prettier
bunx ultracite migrate biomeManual migration: 1. Analyze current configuration 2. Map rules to Biome equivalents 3. Create biome.json with equivalent rules 4. Update package.json scripts 5. Remove old dependencies 6. Test thoroughly
For complete migration guides with detailed rule mappings, see: references/migration-guides.md
Known Limitations
CSS/SCSS: Biome does not lint CSS. Workaround: Use Stylelint Framework gaps: Limited Angular/Astro support. Workaround: Use ultracite/core + manual rules ESLint plugins: Many ESLint plugins have no Biome equivalent. Workaround: Run ESLint alongside Ultracite for specific plugins File types: No Markdown, YAML, HTML linting. Workaround: Use dedicated tools (markdownlint, yamllint, htmlhint)
For complete list of limitations and detailed workarounds, see: references/limitations-and-workarounds.md
Troubleshooting
Common issues:
- VS Code not formatting on save → Install Biome extension, configure settings
- ESLint conflicts → Disable ESLint or run selectively
- Parse errors → Configure JSX support in
biome.json - Pre-commit hooks failing → Use
bunxinstead of global install - CI failures → Pin Bun/Node versions, increase memory limit
For complete troubleshooting guide, see: references/troubleshooting.md
Templates & Scripts
Initial Setup Script
See scripts/install-ultracite.sh for automated setup.
Migration Script
See scripts/migrate-to-ultracite.sh for ESLint/Prettier migration.
Example Configurations
See references/ directory for:
configuration-guide.md: Framework presets and rule detailsgit-hooks-setup.md: Husky, Lefthook, lint-staged setupai-editor-integration.md: Cursor, Claude Code, Copilot rulesmonorepo-configuration.md: Turborepo, Nx, pnpm workspacesmigration-guides.md: ESLint, Prettier, Biome migrationtroubleshooting.md: Common issues and solutionslimitations-and-workarounds.md: Known gaps and fixes
Package Versions
Current versions (verified 2025-11-27):
ultracite: latest@biomejs/biome: >=1.9.0
Check for updates:
npm view ultracite version
npm view @biomejs/biome versionUpdate:
bun update ultracite @biomejs/biomeResources
Official Documentation:
- https://www.ultracite.ai/introduction
- https://www.ultracite.ai/setup
- https://www.ultracite.ai/configuration
- https://biomejs.dev/
Examples:
- https://www.ultracite.ai/examples
Troubleshooting:
- https://www.ultracite.ai/troubleshooting
- https://www.ultracite.ai/faq
Community:
- GitHub Issues: https://github.com/ultracite/ultracite
- Biome Discord: https://discord.gg/biome
When to Load References
Load reference files on-demand based on user questions or task requirements:
`references/provider-biome.md`: When user asks about:
- Biome provider specifics
- Biome-only configuration
- Biome performance optimization
- Biome preset paths (v7:
ultracite/biome/*) - Biome rule customization
`references/provider-eslint.md`: When user asks about:
- ESLint provider setup
- ESLint + Prettier + Stylelint integration
- ESLint plugin configuration
- ESLint migration to Ultracite
- Advanced CSS/SCSS linting
`references/provider-oxlint.md`: When user asks about:
- Oxlint provider setup
- Type-aware linting features
- Oxlint performance benefits
- Oxlint vs Biome comparison
- TypeScript integration
`references/v6-migration.md`: When user asks about:
- Upgrading from v5 to v6
- Framework preset introduction
- v6 configuration changes
- v6 breaking changes
`references/v7-migration.md`: When user asks about:
- Upgrading from v6 to v7
- Preset path migration (
ultracite/core→ultracite/biome/core) - Multi-provider setup
- v7 breaking changes
ultracite doctorcommand
`references/mcp-integration.md`: When user asks about:
- MCP server setup
- AI assistant integration via MCP
- Model Context Protocol
- MCP server configuration
`references/ai-hooks.md`: When user asks about:
- AI hooks setup (distinct from AI rules)
- Auto-format after AI edits
- Editor hook configuration
- Post-edit formatting automation
`references/configuration-guide.md`: When user asks about:
- Framework presets (React, Next.js, Vue, Svelte)
- Core preset rules (200+ rules breakdown)
- Rule customization methods
- File exclusion patterns
- Advanced configuration
`references/git-hooks-setup.md`: When user asks about:
- Pre-commit hooks
- Husky integration
- Lefthook integration
- lint-staged setup
- CI/CD integration
- Hook troubleshooting
`references/ai-editor-integration.md`: When user asks about:
- AI editor rules generation
- Cursor integration
- Claude Code integration
- GitHub Copilot setup
- Custom AI rules
- Editor-specific setup
`references/monorepo-configuration.md`: When user asks about:
- Monorepo setup
- Turborepo integration
- Nx integration
- Package-specific overrides
- Workspace configuration
- Performance optimization
`references/migration-guides.md`: When user asks about:
- ESLint migration
- Prettier migration
- Biome migration
- Rule mapping
- Migration checklist
- Post-migration steps
`references/troubleshooting.md`: When user asks about:
- VS Code issues
- ESLint/Prettier conflicts
- Parse errors
- Pre-commit hook failures
- CI failures
- TypeScript strictness errors
- Installation issues
- Performance problems
`references/limitations-and-workarounds.md`: When user asks about:
- CSS linting
- Framework support gaps
- ESLint plugin ecosystem
- File type support
- Editor integration
- Migration limitations
Secure Installation
When installing linting/formatting packages, follow supply chain security best practices:
- Block post-install scripts —
npm config set ignore-scripts true(or Bun: disabled by default) - Cooldown period — Wait 7 days for new package versions to be vetted by the community
- Audit before installing — Run
socket package score npm <pkg>or usesocket npm install <pkg>to check packages
Load the dependency-upgrade skill for full security configuration including Socket CLI integration, cooldown setup, lockfile validation, and CI enforcement.
Summary
Ultracite provides a unified linting and formatting solution with multi-provider support:
✅ Use when:
- Starting new projects
- Building with React/Next/Vue/Svelte
- Working in monorepos
- Want consistent formatting without configuration
- Performance matters (Biome/Oxlint providers)
- Need ESLint compatibility (ESLint provider)
- Using AI coding assistants
- Require type-aware linting (Oxlint)
⚠️ Consider alternatives when:
- Need specific ESLint plugins not supported by any provider
- Advanced CSS linting required (though ESLint provider includes Stylelint)
- Legacy framework support needed
Key advantages:
- Multi-provider: Choose Biome (fastest), ESLint (most compatible), or Oxlint (type-aware)
- Version 7: Preset path migration, MCP server, AI hooks, multi-provider architecture
- Version 6: Framework-specific presets (React, Next.js, Vue, Svelte, etc.)
- 10-100x faster than traditional ESLint + Prettier (Biome/Oxlint)
- Zero configuration (200+ rules preconfigured for Biome)
- Framework-specific presets
- AI editor integration + AI hooks
- Git hook support
- TypeScript strict mode enforced
Installation:
bun x ultracite init --linter biome # Default (v7+)
bun x ultracite init --linter eslint # ESLint provider (v7+)
bun x ultracite init --linter oxlint # Oxlint provider (v7+)Most common workflow: 1. Install with bun x ultracite init 2. Select framework preset (React, Next.js, etc.) 3. Choose Git hook integration (Husky, Lefthook, lint-staged) 4. Enable AI editor rules (Cursor, Claude Code, Copilot) 5. Optionally migrate from ESLint/Prettier 6. Code with auto-formatting on save 7. Commit with pre-commit hooks ensuring quality
Remember:
- Always check for existing Git hook managers before installing
- Assess project suitability (scan for ESLint/Prettier/frameworks)
- Recommend or warn based on project characteristics
- Enable
strictNullChecksin TypeScript projects - Use framework-specific presets for best results
- Load reference files on-demand based on user questions
Ultracite Configuration Validator Agent
Autonomous agent for analyzing Ultracite/Biome configurations and providing actionable recommendations.
Purpose
This agent specializes in:
- Validating biome.jsonc syntax and structure
- Detecting deprecated preset paths (v6 vs v7)
- Identifying conflicting or redundant rules
- Recommending performance optimizations
- Checking TypeScript and Node.js compatibility
When to Use
This agent automatically triggers when the user mentions:
- "is my ultracite config correct?"
- "validate my biome configuration"
- "check my ultracite setup"
- "why isn't ultracite working?"
- "ultracite configuration errors"
- "optimize my biome config"
- "what's wrong with my biome.jsonc?"
- "validate linting configuration"
Or explicitly invokes the agent:
- "Use config-validator to check my setup"
Analysis Phases
Phase 1: Configuration Discovery
Goal: Locate and read configuration files
Steps: 1. Search for biome.jsonc in current directory 2. Check for biome.json as fallback 3. Read package.json to verify ultracite installation 4. Note provider being used (Biome/ESLint/Oxlint)
Output:
Configuration Discovery
=======================
✅ Found: biome.jsonc
✅ Ultracite: v7.2.0
✅ Provider: Biome v1.9.4Phase 2: Syntax Validation
Goal: Ensure configuration is valid JSON/JSONC
Steps: 1. Parse biome.jsonc as JSONC (allows comments, trailing commas) 2. Check for syntax errors 3. Validate against Biome schema 4. Report line numbers for errors
Detection Patterns:
- Missing commas
- Trailing commas in strict JSON
- Invalid comment syntax
- Unclosed braces/brackets
Output:
Syntax Validation
=================
✅ JSONC syntax: Valid
✅ Schema validation: PassedError Example:
❌ Syntax Error at line 12
10: "linter": {
11: "enabled": true
> 12: "rules": {
^
Error: Expected comma after property value
Fix: Add comma after "enabled": true,Phase 3: Preset Path Validation
Goal: Check for v6 vs v7 preset paths and validate existence
Steps: 1. Extract extends array from config 2. Check each preset path 3. Detect v6 paths (missing provider prefix) 4. Verify preset files exist
v6 vs v7 Detection:
| v6 Path (Old) | v7 Path (New) | Status |
|---|---|---|
ultracite/core | ultracite/biome/core | ⚠️ Deprecated |
ultracite/react | ultracite/biome/react | ⚠️ Deprecated |
ultracite/nextjs | ultracite/biome/nextjs | ⚠️ Deprecated |
ultracite/vue | ultracite/biome/vue | ⚠️ Deprecated |
ultracite/svelte | ultracite/biome/svelte | ⚠️ Deprecated |
Output:
Preset Path Validation
======================
⚠️ Using v6 preset paths (deprecated)
Found:
- "ultracite/core"
- "ultracite/react"
Should be:
- "ultracite/biome/core"
- "ultracite/biome/react"
Fix: Run /ultracite:migrate to upgrade pathsMissing Preset Example:
❌ Preset not found: "ultracite/biome/angular"
Available presets:
- ultracite/biome/core
- ultracite/biome/react
- ultracite/biome/nextjs
- ultracite/biome/vue
- ultracite/biome/svelte
- ultracite/biome/astro
Fix: Use an available preset or create custom configurationPhase 4: Rule Conflict Analysis
Goal: Detect conflicting, redundant, or incompatible rules
Steps: 1. Extract all configured rules 2. Check for known conflicts 3. Identify redundant rules 4. Validate rule option values
Common Conflicts:
| Rule 1 | Rule 2 | Issue |
|---|---|---|
style/useConst | style/noVar | Redundant (useConst implies noVar) |
correctness/noUnusedVariables | TypeScript noUnusedLocals | Duplicate (prefer TypeScript) |
suspicious/noDoubleEquals (error) | suspicious/noDoubleEquals (warn) | Conflicting severity |
Output:
Rule Conflict Analysis
======================
⚠️ Found 2 redundant rules
1. style/useConst + style/noVar
→ style/useConst already enforces no var usage
Recommendation: Remove style/noVar
2. correctness/noUnusedVariables (Biome) + noUnusedLocals (TypeScript)
→ TypeScript already checks unused locals
Recommendation: Disable correctness/noUnusedVariables if using TypeScriptPhase 5: Performance Analysis
Goal: Identify performance bottlenecks and optimization opportunities
Steps: 1. Count total files in project 2. Analyze ignore patterns 3. Check for inefficient globs 4. Recommend provider based on size
Performance Checks:
1. File Count Analysis
find . -type f \( -name "*.js" -o -name "*.ts" -o -name "*.tsx" \) | wc -l2. Ignore Pattern Check
- Ensure
node_modulesexcluded - Check for
dist,build,.next,.nuxtexclusions - Validate glob patterns are efficient
3. Provider Recommendation
- < 500 files: Biome (fastest)
- 500-2000 files: Biome or Oxlint
- > 2000 files: Oxlint (parallel processing)
- TypeScript heavy: Oxlint (type-aware)
Output:
Performance Analysis
====================
✅ Project size: ~350 files
✅ Provider: Biome (optimal for this size)
✅ Ignore patterns: Properly configured
⚠️ Missing ignore:
- .turbo (monorepo build cache)
- .vercel (deployment artifacts)
Add to biome.jsonc:
"files": {
"ignore": [
"node_modules",
"dist",
".turbo",
".vercel"
]
}
Estimated lint time: < 1sLarge Project Warning:
⚠️ Performance Warning
Project size: ~2,500 files
Current provider: Biome
Recommendation: Consider switching to Oxlint provider
- Oxlint uses parallel processing (faster for large codebases)
- Oxlint supports type-aware linting (better TypeScript support)
To switch:
npm install -D oxlint
Update biome.jsonc to use ultracite/oxlint/* presets
See: references/provider-oxlint.mdPhase 6: Compatibility Check
Goal: Verify environment compatibility
Steps: 1. Check Node.js version 2. Verify TypeScript version (if applicable) 3. Check @biomejs/biome version 4. Validate editor integration
Compatibility Matrix:
| Requirement | Min Version | Recommended |
|---|---|---|
| Node.js | 18.x | 20.x+ |
| TypeScript | 4.x | 5.x+ |
| Biome | 1.8.x | 1.9.4+ |
Output:
Compatibility Check
===================
✅ Node.js: v20.10.0 (supported)
✅ TypeScript: v5.3.3 (recommended)
✅ Biome: v1.9.4 (latest)
✅ Editor integration: VS Code with Biome extension detected
- Auto-format on save: Enabled
- Linting: EnabledIncompatibility Example:
⚠️ Compatibility Issue
Node.js: v16.20.0
Required: v18.x or higher
Ultracite/Biome requires Node.js 18+ for optimal performance.
Upgrade:
- Using nvm: nvm install 20 && nvm use 20
- Using Homebrew: brew upgrade node
- Download: https://nodejs.org/Final Report Format
Ultracite Configuration Analysis Report
========================================
CONFIGURATION
-------------
✅ File: biome.jsonc
✅ Syntax: Valid JSONC
✅ Schema: Compliant with Biome 1.9.4
PRESETS
-------
⚠️ Using v6 preset paths (upgrade recommended)
- "ultracite/core" → "ultracite/biome/core"
- "ultracite/react" → "ultracite/biome/react"
Fix: Run /ultracite:migrate to upgrade to v7 paths
RULES
-----
✅ 200+ rules active
⚠️ 2 redundant rules detected
- style/useConst + style/noVar (remove noVar)
- Biome correctness/noUnusedVariables + TS noUnusedLocals (disable Biome)
PERFORMANCE
-----------
✅ Project size: ~350 files
✅ Provider: Biome (optimal)
✅ Ignore patterns: Configured
⚠️ Missing: .turbo, .vercel directories
Estimated lint time: < 1s
COMPATIBILITY
-------------
✅ Node.js: v20.10.0
✅ TypeScript: v5.3.3
✅ Biome: v1.9.4
✅ Editor: VS Code with Biome extension
RECOMMENDATIONS
---------------
1. Priority: Run /ultracite:migrate to upgrade preset paths
2. Optimization: Remove redundant style/noVar rule
3. Performance: Add .turbo and .vercel to ignore patterns
4. TypeScript: Disable Biome's correctness/noUnusedVariables (use TS check)
Overall Status: ⚠️ GOOD (with minor improvements needed)
Next Steps:
1. Run: /ultracite:migrate
2. Edit biome.jsonc to remove redundant rules
3. Add .turbo and .vercel to ignore patterns
4. Test: npx ultracite check .Error Diagnosis
No Configuration Found
❌ No Ultracite configuration found
Looking for:
- biome.jsonc
- biome.json
To create:
npx ultracite init
Or copy from examples:
See references/biome.jsonc.react.exampleInvalid JSON Syntax
❌ Configuration syntax error
File: biome.jsonc
Line 15: Unexpected token }
13: "enabled": true,
14: "rules": {}
> 15: }}
^
Error: Unexpected token
Fix: Remove extra closing braceUnknown Rules
⚠️ Unknown rules detected
The following rules are not recognized:
- "style/useFoo" (line 42)
- "correctness/noBar" (line 57)
Possible causes:
1. Typo in rule name
2. Rule removed in newer Biome version
3. Rule from different provider (Oxlint/ESLint)
Check: https://biomejs.dev/linter/rules/Related Resources
Load these references when needed:
references/configuration-guide.md- Complete rule reference (200+ rules)references/troubleshooting.md- Common configuration issuesreferences/v6-migration.md- v6→v7 preset path migrationreferences/provider-biome.md- Biome provider detailsreferences/monorepo-configuration.md- Monorepo-specific optimizations
Related Commands
/ultracite:doctor- Full setup validation (config + environment)/ultracite:migrate- Upgrade v6→v7 or migrate from ESLint/Prettier
Implementation Notes
This agent uses:
- Read tool to read biome.jsonc and package.json
- Grep tool to search for preset paths and rules
- Glob tool to count project files
- Bash tool to check Node.js version and run validation
No files are modified - this is a read-only analysis agent.
Success Criteria
A successful validation provides: 1. ✅ Syntax validation result 2. ✅ Preset path analysis (v6 vs v7) 3. ✅ Rule conflict detection 4. ✅ Performance recommendations 5. ✅ Compatibility status 6. ✅ Prioritized action items 7. ✅ Overall health status
Ultracite Migration Assistant Agent
Autonomous agent for analyzing ESLint/Prettier configurations and guiding migrations to Ultracite with detailed rule mapping.
Purpose
This agent specializes in:
- Detecting existing ESLint/Prettier configurations
- Mapping ESLint rules to Biome equivalents
- Identifying rules with no Biome equivalent
- Generating biome.jsonc from ESLint/Prettier configs
- Providing migration guidance and workarounds
- Upgrading v6 preset paths to v7 format
When to Use
This agent automatically triggers when the user mentions:
- "migrate from eslint"
- "switch to ultracite from prettier"
- "replace eslint with biome"
- "convert eslint config to ultracite"
- "how to migrate to ultracite?"
- "upgrade ultracite v6 to v7"
- "update preset paths to v7"
- "eslint to biome migration"
Or explicitly invokes the agent:
- "Use migration-assistant to help me migrate"
Migration Types Supported
1. ESLint → Ultracite/Biome 2. Prettier → Ultracite/Biome 3. ESLint + Prettier → Ultracite/Biome (combined) 4. Ultracite v6 → v7 (preset path upgrade)
Migration Phases
Phase 1: Configuration Detection
Goal: Find and identify existing configurations
Steps: 1. Search for ESLint config files 2. Search for Prettier config files 3. Read package.json for inline configs 4. Identify plugins and extensions used
ESLint Config Files (searched in order):
eslint.config.js(flat config).eslintrc.js.eslintrc.cjs.eslintrc.json.eslintrc.yml.eslintrc.yamlpackage.json(eslintConfig field)
Prettier Config Files:
prettier.config.js.prettierrc.js.prettierrc.prettierrc.json.prettierrc.yml.prettierrc.yamlpackage.json(prettier field)
Output:
Configuration Detection
=======================
ESLint Configuration:
✅ Found: .eslintrc.js
- 45 rules configured
- Plugins: @typescript-eslint, react, jsx-a11y
- Extends: eslint:recommended, plugin:react/recommended
Prettier Configuration:
✅ Found: .prettierrc
- printWidth: 80
- semi: false
- singleQuote: true
- trailingComma: 'es5'
Next: Analyzing rule compatibility...Phase 2: Rule Mapping & Gap Analysis
Goal: Map ESLint rules to Biome equivalents and identify gaps
Steps: 1. Extract all ESLint rules and their configurations 2. Map each rule to Biome equivalent 3. Identify rules with no equivalent 4. Suggest workarounds for gaps 5. Calculate mapping coverage percentage
ESLint → Biome Rule Mapping Database:
Correctness Rules
| ESLint Rule | Biome Equivalent | Coverage |
|---|---|---|
no-unused-vars | correctness/noUnusedVariables | ✅ 100% |
no-undef | correctness/noUndeclaredVariables | ✅ 100% |
no-const-assign | correctness/noConstAssign | ✅ 100% |
no-dupe-keys | correctness/noDuplicateObjectKeys | ✅ 100% |
no-unreachable | correctness/noUnreachable | ✅ 100% |
constructor-super | correctness/noInvalidConstructorSuper | ✅ 100% |
no-this-before-super | correctness/noUnreachableSuper | ✅ 100% |
Suspicious Rules
| ESLint Rule | Biome Equivalent | Coverage |
|---|---|---|
no-console | suspicious/noConsoleLog | ✅ 100% |
eqeqeq | suspicious/noDoubleEquals | ✅ 100% |
no-debugger | suspicious/noDebugger | ✅ 100% |
no-empty | suspicious/noEmptyBlockStatements | ✅ 100% |
no-extra-boolean-cast | complexity/noExtraBooleanCast | ✅ 100% |
no-fallthrough | suspicious/noFallthroughSwitchClause | ✅ 100% |
Style Rules
| ESLint Rule | Biome Equivalent | Coverage |
|---|---|---|
prefer-const | style/useConst | ✅ 100% |
no-var | style/noVar | ✅ 100% |
arrow-body-style | style/useArrowFunction | ✅ 100% |
prefer-template | style/useTemplate | ✅ 100% |
object-shorthand | style/useShorthandPropertyAssignment | ✅ 100% |
prefer-exponentiation-operator | style/useExponentiationOperator | ✅ 100% |
TypeScript Rules
| ESLint Rule | Biome Equivalent | Coverage |
|---|---|---|
@typescript-eslint/no-explicit-any | suspicious/noExplicitAny | ✅ 100% |
@typescript-eslint/no-unused-vars | correctness/noUnusedVariables | ✅ 100% |
@typescript-eslint/prefer-as-const | style/useAsConstAssertion | ✅ 100% |
@typescript-eslint/no-namespace | style/noNamespace | ✅ 100% |
React Rules
| ESLint Rule | Biome Equivalent | Coverage |
|---|---|---|
react/jsx-key | correctness/useJsxKeyInIterable | ✅ 100% |
react/jsx-no-duplicate-props | correctness/noDuplicateJsxProps | ✅ 100% |
react/no-children-prop | correctness/noChildrenProp | ✅ 100% |
react/void-dom-elements-no-children | correctness/noVoidElementsWithChildren | ✅ 100% |
react/button-has-type | a11y/useButtonType | ✅ 100% |
Gap Analysis - Rules with No Equivalent
| ESLint Rule | Status | Workaround |
|---|---|---|
@typescript-eslint/no-floating-promises | ❌ No equivalent | Use Oxlint provider (type-aware) |
@typescript-eslint/no-misused-promises | ❌ No equivalent | Use Oxlint provider (type-aware) |
@typescript-eslint/await-thenable | ❌ No equivalent | Use Oxlint provider (type-aware) |
eslint-plugin-security/detect-object-injection | ❌ No equivalent | Manual code review |
eslint-plugin-security/detect-non-literal-require | ❌ No equivalent | Manual code review |
import/no-cycle | ❌ No equivalent | Manual dependency analysis |
import/no-extraneous-dependencies | ❌ No equivalent | Use depcheck or similar tools |
react/no-unstable-nested-components | ❌ No equivalent | Manual code review |
jsx-a11y/click-events-have-key-events | ⚠️ Partial | Biome a11y rules are limited |
Output:
Rule Mapping Analysis
=====================
Total ESLint rules: 45
Mapped to Biome: 38 (84%)
No equivalent: 7 (16%)
Mapped Rules (38):
✅ no-unused-vars → correctness/noUnusedVariables
✅ eqeqeq → suspicious/noDoubleEquals
✅ prefer-const → style/useConst
... (35 more)
Unmapped Rules (7):
❌ @typescript-eslint/no-floating-promises
Workaround: Switch to Oxlint provider for type-aware linting
See: references/provider-oxlint.md
❌ eslint-plugin-security/detect-object-injection
Workaround: Manual code review for security issues
Consider: SonarQube or Snyk for security scanning
❌ import/no-cycle
Workaround: Use madge or dpdm for dependency analysis
Install: npm i -D madge
... (4 more)
Coverage: 84% (Good - most rules mapped)Phase 3: Prettier Mapping
Goal: Map Prettier options to Biome formatter configuration
Prettier → Biome Formatter Mapping:
| Prettier Option | Biome Equivalent | Notes |
|---|---|---|
printWidth: 80 | formatter.lineWidth: 80 | ✅ Direct mapping |
tabWidth: 2 | formatter.indentWidth: 2 | ✅ Direct mapping |
useTabs: false | formatter.indentStyle: "space" | ✅ Direct mapping |
semi: true | javascript.formatter.semicolons: "always" | ✅ Direct mapping |
semi: false | javascript.formatter.semicolons: "asNeeded" | ✅ Direct mapping |
singleQuote: true | javascript.formatter.quoteStyle: "single" | ✅ Direct mapping |
singleQuote: false | javascript.formatter.quoteStyle: "double" | ✅ Direct mapping |
trailingComma: "es5" | javascript.formatter.trailingCommas: "es5" | ✅ Direct mapping |
trailingComma: "all" | javascript.formatter.trailingCommas: "all" | ✅ Direct mapping |
arrowParens: "always" | javascript.formatter.arrowParentheses: "always" | ✅ Direct mapping |
arrowParens: "avoid" | javascript.formatter.arrowParentheses: "asNeeded" | ✅ Direct mapping |
bracketSpacing: true | json.formatter.trailingCommas: "none" | ✅ Default behavior |
quoteProps: "as-needed" | javascript.formatter.quoteProperties: "asNeeded" | ✅ Direct mapping |
Output:
Prettier Formatter Mapping
==========================
Prettier Options Detected:
- printWidth: 80
- semi: false
- singleQuote: true
- trailingComma: 'es5'
- arrowParens: 'avoid'
Biome Formatter Equivalent:
{
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 80
},
"javascript": {
"formatter": {
"semicolons": "asNeeded",
"quoteStyle": "single",
"trailingCommas": "es5",
"arrowParentheses": "asNeeded"
}
}
}
Coverage: 100% (all Prettier options mapped)Phase 4: Configuration Generation
Goal: Generate biome.jsonc from ESLint/Prettier configs
Steps: 1. Determine framework preset (React, Next.js, Vue, Svelte) 2. Create extends array with appropriate presets 3. Add mapped rules to linter.rules 4. Add formatter configuration from Prettier 5. Add comments for unmapped rules 6. Validate generated config
Framework Detection Logic:
Check package.json dependencies for:
react→ Useultracite/biome/reactpresetnext→ Useultracite/biome/nextjspresetvue→ Useultracite/biome/vuepresetsvelte→ Useultracite/biome/sveltepresetastro→ Useultracite/biome/astropreset- None detected → Use
ultracite/biome/coreonly
Generated Configuration Template:
{
"$schema": "https://biomejs.dev/schemas/2.3.8/schema.json",
"extends": [
"ultracite/biome/core",
"ultracite/biome/react" // Detected from dependencies
],
"files": {
"ignore": [
"node_modules",
"dist",
"build",
".next",
"coverage"
]
},
"linter": {
"enabled": true,
"rules": {
"correctness": {
"noUnusedVariables": "error", // Mapped from no-unused-vars
"noUndeclaredVariables": "error" // Mapped from no-undef
},
"suspicious": {
"noConsoleLog": "warn", // Mapped from no-console
"noDoubleEquals": "error" // Mapped from eqeqeq
},
"style": {
"useConst": "error", // Mapped from prefer-const
"noVar": "error" // Mapped from no-var
}
// Unmapped rules (see comments below)
}
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 80
},
"javascript": {
"formatter": {
"semicolons": "asNeeded", // From Prettier: semi: false
"quoteStyle": "single", // From Prettier: singleQuote: true
"trailingCommas": "es5", // From Prettier: trailingComma: 'es5'
"arrowParentheses": "asNeeded" // From Prettier: arrowParens: 'avoid'
}
}
}
// UNMAPPED RULES
// ==============
// The following ESLint rules have no direct Biome equivalent:
//
// 1. @typescript-eslint/no-floating-promises
// → Consider using Oxlint provider for type-aware linting
// → See: references/provider-oxlint.md
//
// 2. eslint-plugin-security/detect-object-injection
// → Manual code review recommended
// → Consider: SonarQube or Snyk for security scanning
//
// 3. import/no-cycle
// → Use madge or dpdm for dependency cycle detection
// → Install: npm i -D madge
// → Run: npx madge --circular src/Output:
Configuration Generation
========================
✅ Generated biome.jsonc
- Framework preset: React (detected from dependencies)
- Linter rules: 38 mapped
- Formatter: Configured from Prettier settings
- Comments: 7 unmapped rules documented
Preview:
- File: biome.jsonc (94 lines)
- Presets: ultracite/biome/core, ultracite/biome/react
- Rules: 38 active + 7 unmapped (documented in comments)
- Formatter: Enabled with Prettier settings
Next: Backup old configs and validatePhase 5: Backup Strategy
Goal: Safely backup old configurations before migration
Steps: 1. Create .backup/ directory 2. Move ESLint configs to .backup/ 3. Move Prettier configs to .backup/ 4. Create backup manifest 5. Provide rollback instructions
Backup Process:
mkdir -p .backup/
mv .eslintrc.js .backup/
mv .prettierrc .backup/
mv .eslintignore .backup/
mv .prettierignore .backup/Backup Manifest (created in .backup/manifest.txt):
Ultracite Migration Backup
Created: 2025-01-18 10:30:00
Backed up files:
- .eslintrc.js → .backup/.eslintrc.js
- .prettierrc → .backup/.prettierrc
- .eslintignore → .backup/.eslintignore
- .prettierignore → .backup/.prettierignore
Original ESLint configuration:
- 45 rules
- Plugins: @typescript-eslint, react, jsx-a11y
- Extends: eslint:recommended, plugin:react/recommended
Original Prettier configuration:
- printWidth: 80
- semi: false
- singleQuote: true
To rollback:
1. Remove biome.jsonc
2. Restore files: mv .backup/.eslintrc.js .
3. Restore packages: npm install -D eslint prettierOutput:
Backup Strategy
===============
✅ Created .backup/ directory
✅ Backed up:
- .eslintrc.js
- .prettierrc
- .eslintignore
- .prettierignore
✅ Created backup manifest: .backup/manifest.txt
Rollback instructions included in manifest.Phase 6: Validation & Testing
Goal: Validate generated configuration and test on codebase
Steps: 1. Validate biome.jsonc syntax 2. Run ultracite check on sample files 3. Compare results with ESLint (if possible) 4. Report differences and issues
Validation Commands:
# 1. Syntax validation
npx ultracite check --config-only
# 2. Test on sample files
npx ultracite check src/App.tsx src/utils/api.ts
# 3. Full project check
npx ultracite check .
# 4. Compare with ESLint (before removing)
npx eslint src/ > eslint-results.txt
npx ultracite check src/ > ultracite-results.txtOutput:
Validation & Testing
====================
✅ Syntax Validation
- biome.jsonc is valid
✅ Sample File Testing
- Tested: src/App.tsx, src/utils/api.ts
- Errors: 0
- Warnings: 3 (all auto-fixable)
⚠️ Full Project Check
- Total files: 127
- Errors: 5
- Warnings: 23
- Auto-fixable: 21
Comparison with ESLint:
- ESLint found: 28 issues
- Ultracite found: 28 issues
- Coverage: 100% (all ESLint issues detected)
Next: Fix issues with npx ultracite check --write .Phase 7: v6→v7 Preset Path Migration
Goal: Upgrade Ultracite v6 preset paths to v7 format
v6 → v7 Mapping:
| v6 Path | v7 Path |
|---|---|
ultracite/core | ultracite/biome/core |
ultracite/react | ultracite/biome/react |
ultracite/nextjs | ultracite/biome/nextjs |
ultracite/vue | ultracite/biome/vue |
ultracite/svelte | ultracite/biome/svelte |
ultracite/astro | ultracite/biome/astro |
Steps: 1. Read biome.jsonc 2. Find all v6 preset paths in extends array 3. Replace with v7 equivalents 4. Validate new paths exist 5. Test configuration
Implementation:
// Before (v6)
{
"extends": [
"ultracite/core",
"ultracite/react"
]
}
// After (v7)
{
"extends": [
"ultracite/biome/core",
"ultracite/biome/react"
]
}Output:
v6→v7 Preset Path Migration
===========================
Detected v6 Paths:
- "ultracite/core"
- "ultracite/react"
Upgraded to v7 Paths:
- "ultracite/biome/core"
- "ultracite/biome/react"
✅ Validation: All presets exist
✅ Test run: npx ultracite check .
- 0 errors
Migration complete!Final Migration Report
Ultracite Migration Report
==========================
MIGRATION TYPE
--------------
ESLint + Prettier → Ultracite/Biome
ANALYSIS
--------
ESLint Configuration:
✅ Found: .eslintrc.js
- 45 rules configured
- Plugins: @typescript-eslint, react, jsx-a11y
- Extends: eslint:recommended, plugin:react/recommended
Prettier Configuration:
✅ Found: .prettierrc
- printWidth: 80, semi: false, singleQuote: true
RULE MAPPING
------------
✅ Mapped: 38 rules (84%)
❌ No equivalent: 7 rules (16%)
Unmapped Rules:
1. @typescript-eslint/no-floating-promises
→ Use Oxlint provider (type-aware linting)
2. eslint-plugin-security/detect-object-injection
→ Manual code review recommended
3. import/no-cycle
→ Use madge: npm i -D madge && npx madge --circular src/
... (4 more - see biome.jsonc comments)
GENERATED CONFIGURATION
-----------------------
✅ Created: biome.jsonc (94 lines)
- Framework preset: React
- Linter rules: 38 active
- Formatter: Configured from Prettier
- Comments: 7 unmapped rules documented
BACKUP
------
✅ Old configs backed up to .backup/
- .eslintrc.js
- .prettierrc
- .eslintignore
- .prettierignore
✅ Backup manifest: .backup/manifest.txt
VALIDATION
----------
✅ Syntax: Valid
✅ Test run: npx ultracite check .
- 5 errors
- 23 warnings (21 auto-fixable)
✅ Comparison with ESLint:
- Coverage: 100% (all ESLint issues detected by Ultracite)
NEXT STEPS
----------
1. Fix issues: npx ultracite check --write .
2. Review unmapped rules in biome.jsonc comments
3. Consider Oxlint provider for type-aware linting:
npm install -D oxlint
See: references/provider-oxlint.md
4. Remove old packages:
npm uninstall eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
npm uninstall prettier eslint-config-prettier
5. Update package.json scripts:
"lint": "ultracite check ."
"format": "ultracite check --write ."
6. Commit changes:
git add biome.jsonc .backup/
git commit -m "Migrate to Ultracite from ESLint + Prettier"
ROLLBACK INSTRUCTIONS
---------------------
If issues occur:
1. Remove biome.jsonc
2. Restore: mv .backup/.eslintrc.js . && mv .backup/.prettierrc .
3. Reinstall: npm install -D eslint prettier
4. See: .backup/manifest.txt
Migration Status: ✅ SUCCESS (with 7 unmapped rules to review)Related Resources
Load these references when needed:
references/migration-guides.md- Complete ESLint/Prettier rule mappingsreferences/provider-biome.md- Biome provider detailsreferences/provider-oxlint.md- Oxlint for type-aware lintingreferences/troubleshooting.md- Common migration issuesreferences/v6-migration.md- v6→v7 preset path migration
Related Commands
/ultracite:migrate- Interactive migration wizard (uses this agent)/ultracite:doctor- Validate setup after migration
Implementation Notes
This agent uses:
- Read tool to read ESLint/Prettier configs and package.json
- Glob tool to find config files
- Write tool to create biome.jsonc and backup manifest
- Edit tool to update preset paths (v6→v7)
- Bash tool to run validation commands
- Grep tool to search for preset paths
Files are modified with backups created first for safety.
Success Criteria
A successful migration provides: 1. ✅ Complete rule mapping analysis 2. ✅ Unmapped rules with workarounds 3. ✅ Generated biome.jsonc configuration 4. ✅ Backed up old configurations 5. ✅ Validation test results 6. ✅ Next steps and rollback instructions 7. ✅ Migration status report
Ultracite Doctor Command
Run comprehensive diagnostics on your Ultracite setup.
What This Command Does
1. Installation Check
- Verify ultracite is installed in package.json
- Check @biomejs/biome version
- Detect provider (Biome/ESLint/Oxlint)
2. Configuration Validation
- Parse biome.jsonc syntax
- Check for deprecated presets (v6 vs v7 paths)
- Validate preset paths exist
- Detect incompatible rule combinations
3. Conflict Detection
- Check for lingering ESLint/Prettier configs
- Warn about potential tool conflicts
- Suggest cleanup steps
4. Environment Check
- Verify Node.js version
- Check for Git hooks integration
- Validate editor integration
5. Performance Analysis
- Estimate project size
- Recommend provider based on size
- Suggest optimization opportunities
How to Use
Simply run /ultracite:doctor in your project directory. The command will automatically:
1. Scan your project for Ultracite installation 2. Validate your configuration files 3. Check for common issues 4. Provide actionable recommendations
Diagnostic Steps
Step 1: Installation Check
Check if ultracite is installed:
- Read
package.json - Look for
ultracitein dependencies/devDependencies - Verify
@biomejs/biomeversion (if using Biome provider)
Expected output:
✅ Ultracite installed: v7.2.0
✅ Provider: Biome v1.9.4Step 2: Configuration Validation
Read and parse biome.jsonc:
- Check JSON/JSONC syntax
- Validate preset paths
- Detect v6 vs v7 paths
Common issues detected:
- v6 preset paths:
ultracite/core→ Should beultracite/biome/core - Missing presets: Path references non-existent preset file
- Syntax errors: Invalid JSON/JSONC
Expected output:
✅ Configuration: biome.jsonc valid
⚠️ Preset paths: Using v6 paths (upgrade to v7)
→ Run /ultracite:migrate to fixStep 3: Conflict Detection
Search for conflicting configuration files:
.eslintrc*(any extension).prettierrc*(any extension).stylelintrc*(any extension)eslint.config.js(flat config)
If found, warn about potential conflicts:
⚠️ Conflicting tools detected:
- .eslintrc.js found
- .prettierrc found
→ Consider removing or running /ultracite:migrateStep 4: Environment Check
Check Node.js version:
node --versionRequired: Node.js >= 18.x
Check for Git hooks:
- Look for
.husky/directory - Check
lefthook.yml - Search
package.jsonforlint-staged
Expected output:
✅ Node.js: v20.10.0
⚠️ Git hooks: Not configured
→ See references/git-hooks-setup.mdStep 5: Performance Analysis
Estimate project size:
- Count files matching patterns:
**/*.{js,jsx,ts,tsx,vue,svelte} - Exclude node_modules, dist, build
Recommend provider based on size:
- < 500 files: Biome (fastest)
- 500-2000 files: Biome or Oxlint
- > 2000 files: Oxlint (parallel processing)
- TypeScript heavy: Oxlint (type-aware linting)
Expected output:
✅ Project size: ~350 files
✅ Provider: Biome (optimal for your project size)Output Format
The doctor command provides a comprehensive report:
Ultracite Doctor Report
=======================
✅ INSTALLATION
- Ultracite: v7.2.0
- Provider: Biome v1.9.4
- Node.js: v20.10.0
✅ CONFIGURATION
- Config file: biome.jsonc
- Syntax: Valid
⚠️ Preset paths: Using v6 paths (upgrade recommended)
Old: "ultracite/core"
New: "ultracite/biome/core"
→ Run /ultracite:migrate to upgrade
⚠️ CONFLICTS
- Found .eslintrc.js
- Found .prettierrc
→ Consider removing or migrating with /ultracite:migrate
✅ ENVIRONMENT
- Node.js: v20.10.0 (supported)
⚠️ Git hooks: Not configured
→ See references/git-hooks-setup.md for setup
✅ PERFORMANCE
- Project size: ~350 files
- Provider: Biome (optimal)
- Estimated lint time: < 1s
RECOMMENDATIONS
===============
1. Run /ultracite:migrate to upgrade preset paths to v7
2. Remove conflicting .eslintrc.js and .prettierrc files
3. Set up Git hooks for automatic linting
4. Configure editor integration (see references/ai-editor-integration.md)
Overall Status: ⚠️ GOOD (with minor issues)Error Handling
Ultracite Not Installed
❌ Ultracite not found in package.json
To install:
npm install -D ultracite @biomejs/biome
Or use a different provider:
npm install -D ultracite eslint
npm install -D ultracite oxlintNo Configuration File
❌ No biome.jsonc found
Run to create:
npx ultracite init
Or copy from examples:
cp node_modules/ultracite/presets/biome/react.jsonc biome.jsoncInvalid Configuration
❌ Configuration syntax error in biome.jsonc:12
10: "linter": {
11: "enabled": true,
> 12: "rules": {
^
Error: Unexpected token
Fix: Check JSON/JSONC syntaxWhen to Run
Run /ultracite:doctor when:
- ✅ Setting up Ultracite for the first time
- ✅ After migrating from ESLint/Prettier
- ✅ Before deploying to production
- ✅ When experiencing linting issues
- ✅ After upgrading Ultracite versions
- ✅ When configuration changes don't seem to apply
- ✅ To verify Git hooks integration
Related Commands
/ultracite:migrate- Migrate from ESLint/Prettier or upgrade v6→v7- Load
references/troubleshooting.md- For specific error solutions - Load
references/configuration-guide.md- For detailed configuration options
Implementation Notes
This command uses:
- Read tool to read package.json, biome.jsonc
- Glob tool to find configuration files
- Grep tool to search for preset paths
- Bash tool to check Node.js version
No files are modified - this is a read-only diagnostic command.
Ultracite Migration Command
Interactive migration wizard for: 1. ESLint + Prettier → Ultracite (with rule mapping) 2. Ultracite v6 → v7 (preset path migration)
What This Command Does
ESLint/Prettier Migration
Automates the complex process of migrating from ESLint and Prettier to Ultracite:
1. Scan existing configurations
- Detect
.eslintrc*,.prettierrc*,.stylelintrc* - Read and parse rules
- Identify plugins and extends
2. Analyze compatibility
- Map ESLint rules to Biome equivalents
- Identify rules with no equivalent
- Suggest workarounds for gaps
3. Generate biome.jsonc
- Create equivalent configuration
- Add comments explaining rule mapping
- Include unmapped rules as comments
4. Backup old configs
- Move to
.backup/directory - Preserve for rollback if needed
5. Validate new config
- Test syntax
- Run
ultracite checkon sample files - Report any errors
v6→v7 Migration
Upgrades Ultracite preset paths from v6 to v7 format:
1. Scan biome.jsonc for old paths
- Detect "ultracite/core" pattern
- Detect "ultracite/react", "ultracite/nextjs", etc.
2. Update preset paths
- Replace with "ultracite/biome/core"
- Replace with "ultracite/biome/react", etc.
3. Validate new paths
- Ensure presets exist
- Test configuration loads
4. Report changes made
How to Use
Interactive Mode (Recommended)
Simply run /ultracite:migrate and answer the prompts:
/ultracite:migrateThe command will: 1. Detect existing configurations 2. Ask which migration to perform 3. Guide you through the process 4. Provide a summary report
With Argument (Skip Detection)
Specify the migration type directly:
/ultracite:migrate eslint
/ultracite:migrate prettier
/ultracite:migrate v6
/ultracite:migrate v7Migration Workflows
Workflow 1: ESLint Migration
Step 1: Detect ESLint Configuration
Search for ESLint config files:
.eslintrc.js.eslintrc.json.eslintrc.ymleslint.config.js(flat config)package.json(eslintConfig field)
Read and parse the configuration.
Step 2: Map Rules to Biome
Common ESLint rule mappings:
| ESLint Rule | Biome Equivalent | Status |
|---|---|---|
no-unused-vars | correctness/noUnusedVariables | ✅ Mapped |
no-console | suspicious/noConsoleLog | ✅ Mapped |
eqeqeq | suspicious/noDoubleEquals | ✅ Mapped |
prefer-const | style/useConst | ✅ Mapped |
arrow-body-style | style/useArrowFunction | ✅ Mapped |
@typescript-eslint/no-floating-promises | Use Oxlint provider | ⚠️ No equivalent |
eslint-plugin-security/* | Manual review | ⚠️ No equivalent |
Load full mapping from references/migration-guides.md.
Step 3: Generate biome.jsonc
Create configuration with:
- Mapped rules enabled
- Comments for unmapped rules
- Framework-specific presets
- Formatter settings (if Prettier detected)
Example generated config:
{
"$schema": "https://biomejs.dev/schemas/2.3.8/schema.json",
"extends": [
"ultracite/biome/core",
"ultracite/biome/react" // Detected from eslint-plugin-react
],
"linter": {
"rules": {
"correctness": {
"noUnusedVariables": "error" // Mapped from no-unused-vars
},
"suspicious": {
"noConsoleLog": "warn", // Mapped from no-console
"noDoubleEquals": "error" // Mapped from eqeqeq
}
// @typescript-eslint/no-floating-promises: No Biome equivalent
// Consider using Oxlint provider for type-aware linting
}
},
"formatter": {
"enabled": true,
"indentStyle": "space", // From Prettier config
"lineWidth": 80 // From Prettier printWidth
}
}Step 4: Backup Old Configs
Move old files to .backup/:
mkdir -p .backup
mv .eslintrc.js .backup/
mv .prettierrc .backup/Step 5: Validate
Run Ultracite check:
npx ultracite check .Report any errors found.
Workflow 2: Prettier Migration
Step 1: Detect Prettier Configuration
Search for Prettier config files:
.prettierrc.prettierrc.json.prettierrc.ymlprettier.config.jspackage.json(prettier field)
Read and parse the configuration.
Step 2: Map to Biome Formatter
Common Prettier option mappings:
| Prettier Option | Biome Equivalent | Notes |
|---|---|---|
printWidth | formatter.lineWidth | ✅ Direct mapping |
tabWidth | formatter.indentWidth | ✅ Direct mapping |
useTabs | formatter.indentStyle: "tab" | ✅ Direct mapping |
semi | javascript.formatter.semicolons | ✅ Direct mapping |
singleQuote | javascript.formatter.quoteStyle | ✅ Direct mapping |
trailingComma | javascript.formatter.trailingCommas | ✅ Direct mapping |
arrowParens | javascript.formatter.arrowParentheses | ✅ Direct mapping |
Load full mapping from references/migration-guides.md.
Step 3: Generate Formatter Config
Add to biome.jsonc:
{
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 80
},
"javascript": {
"formatter": {
"semicolons": "asNeeded",
"quoteStyle": "single",
"trailingCommas": "es5",
"arrowParentheses": "asNeeded"
}
}
}Step 4: Backup and Validate
Same as ESLint migration workflow.
Workflow 3: v6→v7 Migration
Step 1: Detect v6 Preset Paths
Read biome.jsonc and search for old preset paths:
"ultracite/core"→"ultracite/biome/core""ultracite/react"→"ultracite/biome/react""ultracite/nextjs"→"ultracite/biome/nextjs""ultracite/vue"→"ultracite/biome/vue""ultracite/svelte"→"ultracite/biome/svelte"
Step 2: Update Paths
Use Edit tool to replace old paths:
Before:
{
"extends": [
"ultracite/core",
"ultracite/react"
]
}After:
{
"extends": [
"ultracite/biome/core",
"ultracite/biome/react"
]
}Step 3: Validate
Check that presets exist:
node -e "require('ultracite/biome/core')"Step 4: Report
v6→v7 Migration Complete
✅ Updated preset paths:
- ultracite/core → ultracite/biome/core
- ultracite/react → ultracite/biome/react
✅ Validated: All presets exist
Next steps:
Run: npx ultracite check .Interactive Prompts
Prompt 1: Migration Type Selection
Which migration do you want to perform?
1. ESLint → Ultracite
2. Prettier → Ultracite
3. ESLint + Prettier → Ultracite
4. Ultracite v6 → v7 (preset paths)
5. Cancel
Choose [1-5]:Prompt 2: Backup Confirmation
Found existing .eslintrc.js with 45 rules.
Backup old configuration files? [y/n]
(Recommended: Creates .backup/ directory)Prompt 3: Validation Confirmation
Generated biome.jsonc successfully.
Test new configuration before committing? [y/n]
(Will run: npx ultracite check .)Prompt 4: Cleanup Confirmation
Migration complete!
Remove old package dependencies? [y/n]
Will run:
npm uninstall eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
npm uninstall prettier eslint-config-prettier
(You can do this manually later)Output Reports
ESLint Migration Report
ESLint → Ultracite Migration Report
===================================
ANALYSIS
--------
✅ Found .eslintrc.js
- 45 rules configured
- Plugins: @typescript-eslint, react, jsx-a11y
- Extends: eslint:recommended, plugin:react/recommended
RULE MAPPING
------------
✅ Mapped: 40 rules (89%)
⚠️ No equivalent: 5 rules (11%)
Unmapped Rules:
1. @typescript-eslint/no-floating-promises
→ Use Oxlint provider (supports type-aware linting)
→ See references/provider-oxlint.md
2. eslint-plugin-security/detect-object-injection
→ Manual code review recommended
→ No automatic detection in Biome
3. eslint-plugin-security/detect-non-literal-require
→ Manual code review recommended
4. import/no-cycle
→ Manual dependency analysis needed
5. react/no-unstable-nested-components
→ Manual code review recommended
GENERATED CONFIGURATION
-----------------------
✅ Created biome.jsonc
- Framework preset: React
- Provider: Biome
- Rules: 40 mapped + comments for 5 unmapped
- Formatter: Enabled (Prettier settings preserved)
BACKUP
------
✅ Backed up to .backup/:
- .eslintrc.js
- .prettierrc
VALIDATION
----------
✅ Configuration syntax: Valid
✅ Test run: npx ultracite check .
- 0 errors
- 3 warnings (fixable)
NEXT STEPS
----------
1. Review generated biome.jsonc
2. Address unmapped rules (see comments in config)
3. Run: npx ultracite check --write .
4. Remove old packages:
npm uninstall eslint prettier
5. Update scripts in package.json:
"lint": "ultracite check ."
"format": "ultracite check --write ."
Migration Status: ✅ SUCCESS (with 5 unmapped rules to review)v6→v7 Migration Report
Ultracite v6→v7 Migration Report
================================
DETECTED
--------
✅ Found biome.jsonc with v6 preset paths
CHANGES
-------
✅ Updated preset paths:
- "ultracite/core" → "ultracite/biome/core"
- "ultracite/react" → "ultracite/biome/react"
VALIDATION
----------
✅ All presets exist
✅ Configuration syntax valid
✅ Test run: npx ultracite check .
- 0 errors
NEXT STEPS
----------
1. Commit changes to biome.jsonc
2. Run: npx ultracite check .
Migration Status: ✅ SUCCESSError Handling
No Configuration Found
❌ No ESLint or Prettier configuration found
Looking for:
- .eslintrc.js, .eslintrc.json, .eslintrc.yml
- .prettierrc, .prettierrc.json, prettier.config.js
- package.json with eslintConfig or prettier fields
To create new Ultracite config:
Run: npx ultracite initParsing Error
❌ Failed to parse .eslintrc.js
Error: Unexpected token at line 12
10: module.exports = {
11: extends: ['eslint:recommended'],
> 12: rules: {
^
Error: Invalid JavaScript
Fix: Verify .eslintrc.js syntaxValidation Failure
❌ Generated configuration failed validation
Error: npx ultracite check . exited with code 1
12 errors found
- src/App.tsx:15: Unexpected console statement
- src/utils/api.ts:42: Missing return type
Fix: Review errors and adjust biome.jsonc rulesWhen to Use
Use /ultracite:migrate when:
- ✅ Migrating from ESLint to Ultracite
- ✅ Migrating from Prettier to Ultracite
- ✅ Upgrading from Ultracite v6 to v7
- ✅ Consolidating ESLint + Prettier into Ultracite
- ✅ Switching providers (ESLint → Biome)
- ✅ Adopting Ultracite in existing projects
Related Resources
- Load
references/migration-guides.md- Detailed ESLint/Prettier mappings - Load
references/v6-migration.md- v6→v7 migration guide - Load
references/v7-migration.md- v7 features and changes - Load
references/provider-biome.md- Biome provider details - Load
references/troubleshooting.md- Common migration issues
Related Commands
/ultracite:doctor- Validate setup after migration- Agent:
migration-assistant- Get detailed migration analysis
Implementation Notes
This command uses:
- Read tool to read existing configs
- Glob tool to find config files
- Write tool to create biome.jsonc
- Edit tool to update preset paths
- Bash tool to run validation
- AskUserQuestion tool for interactive prompts
Files may be modified - always creates backups before making changes.
Ultracite AI Editor Integration
Complete guide for integrating Ultracite with AI coding assistants (Cursor, Claude Code, GitHub Copilot, etc.) using AI editor rules.
Last Updated: 2025-11-22
---
Overview
Ultracite generates AI editor rules that teach AI assistants about your project's linting/formatting standards, reducing hallucinations and improving code quality.
Benefits:
- AI generates lint-compliant code from the start
- Fewer back-and-forth corrections
- Consistent code style across AI and human contributions
- Automatic synchronization with Ultracite config
Supported Editors:
- Cursor
- Claude Code (Windsurf)
- GitHub Copilot
- Continue.dev
- Codeium
- Zed
- VS Code (with Continue extension)
---
How AI Editor Rules Work
1. Ultracite analyzes your config (biome.json) 2. Generates editor-specific rules (.cursorrules, .windsurfrules, etc.) 3. AI editor loads rules into context window 4. AI generates compliant code automatically
Example flow:
biome.json → ultracite generate-ai-rules → .cursorrules → Cursor → Lint-free code---
Supported Editors
Cursor
File: .cursorrules
Setup:
# Generate rules
bunx ultracite generate-ai-rules
# Rules appear in ~/.cursorrules or project root
cat .cursorrulesCursor automatically loads .cursorrules on project open.
Verification: 1. Open Cursor in your project 2. Ask Cursor to generate a React component 3. Check that code follows your Ultracite config (e.g., no console.log if disabled)
---
Claude Code (Windsurf)
File: .windsurfrules
Setup:
# Generate rules
bunx ultracite generate-ai-rules
# Rules appear in project root
cat .windsurfrulesWindsurf automatically loads .windsurfrules on project open.
Verification: 1. Open Windsurf in your project 2. Ask Claude to write a function 3. Verify code matches your linting rules
---
GitHub Copilot
File: .github/copilot-instructions.md
Setup:
# Generate rules
bunx ultracite generate-ai-rules --editor=copilot
# Rules appear in .github/
cat .github/copilot-instructions.mdGitHub Copilot reads from .github/copilot-instructions.md automatically.
Verification: 1. Open project in VS Code with Copilot 2. Start typing a function 3. Check that Copilot suggestions follow your rules
---
Continue.dev
File: .continuerules
Setup:
# Generate rules
bunx ultracite generate-ai-rules --editor=continue
# Rules appear in project root
cat .continuerulesContinue extension loads .continuerules automatically.
Verification: 1. Open Continue panel in VS Code 2. Ask Continue to generate code 3. Verify compliance with linting rules
---
Codeium
File: .codeiumrules
Setup:
# Generate rules
bunx ultracite generate-ai-rules --editor=codeium
# Rules appear in project root
cat .codeiumrulesCodeium reads .codeiumrules automatically.
---
Zed
File: .zedrules
Setup:
# Generate rules
bunx ultracite generate-ai-rules --editor=zed
# Rules appear in project root
cat .zedrulesZed assistant loads .zedrules automatically.
---
Generated Rules Format
Example .cursorrules
# Project Linting Rules (Powered by Ultracite)
This project uses Ultracite (built on Biome) for linting and formatting.
## Active Presets
- ultracite/core
- ultracite/react
## Key Rules
### Correctness
- ✅ No unused variables
- ✅ No unreachable code
- ✅ Use === instead of ==
- ✅ No constant conditions
### React-Specific
- ✅ Exhaustive hook dependencies
- ✅ No array index as key
- ✅ Explicit button types
- ✅ No children prop
### Style
- ✅ Prefer const over let when possible
- ✅ Use template literals over concatenation
- ✅ Single variable declarator per statement
### Disabled Rules
- ❌ console.log allowed (noConsoleLog: off)
## When generating code:
1. Follow these rules strictly
2. Use const by default, let only when reassignment needed
3. Use === for all equality checks
4. Include all dependencies in React hooks
5. Avoid array indices as React keys
6. Use template literals for string interpolation
## Formatting
- Indent: 2 spaces
- Line width: 80 characters
- Semicolons: As needed
- Quotes: Single quotes
- Trailing commas: ES5 style---
Customization
Global Rules (All Editors)
Generate rules for all supported editors at once:
bunx ultracite generate-ai-rules --allThis creates:
.cursorrules.windsurfrules.github/copilot-instructions.md.continuerules.codeiumrules.zedrules
---
Custom Rule Template
Create a custom template for generated rules:
.ultracite/ai-rules-template.md:
# {{PROJECT_NAME}} Linting Rules
Generated from biome.json on {{DATE}}.
## Presets
{{PRESETS}}
## Enabled Rules
{{ENABLED_RULES}}
## Disabled Rules
{{DISABLED_RULES}}
## Custom Instructions
- Always use async/await over .then()
- Prefer named exports over default exports
- Add JSDoc comments to all exported functionsGenerate with custom template:
bunx ultracite generate-ai-rules --template=.ultracite/ai-rules-template.md---
Per-Editor Customization
Cursor-specific additions:
.cursorrules:
# ... (auto-generated rules)
## Cursor-Specific
- Use Cmd+K to generate code snippets
- Prefer inline completions for simple expressions
- Use chat for complex refactoringsCopilot-specific additions:
.github/copilot-instructions.md:
# ... (auto-generated rules)
## GitHub Copilot Tips
- Accept suggestions with Tab
- Use Alt+] for next suggestion
- Use Copilot Chat for explanations---
Automatic Updates
Git Hook Integration
Automatically regenerate rules when biome.json changes:
Husky (.husky/post-merge):
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
# Check if biome.json changed
if git diff HEAD@{1} HEAD --name-only | grep -q "biome.json"; then
bunx ultracite generate-ai-rules
git add .cursorrules .windsurfrules
fiLefthook (lefthook.yml):
post-merge:
commands:
update-ai-rules:
files: biome.json
run: bunx ultracite generate-ai-rules && git add .cursorrules .windsurfrules---
CI Integration
Ensure rules are up-to-date in CI:
GitHub Actions:
name: Check AI Rules
on: [pull_request]
jobs:
check-rules:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v1
- name: Install Ultracite
run: bun add -D ultracite
- name: Generate AI rules
run: bunx ultracite generate-ai-rules
- name: Check if rules are up-to-date
run: |
git diff --exit-code .cursorrules .windsurfrules || \
(echo "AI rules are out of date. Run 'ultracite generate-ai-rules'" && exit 1)---
Best Practices
1. Commit AI Rules to Git
git add .cursorrules .windsurfrules .github/copilot-instructions.md
git commit -m "Add AI editor rules for Ultracite"Why: Ensures all team members have consistent AI behavior.
---
2. Regenerate After Config Changes
# After editing biome.json
bunx ultracite generate-ai-rulesWhy: Keeps AI rules synchronized with linting config.
---
3. Test AI Compliance
Cursor: 1. Ask: "Generate a React component with a form" 2. Verify: No console.log, correct hook dependencies, proper key usage
GitHub Copilot: 1. Start typing: function fetchUser( 2. Verify: Copilot suggests async keyword, uses ===, avoids deprecated APIs
---
4. Use Editor-Specific Rules
Don't rely on auto-generated rules alone. Add project-specific conventions:
# .cursorrules
## Project Conventions
- Use Tailwind classes, avoid inline styles
- Prefer server components in Next.js App Router
- Use Zod for all form validation
- Fetch data with React Query, not useEffect---
5. Document Rule Rationale
Explain why rules exist:
## Disabled Rules
- `noConsoleLog: off` - Allowed in development for debugging
- `noUnusedVariables: warn` - Warning only to support WIP code---
Troubleshooting
Rules Not Loading
Cursor:
- Reload: Cmd+Shift+P → "Reload Window"
- Check:
.cursorrulesin project root - Verify: Settings → Cursor → "Load project rules"
GitHub Copilot:
- Restart: VS Code → Developer → Reload Window
- Check:
.github/copilot-instructions.mdexists - Verify: Copilot extension enabled
Continue.dev:
- Reload: Continue panel → Refresh
- Check:
.continuerulesin project root
---
AI Ignoring Rules
Increase rule prominence:
# .cursorrules
## ⚠️ CRITICAL RULES (NEVER IGNORE)
1. **NO console.log in production code**
2. **ALWAYS use === for equality**
3. **REQUIRED: Exhaustive React hook dependencies**Be specific:
# ❌ Vague
- Follow best practices
# ✅ Specific
- Use React.memo for components that render frequently
- Debounce search inputs with 300ms delay
- Always validate user input with Zod schemas---
Rules Out of Sync
Symptom: AI generates code that fails linting
Fix: Regenerate rules
bunx ultracite generate-ai-rulesVerify:
git diff .cursorrules # Check what changed---
Advanced Patterns
Conditional Rules by File Type
# .cursorrules
## TypeScript Files
- Always use explicit return types
- Prefer interfaces over types for objects
- Use const assertions for literal types
## React Components
- Use function declarations, not arrow functions
- Separate container and presentational components
- Always use React.FC for component types
## Test Files
- Use describe/it blocks (not test/it)
- Mock external dependencies
- Aim for 80%+ coverage---
Framework-Specific Rules
Next.js:
## Next.js Conventions
- Use `<Link>` from next/link, never `<a>`
- Use `<Image>` from next/image, never `<img>`
- Server Components by default, 'use client' only when needed
- Fetch data in Server Components, not useEffectNuxt 3:
## Nuxt 3 Conventions
- Use `<NuxtLink>` instead of `<a>`
- Use `<NuxtImg>` for optimized images
- Prefer Composition API over Options API
- Use auto-imports, avoid manual imports---
See also:
configuration-guide.mdfor Ultracite setupgit-hooks-setup.mdfor hook integrationtroubleshooting.mdfor common issues
AI Hooks Reference
Feature: AI Hooks (Auto-format after AI edits) Version: v7.0+ Purpose: Automatically run ultracite fix after AI code edits
Overview
AI Hooks automatically format and lint code after AI assistants (Cursor, Claude Code, etc.) make edits. This ensures AI-generated code follows project standards without manual intervention.
AI Hooks vs AI Rules
AI Rules (existing feature):
- Guides AI generation toward better code upfront
- Provides linting guidelines to AI during generation
- Prevents errors before they occur
AI Hooks (new in v7):
- Runs
ultracite fixafter AI edits - Automatically formats AI-generated code
- Fixes linting issues automatically
- Applies import organization, spacing, etc.
Recommended workflow (combine both features): 1. AI Rules → Guides AI generation toward clean code 2. AI Hooks → Automatically fixes formatting issues
Installation
Cursor
# Install AI hooks for Cursor
npx ultracite ai-hooks install --editor cursor
# Installs to: .cursor/hooks/post-edit.shWhat it does: 1. Creates .cursor/hooks/ directory 2. Adds post-edit.sh script that runs npx ultracite fix on edited files 3. Configures Cursor to execute hook after AI edits
Claude Code
# Install AI hooks for Claude Code
npx ultracite ai-hooks install --editor claude-code
# Installs to: .claude/hooks/post-edit.shConfiguration (.claude/settings.json):
{
"hooks": {
"postEdit": ".claude/hooks/post-edit.sh"
}
}Windsurf
# Install AI hooks for Windsurf
npx ultracite ai-hooks install --editor windsurf
# Installs to: .windsurf/hooks/after-edit.shCline (VS Code Extension)
# Install AI hooks for Cline
npx ultracite ai-hooks install --editor cline
# Installs to: .vscode/cline-hooks/post-edit.shGitHub Copilot (Experimental)
Note: GitHub Copilot doesn't natively support hooks. Use editor's format-on-save instead.
Alternative (VS Code):
// .vscode/settings.json
{
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll": true
}
}Hook Script Details
Post-Edit Hook Script
Location: .cursor/hooks/post-edit.sh (Cursor example)
#!/bin/bash
# Ultracite AI Hook - Auto-format after AI edits
# Get list of edited files from AI
EDITED_FILES=$1
if [ -z "$EDITED_FILES" ]; then
echo "No files to format"
exit 0
fi
# Run Ultracite fix on edited files
npx ultracite fix $EDITED_FILES --quiet
# Exit code 0 = success (allow AI edit to complete)
exit 0Customization
Edit hook script to customize behavior:
#!/bin/bash
# Custom Ultracite AI Hook
EDITED_FILES=$1
# Only format TypeScript files
TS_FILES=$(echo "$EDITED_FILES" | grep -E '\.(ts|tsx)$')
if [ -n "$TS_FILES" ]; then
# Run fix with custom flags
npx ultracite fix $TS_FILES \
--no-errors-on-unmatched \
--skip-gitignored \
--quiet
fi
exit 0Configuration Options
Hook Behavior
Configure hook execution in .ultracite/hooks.json:
{
"aiHooks": {
"enabled": true,
"runOn": "post-edit",
"filePatterns": ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx"],
"excludePatterns": ["**/*.test.ts", "**/dist/**"],
"timeoutMs": 5000,
"showNotifications": true
}
}Options:
enabled: Enable/disable hooksrunOn: When to run (post-edit,pre-commit)filePatterns: Which files to formatexcludePatterns: Files to skiptimeoutMs: Max hook execution timeshowNotifications: Show toast notifications
Per-Editor Configuration
Cursor (.cursor/hooks/config.json):
{
"hooks": {
"postEdit": {
"enabled": true,
"script": "./post-edit.sh",
"timeout": 5000
}
}
}Claude Code (.claude/settings.json):
{
"hooks": {
"postEdit": ".claude/hooks/post-edit.sh",
"postEditTimeout": 5000
}
}Usage
Automatic Execution
Once installed, hooks run automatically:
1. AI makes edit → File is modified 2. Hook triggers → post-edit.sh runs 3. Ultracite fixes → Auto-format, organize imports, fix lint issues 4. User sees result → Formatted code
Manual Testing
Test hook manually:
# Simulate AI edit on file
.cursor/hooks/post-edit.sh src/index.ts
# Test multiple files
.cursor/hooks/post-edit.sh "src/**/*.ts"Disable Temporarily
# Disable hooks for single AI session
ULTRACITE_HOOKS_DISABLED=true cursor
# Or edit config
# .ultracite/hooks.json
{
"aiHooks": {
"enabled": false // Disable
}
}Workflow Examples
Example 1: React Component Generation
Before AI Hooks: 1. Ask AI: "Create a React button component" 2. AI generates code 3. Manual step: Run npx ultracite fix src/Button.tsx 4. Code is formatted
After AI Hooks: 1. Ask AI: "Create a React button component" 2. AI generates code 3. Hook auto-runs: npx ultracite fix src/Button.tsx 4. Code is formatted automatically ✨
Example 2: Large Refactoring
Before AI Hooks: 1. Ask AI: "Refactor these 10 files to use hooks" 2. AI edits 10 files 3. Manual step: Run npx ultracite fix src/**/*.tsx 4. All files formatted
After AI Hooks: 1. Ask AI: "Refactor these 10 files to use hooks" 2. AI edits 10 files 3. Hook auto-runs: Formats each file as edited 4. All files automatically formatted ✨
Performance Considerations
Hook Execution Time
Typical hook execution times:
- Single file: 50-200ms
- 5 files: 200-500ms
- 10+ files: 500ms-2s
Optimization Tips
1. Only format changed files:
# In hook script
CHANGED_FILES=$(echo "$EDITED_FILES" | grep -E '\.(ts|tsx)$')
npx ultracite fix $CHANGED_FILES # Not all files2. Skip tests and generated files:
{
"excludePatterns": [
"**/*.test.ts",
"**/*.spec.ts",
"**/*.generated.ts",
"**/dist/**",
"**/node_modules/**"
]
}3. Use cache:
# Ultracite automatically caches results
npx ultracite fix $FILES --use-cache4. Set timeout:
{
"timeoutMs": 3000 // Kill if takes >3s
}Troubleshooting
Hook Not Running
Problem: AI edits don't trigger hook
Check: 1. Hook script exists: ls .cursor/hooks/post-edit.sh 2. Script is executable: chmod +x .cursor/hooks/post-edit.sh 3. Hooks enabled: Check .ultracite/hooks.json
Solution:
# Reinstall hooks
npx ultracite ai-hooks install --editor cursor --force
# Make executable
chmod +x .cursor/hooks/post-edit.sh
# Test manually
.cursor/hooks/post-edit.sh src/test.tsHook Fails Silently
Problem: Hook runs but doesn't format
Debug:
# Run hook with debug output
DEBUG=ultracite:hooks .cursor/hooks/post-edit.sh src/test.ts
# Check Ultracite can run
npx ultracite fix src/test.ts --verboseCommon issues:
- Ultracite not installed:
bun add -D ultracite - Invalid configuration:
npx ultracite doctor - File not matched by patterns: Check
filePatterns
Hook Timeout
Problem: Hook takes too long, gets killed
Solution: Increase timeout
{
"aiHooks": {
"timeoutMs": 10000 // 10 seconds
}
}Or optimize hook:
# Skip slow operations
npx ultracite fix $FILES \
--skip-typecheck \
--no-verify \
--quietConflicting Format Changes
Problem: Hook reverts some of AI's formatting
Cause: AI uses different format style than Ultracite
Solution: Align AI rules with Ultracite config
1. Update AI Rules (.cursor/rules/ultracite.mdc):
- Use 2 spaces for indentation (matches Ultracite)
- Use single quotes for strings (matches Ultracite)
- No semicolons (matches Ultracite Biome config)2. Update Ultracite config to match AI preferences:
{
"formatter": {
"indentWidth": 2,
"quoteStyle": "single",
"semicolons": false
}
}Advanced Usage
Conditional Formatting
Format only if file changed significantly:
#!/bin/bash
EDITED_FILES=$1
for file in $EDITED_FILES; do
# Check if file changed >10 lines
CHANGED_LINES=$(git diff --numstat "$file" | awk '{print $1 + $2}')
if [ "$CHANGED_LINES" -gt 10 ]; then
npx ultracite fix "$file" --quiet
fi
donePre-Commit Integration
Combine AI hooks with Git hooks:
# .husky/pre-commit
#!/bin/bash
# Format staged files (from AI edits or manual)
npx lint-staged
# Or use Ultracite directly
npx ultracite fix --staged --quietMulti-Provider Support
Use different providers based on file type:
#!/bin/bash
EDITED_FILES=$1
for file in $EDITED_FILES; do
case "$file" in
*.css|*.scss)
# Use ESLint provider for CSS
npx ultracite fix "$file" --provider eslint
;;
*.ts|*.tsx)
# Use Oxlint for TypeScript
npx ultracite fix "$file" --provider oxlint
;;
*)
# Default to Biome
npx ultracite fix "$file"
;;
esac
doneBest Practices
1. Combine with AI Rules
- Use AI Rules to guide generation
- Use AI Hooks to polish result
2. Set Reasonable Timeouts
- Keep hooks fast (<2s)
- Avoid blocking AI workflow
3. Exclude Generated Files
- Don't format lock files, dist, node_modules
- Focus on source files only
4. Use Notifications
- Enable toast notifications to see hook status
- Helps debug when hooks fail
5. Test Hooks Locally
- Run hook manually before committing
- Verify it works on sample files
Resources
- AI Hooks Guide: https://www.ultracite.ai/guides/ai-hooks
- Cursor Hooks Docs: https://cursor.sh/docs/hooks
- Claude Code Hooks: https://docs.anthropic.com/claude/docs/hooks
- Hook Examples: https://github.com/ultracite/ultracite/tree/main/examples/hooks
- Troubleshooting: https://www.ultracite.ai/troubleshooting/ai-hooks
{
"$schema": "https://biomejs.dev/schemas/2.3.8/schema.json",
// Monorepo root configuration
// Single config applies to all packages
"extends": ["ultracite/biome/core", "ultracite/biome/react"], // v7 paths
// Optional: Customize formatter
"formatter": {
"enabled": true,
"indentWidth": 2,
"lineWidth": 100
},
// Optional: Customize linter
"linter": {
"enabled": true
},
// Exclude common monorepo build outputs
"files": {
"ignore": [
// Package managers
"node_modules",
".pnpm-store",
// Build outputs
"dist",
"build",
".next",
"out",
".turbo",
".cache",
// Testing
"coverage",
// Generated
"**/*.generated.ts",
"**/__generated__/**"
]
},
// Package-specific overrides
"overrides": [
{
// Legacy package with relaxed rules
"include": ["packages/legacy/**"],
"linter": {
"rules": {
"style": {
"useConst": "warn",
"noVar": "warn"
},
"suspicious": {
"noExplicitAny": "warn"
}
}
}
},
{
// Next.js app
"include": ["apps/web/**"],
"extends": ["ultracite/biome/next"], // v7 path
"linter": {
"rules": {
"performance": {
"noImgElement": "error"
}
}
}
},
{
// Node.js API (no React)
"include": ["apps/api/**"],
"extends": ["ultracite/biome/core"], // v7 path
"javascript": {
"globals": ["process", "Buffer", "__dirname", "__filename"]
}
},
{
// Shared UI components
"include": ["packages/ui/**"],
"extends": ["ultracite/biome/react"], // v7 path
"linter": {
"rules": {
"a11y": {
// Strict accessibility for shared components
"*": "error"
}
}
}
},
{
// Test files
"include": ["**/*.test.ts", "**/*.test.tsx", "**/*.spec.ts"],
"linter": {
"rules": {
"suspicious": {
"noExplicitAny": "off"
},
"style": {
"noNonNullAssertion": "off"
}
}
}
}
]
}
{
"$schema": "https://biomejs.dev/schemas/2.3.8/schema.json",
// Next.js preset includes React preset automatically
"extends": ["ultracite/biome/core", "ultracite/biome/next"], // v7 paths
// Optional: Customize formatter
"formatter": {
"enabled": true,
"indentWidth": 2,
"lineWidth": 100 // Next.js projects often use wider lines
},
// Optional: Customize linter
"linter": {
"enabled": true,
"rules": {
// Next.js specific customizations
"performance": {
// Ensure next/image is used (default: error)
"noImgElement": "error"
}
}
},
// Optional: Exclude Next.js build outputs
"files": {
"ignore": [
".next",
"out",
"dist",
"build",
"coverage",
"node_modules",
"**/*.generated.ts",
".vercel",
".turbo"
]
},
// Optional: Overrides for specific files
"overrides": [
{
// Allow certain patterns in config files
"include": ["next.config.*"],
"linter": {
"rules": {
"correctness": {
"noUnusedVariables": "warn"
}
}
}
},
{
// Relax rules for App Router server components
"include": ["app/**/*page.tsx", "app/**/*layout.tsx"],
"linter": {
"rules": {
"nursery": {
"noUseAwait": "off"
}
}
}
}
]
}
{
"$schema": "https://biomejs.dev/schemas/2.3.8/schema.json",
"extends": ["ultracite/biome/core", "ultracite/biome/react"], // v7 paths
// Optional: Customize formatter
"formatter": {
"enabled": true,
"formatWithErrors": false,
"indentStyle": "space",
"indentWidth": 2,
"lineEnding": "lf",
"lineWidth": 80
},
// Optional: Customize linter
"linter": {
"enabled": true,
"rules": {
// Example: Disable autofocus rule for React
"a11y": {
"noAutofocus": "off"
},
// Example: Allow dangerouslySetInnerHTML with explicit ignore comment
"security": {
"noDangerouslySetInnerHtml": "warn"
}
}
},
// Optional: Exclude files
"files": {
"ignore": [
"dist",
"build",
".next",
"coverage",
"node_modules",
"**/*.generated.ts"
]
},
// Optional: JavaScript/TypeScript specific
"javascript": {
"formatter": {
"quoteStyle": "single",
"trailingCommas": "es5",
"semicolons": "always",
"arrowParentheses": "always",
"bracketSpacing": true
}
},
// Optional: JSON specific
"json": {
"formatter": {
"enabled": true,
"indentWidth": 2
}
}
}
{
"$schema": "https://biomejs.dev/schemas/2.3.8/schema.json",
"extends": ["ultracite/biome/core", "ultracite/biome/svelte"], // v7 paths
// HTML support for .svelte files
"html": {
"experimentalFullSupportEnabled": true,
"formatter": {
"enabled": true,
"indentScriptAndStyle": true,
"indentWidth": 2
}
},
// Optional: Customize formatter
"formatter": {
"enabled": true,
"indentWidth": 2,
"lineWidth": 80
},
// Optional: Customize linter
"linter": {
"enabled": true,
"rules": {
// Svelte-specific customizations
"suspicious": {
// Prevent React-specific props in Svelte (default: error)
"noReactSpecificProps": "error"
}
}
},
// Optional: Exclude files
"files": {
"ignore": [
".svelte-kit",
"build",
"dist",
"coverage",
"node_modules",
"**/*.generated.ts"
]
},
// Overrides for .svelte files (already handled by preset)
"overrides": [
{
"include": ["*.svelte"],
"linter": {
"rules": {
// Additional .svelte specific customizations
// Note: Preset already relaxes rules for SFC structure
}
}
}
]
}
{
"$schema": "https://biomejs.dev/schemas/2.3.8/schema.json",
"extends": ["ultracite/biome/core", "ultracite/biome/vue"], // v7 paths
// HTML support for .vue files
"html": {
"experimentalFullSupportEnabled": true,
"formatter": {
"enabled": true,
"indentScriptAndStyle": true,
"indentWidth": 2,
"lineWidth": 80
}
},
// Optional: Customize formatter
"formatter": {
"enabled": true,
"indentWidth": 2
},
// Optional: Customize linter
"linter": {
"enabled": true,
"rules": {
// Vue-specific rules are already configured
// Add custom overrides here
}
},
// Optional: Exclude files
"files": {
"ignore": [
"dist",
".nuxt",
".output",
"coverage",
"node_modules",
"**/*.generated.ts"
]
},
// Optional: Overrides for .vue files (already handled by preset)
"overrides": [
{
"include": ["*.vue"],
"linter": {
"rules": {
// Additional .vue specific customizations
}
}
}
]
}
Ultracite Configuration Guide
Complete guide for configuring Ultracite with framework presets, customization, and file exclusion patterns.
Last Updated: 2025-11-22
---
Configuration File Structure
Ultracite uses Biome's configuration format (biome.json or biome.jsonc):
{
"$schema": "https://biomejs.dev/schemas/2.3.8/schema.json",
"extends": ["ultracite/core"],
// Optional: Add framework-specific preset
// "extends": ["ultracite/core", "ultracite/react"],
// Optional: Customize rules
"linter": {
"rules": {
"a11y": {
"noAutofocus": "off" // Disable specific rule
}
}
},
// Optional: Exclude files/directories
"files": {
"ignore": [
"dist",
"build",
"coverage",
"**/*.generated.ts"
]
}
}---
Framework Presets
React Preset (ultracite/react)
Extends: ultracite/core + React-specific rules
Includes:
- React Hooks linting (exhaustive deps, rules of hooks)
- JSX accessibility (a11y) checks
- React-specific naming conventions
- Component best practices
Configuration:
{
"$schema": "https://biomejs.dev/schemas/2.3.8/schema.json",
"extends": ["ultracite/core", "ultracite/react"]
}Key Rules:
useExhaustiveDependencies: Ensures all dependencies are listed in hooksnoArrayIndexKey: Prevents using array indices as React keysuseButtonType: Requires explicit button typesnoChildrenProp: Prevents passing children as propsuseJsxKeyInIterable: Requires keys in JSX lists
Best For:
- Create React App projects
- Vite React projects
- Custom React setups
---
Next.js Preset (ultracite/nextjs)
Extends: ultracite/react + Next.js-specific rules
Includes:
- Everything from
ultracite/react - Next.js-specific imports (e.g.,
next/link,next/image) - App Router conventions
- Server Component rules
- Performance optimizations
Configuration:
{
"$schema": "https://biomejs.dev/schemas/2.3.8/schema.json",
"extends": ["ultracite/core", "ultracite/nextjs"]
}Key Rules:
noHtmlLinkForPages: Enforces using Next.js<Link>noImgElement: Enforces using Next.js<Image>noTitleInDocumentHead: Prevents<title>in custom Document- Server/Client Component separation checks
Best For:
- Next.js 14+ projects (App Router)
- Next.js Pages Router projects
- Vercel deployments
---
Vue Preset (ultracite/vue)
Extends: ultracite/core + Vue-specific rules
Includes:
- Vue 3 Composition API linting
- Template syntax validation
- Reactivity system checks
- Component naming conventions
Configuration:
{
"$schema": "https://biomejs.dev/schemas/2.3.8/schema.json",
"extends": ["ultracite/core", "ultracite/vue"]
}Key Rules:
useValidVModelName: Ensures correct v-model namingnoMutatingProps: Prevents prop mutationsrequireEmitsOption: Requires explicit emits declarationnoReactiveReassign: Prevents reassigning reactive variables
Best For:
- Nuxt 3 projects
- Vue 3 + Vite projects
- Quasar Framework
---
Svelte Preset (ultracite/svelte)
Extends: ultracite/core + Svelte-specific rules
Includes:
- Svelte 4/5 syntax validation
- Reactive declarations linting
- Component lifecycle checks
- Store best practices
Configuration:
{
"$schema": "https://biomejs.dev/schemas/2.3.8/schema.json",
"extends": ["ultracite/core", "ultracite/svelte"]
}Key Rules:
noInnerDeclarations: Prevents function declarations in blocksvalidEach: Ensures each blocks have valid syntaxnoUnusedStores: Detects unused store subscriptionspreferReadableExports: Enforces readable exports over defaults
Best For:
- SvelteKit projects
- Svelte 5 (runes support)
- Svelte component libraries
---
Core Preset Features
The ultracite/core preset includes 200+ rules across these categories:
1. Correctness (85 rules)
Catches actual bugs and logic errors:
noUnreachable: Detects unreachable codenoUnsafeFinally: Prevents unsafe control flow in finally blocksnoConstantCondition: Catches always-true/false conditionsuseValidForDirection: Ensures correct for-loop directionnoUnusedVariables: Removes unused variables
2. Suspicious (48 rules)
Flags code that might indicate bugs:
noDoubleEquals: Enforces===over==noAsyncPromiseExecutor: Prevents async Promise executorsnoConsoleLog: Flags console.log statementsnoDebugger: Removes debugger statementsnoShadowRestrictedNames: Prevents shadowing global variables
3. Style (35 rules)
Enforces consistent code style:
useConst: Prefersconstoverletwhen possibleuseTemplate: Prefers template literals over string concatenationuseSingleVarDeclarator: One variable per declarationnoNegationElse: Simplifies negated conditionsnoUnusedTemplateLiteral: Removes unnecessary template literals
4. Complexity (12 rules)
Reduces cognitive complexity:
noExcessiveCognitiveComplexity: Limits function complexitynoForEach: Prefers for-of loops over forEachuseFlatMap: Suggests flatMap over map().flat()noUselessFragments: Removes unnecessary React fragments
5. Performance (8 rules)
Optimizes runtime performance:
noAccumulatingSpread: Prevents O(n²) spread operationsnoDelete: Avoids delete operator (breaks V8 optimizations)useArrayLiterals: Prefers[]overnew Array()
6. Security (6 rules)
Prevents security vulnerabilities:
noDangerouslySetInnerHtml: Flags XSS risksnoGlobalEval: Prevents eval() usagenoGlobalObjectCalls: Prevents calling global objects as functions
7. Accessibility (6 rules)
Ensures inclusive UIs:
useAltText: Requires alt text on imagesuseAnchorContent: Ensures links have accessible contentuseButtonType: Requires explicit button typesuseKeyWithClickEvents: Ensures keyboard accessibility
---
Advanced Customization
Disabling Rules
Single rule:
{
"linter": {
"rules": {
"suspicious": {
"noConsoleLog": "off"
}
}
}
}Entire category:
{
"linter": {
"rules": {
"suspicious": {
"all": false // Disable all suspicious rules
}
}
}
}Re-enable specific rule in disabled category:
{
"linter": {
"rules": {
"suspicious": {
"all": false,
"noConsoleLog": "error" // Re-enable this one
}
}
}
}---
Rule Severity Levels
{
"linter": {
"rules": {
"suspicious": {
"noConsoleLog": "warn", // Warning (doesn't fail CI)
"noDebugger": "error", // Error (fails CI)
"noDoubleEquals": "off" // Disabled
}
}
}
}---
Per-File Configuration
Disable rules for specific files:
{
"overrides": [
{
"include": ["**/*.test.ts", "**/*.test.tsx"],
"linter": {
"rules": {
"suspicious": {
"noConsoleLog": "off"
}
}
}
}
]
}Different rules for different directories:
{
"overrides": [
{
"include": ["src/legacy/**"],
"linter": {
"rules": {
"complexity": {
"all": false // Legacy code exempted from complexity rules
}
}
}
}
]
}---
File Exclusion Patterns
Common Exclusions
{
"files": {
"ignore": [
// Build outputs
"dist",
"build",
".next",
"out",
// Dependencies
"node_modules",
".pnpm-store",
// Test coverage
"coverage",
".nyc_output",
// Generated files
"**/*.generated.ts",
"**/*.d.ts",
// Cache directories
".cache",
".turbo",
// Framework-specific
".nuxt",
".svelte-kit",
"vite.config.ts.timestamp-*"
]
}
}---
Glob Patterns
Wildcards:
*: Matches any file/directory (non-recursive)**: Matches any file/directory (recursive)?: Matches single character
Examples:
{
"files": {
"ignore": [
"*.config.js", // All .config.js files in root
"**/*.config.js", // All .config.js files anywhere
"src/generated/**", // Everything in src/generated/
"**/__tests__/**", // All __tests__ directories
"*.{spec,test}.ts" // All .spec.ts and .test.ts files
]
}
}---
Including Files
By default, Ultracite lints all supported files. Use include to limit scope:
{
"files": {
"include": [
"src/**/*.ts",
"src/**/*.tsx"
]
}
}---
Formatter Configuration
Format Options
{
"formatter": {
"enabled": true,
"formatWithErrors": false,
"indentStyle": "space",
"indentWidth": 2,
"lineEnding": "lf",
"lineWidth": 80
}
}---
Per-Language Formatting
{
"formatter": {
"enabled": true
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"semicolons": "asNeeded",
"trailingCommas": "es5"
}
},
"json": {
"formatter": {
"indentWidth": 2
}
}
}---
Environment-Specific Configuration
Development
{
"$schema": "https://biomejs.dev/schemas/2.3.8/schema.json",
"extends": ["ultracite/core", "ultracite/react"],
"linter": {
"rules": {
"suspicious": {
"noConsoleLog": "off", // Allow console.log in dev
"noDebugger": "off" // Allow debugger in dev
}
}
}
}---
Production/CI
{
"$schema": "https://biomejs.dev/schemas/2.3.8/schema.json",
"extends": ["ultracite/core", "ultracite/react"],
"linter": {
"rules": {
"suspicious": {
"noConsoleLog": "error", // Fail on console.log
"noDebugger": "error" // Fail on debugger
}
}
}
}Tip: Use different config files per environment:
# Development
ultracite check --config-path=biome.dev.json
# CI
ultracite check --config-path=biome.ci.json---
See also:
git-hooks-setup.mdfor pre-commit integrationmonorepo-configuration.mdfor multi-package setupstroubleshooting.mdfor configuration issues
Ultracite Git Hooks Setup
Complete guide for integrating Ultracite with Husky, Lefthook, and lint-staged for automated pre-commit linting.
Last Updated: 2025-11-22
---
Overview
Git hooks automatically run Ultracite before commits, preventing bad code from entering the repository.
Benefits:
- Catch errors before they reach CI
- Enforce code quality standards
- Reduce code review noise
- Faster feedback loop
Supported Hook Managers:
- Husky (npm-based, most popular)
- Lefthook (Go-based, faster)
- lint-staged (runs linters on staged files only)
---
Choosing a Hook Manager
| Feature | Husky | Lefthook | lint-staged |
|---|---|---|---|
| Language | Node.js | Go | Node.js |
| Speed | Medium | Fast | Medium |
| Configuration | Shell scripts | YAML | JavaScript |
| Popularity | 40k+ stars | 5k+ stars | 13k+ stars |
| Best For | General use | Monorepos | Simple linting |
| Windows Support | ✅ | ✅ | ✅ |
Recommendation:
- First-time setup: Husky (most documentation)
- Performance-critical: Lefthook (2-3x faster)
- Simple projects: lint-staged only
---
Husky Integration
Installation
# Install Husky
bun add -D husky
# Initialize Husky
bunx husky initThis creates:
.husky/directory.husky/pre-commithook
---
Basic Setup
Option 1: Lint all files (simple, slower):
# .husky/pre-commit
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
ultracite check --writeOption 2: Lint staged files only (recommended):
# .husky/pre-commit
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
ultracite check --staged --write---
Advanced Setup with lint-staged
Install lint-staged:
bun add -D lint-stagedConfigure lint-staged in package.json:
{
"lint-staged": {
"*.{js,jsx,ts,tsx,json,css}": [
"ultracite check --write --no-errors-on-unmatched --files-ignore-unknown=true"
]
}
}Update `.husky/pre-commit`:
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
bunx lint-staged---
Framework-Specific Examples
Next.js:
{
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"ultracite check --write --no-errors-on-unmatched"
],
"*.{json,css}": [
"ultracite format --write"
]
}
}Turborepo Monorepo:
{
"lint-staged": {
"apps/**/*.{js,jsx,ts,tsx}": [
"ultracite check --write --no-errors-on-unmatched"
],
"packages/**/*.{js,jsx,ts,tsx}": [
"ultracite check --write --no-errors-on-unmatched"
]
}
}---
Troubleshooting Husky
Hook not executing:
# Make hook executable
chmod +x .husky/pre-commit
# Verify hook exists
ls -la .husky/Hook fails silently:
# Add debugging
set -x # Add to top of .husky/pre-commit
# Test hook manually
.husky/pre-commitSkipping hooks (emergency only):
git commit --no-verify -m "Emergency fix"---
Lefthook Integration
Installation
# Install Lefthook
bun add -D lefthook
# Initialize Lefthook
bunx lefthook installThis creates:
lefthook.ymlconfiguration- Git hooks in
.git/hooks/
---
Basic Setup
Create lefthook.yml:
pre-commit:
commands:
ultracite:
glob: "*.{js,jsx,ts,tsx,json,css}"
run: ultracite check --write --no-errors-on-unmatched --files-ignore-unknown=true {staged_files}---
Advanced Setup
Multiple commands:
pre-commit:
parallel: true # Run commands in parallel
commands:
ultracite-lint:
glob: "*.{js,jsx,ts,tsx}"
run: ultracite check --write --no-errors-on-unmatched {staged_files}
ultracite-format:
glob: "*.{json,css,md}"
run: ultracite format --write {staged_files}
type-check:
glob: "*.{ts,tsx}"
run: tsc --noEmit {staged_files}---
Monorepo Setup
Root `lefthook.yml`:
pre-commit:
commands:
ultracite-apps:
glob: "apps/**/*.{js,jsx,ts,tsx}"
run: ultracite check --write --config-path=apps/biome.json {staged_files}
ultracite-packages:
glob: "packages/**/*.{js,jsx,ts,tsx}"
run: ultracite check --write --config-path=packages/biome.json {staged_files}---
Performance Optimization
Skip on merge commits (faster rebases):
pre-commit:
skip:
- merge
commands:
ultracite:
run: ultracite check --staged --writeFail fast (stop on first error):
pre-commit:
piped: true # Stop pipeline on error
commands:
ultracite:
run: ultracite check --staged --write---
Troubleshooting Lefthook
Hook not found:
# Reinstall hooks
bunx lefthook install
# Verify installation
ls -la .git/hooks/pre-commitYAML syntax errors:
# Validate config
bunx lefthook run pre-commit --verboseSkipping hooks (emergency only):
LEFTHOOK=0 git commit -m "Emergency fix"---
lint-staged (Standalone)
Installation
bun add -D lint-staged husky
bunx husky init---
Configuration Options
Option 1: `package.json` (recommended for simple setups):
{
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"ultracite check --write --no-errors-on-unmatched"
],
"*.{json,css}": [
"ultracite format --write"
]
}
}Option 2: `.lintstagedrc.json` (cleaner):
{
"*.{js,jsx,ts,tsx}": [
"ultracite check --write --no-errors-on-unmatched"
],
"*.{json,css}": [
"ultracite format --write"
]
}Option 3: `lint-staged.config.js` (dynamic configuration):
export default {
'*.{js,jsx,ts,tsx}': (filenames) => [
`ultracite check --write --no-errors-on-unmatched ${filenames.join(' ')}`,
],
'*.{json,css}': (filenames) => [
`ultracite format --write ${filenames.join(' ')}`,
],
};---
Advanced Patterns
Conditional linting:
export default {
'*.{js,jsx,ts,tsx}': (filenames) => {
const isApp = filenames.some(f => f.startsWith('apps/'));
const config = isApp ? 'apps/biome.json' : 'biome.json';
return [
`ultracite check --config-path=${config} --write ${filenames.join(' ')}`,
];
},
};Multiple commands per file type:
{
"*.{js,jsx,ts,tsx}": [
"ultracite check --write --no-errors-on-unmatched",
"vitest related --run"
]
}---
Troubleshooting lint-staged
Files not being linted:
# Test manually
bunx lint-staged --debug
# Check staged files
git diff --cached --name-onlyGlob patterns not matching:
# Test pattern matching
bunx lint-staged --diff="main...HEAD"Hangs on large changesets:
{
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"ultracite check --write --no-errors-on-unmatched --files-max-size=1048576"
]
}
}---
Detection Logic
Ultracite CLI automatically detects existing hook managers:
# Check for Husky
ls .husky/pre-commit
# Check for Lefthook
ls lefthook.yml
# Check for lint-staged
cat package.json | grep "lint-staged"Auto-configuration priority: 1. If lefthook.yml exists → Use Lefthook 2. Else if .husky/ exists → Use Husky 3. Else → Prompt user to choose
---
CI Integration
GitHub Actions
name: Lint
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v1
- name: Install dependencies
run: bun install
- name: Run Ultracite
run: bun ultracite ci---
GitLab CI
lint:
image: node:20
script:
- npm install -g bun
- bun install
- bun ultracite ci---
Cloudflare Pages
# .cloudflare/pages.yml
build:
command: bun run build
environment:
NODE_VERSION: 20
pre_build:
- bun install
- bun ultracite ci---
Best Practices
1. Use `--staged` flag to lint only changed files (faster) 2. Use `--write` flag to auto-fix issues 3. Use `--no-errors-on-unmatched` to ignore unsupported file types 4. Combine with lint-staged for maximum performance 5. Skip hooks sparingly (only for emergencies) 6. Test hooks locally before pushing to CI 7. Document hook setup in project README 8. Use Lefthook for monorepos (better performance)
---
See also:
configuration-guide.mdfor Ultracite configurationai-editor-integration.mdfor editor hookstroubleshooting.mdfor hook failures
# Lefthook configuration for Ultracite
# https://github.com/evilmartians/lefthook
# Pre-commit hook
pre-commit:
parallel: true
commands:
# Run Ultracite on staged files
ultracite:
glob: "*.{js,jsx,ts,tsx,json,jsonc,css}"
run: npx ultracite fix {staged_files}
stage_fixed: true # Automatically stage fixed files
# Optional: Type check
# typecheck:
# glob: "*.{ts,tsx}"
# run: tsc --noEmit
# Pre-push hook (optional)
# pre-push:
# commands:
# lint:
# run: npx ultracite check
# test:
# run: npm test
# Commit message hook (optional)
# commit-msg:
# commands:
# commitlint:
# run: npx commitlint --edit {1}
// lint-staged configuration for Ultracite
// Can be used as .lintstagedrc.js or .lintstagedrc.cjs
module.exports = {
// JavaScript/TypeScript files
'*.{js,jsx,ts,tsx}': [
'npx ultracite fix',
],
// JSON files
'*.{json,jsonc}': [
'npx ultracite fix',
],
// CSS files
'*.{css,scss}': [
'npx ultracite fix',
],
// Markdown files (formatting only, no linting)
'*.{md,mdx}': [
'npx ultracite fix',
],
// Optional: Run type check on TypeScript files
// '*.{ts,tsx}': [
// 'npx ultracite fix',
// () => 'tsc --noEmit',
// ],
};
// ESM version (.lintstagedrc.mjs):
// export default {
// '*.{js,jsx,ts,tsx,json,jsonc,css}': ['npx ultracite fix'],
// };
// JSON version (.lintstagedrc.json):
// {
// "*.{js,jsx,ts,tsx,json,jsonc,css}": ["npx ultracite fix"]
// }
// package.json version:
// {
// "lint-staged": {
// "*.{js,jsx,ts,tsx,json,jsonc,css}": ["npx ultracite fix"]
// }
// }
Biome Provider Reference
Provider: Biome (Default) Speed: Fastest (10-100x faster than ESLint) Best for: New projects, TypeScript-first development, performance-critical builds
Overview
Biome is the default Ultracite provider, offering blazing-fast Rust-based linting and formatting. It provides zero-configuration setup with 200+ preconfigured rules optimized for modern TypeScript development.
Installation
# Install with Biome provider (default)
bun x ultracite init --linter biome
# Or without explicit flag (defaults to Biome)
bun x ultracite initConfiguration File
Biome uses biome.jsonc for configuration:
{
"$schema": "https://biomejs.dev/schemas/2.3.8/schema.json",
"extends": [
"ultracite/biome/core", // v7 path (required)
"ultracite/biome/react" // Framework preset
],
"files": {
"ignore": ["dist", "node_modules", ".next", "build"]
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100
},
"linter": {
"enabled": true
}
}V7 Preset Paths (Breaking Change)
v6 paths (old - deprecated):
{
"extends": ["ultracite/core", "ultracite/react"]
}v7 paths (new - required):
{
"extends": ["ultracite/biome/core", "ultracite/biome/react"]
}Migration: Add /biome/ segment to all preset paths.
Available Presets
Core Preset
ultracite/biome/core- Base rules (200+ rules)- TypeScript strict mode
- Null/undefined safety
- Import organization
- Security rules
- Performance optimizations
Framework Presets
ultracite/biome/react- React + JSX rulesultracite/biome/next- Next.js optimizationultracite/biome/vue- Vue 3 SFC supportultracite/biome/svelte- Svelte componentsultracite/biome/solid- Solid.js patternsultracite/biome/qwik- Qwik frameworkultracite/biome/angular- Angular componentsultracite/biome/remix- Remix frameworkultracite/biome/astro- Astro framework
Rule Customization
Override or extend rules in biome.jsonc:
{
"extends": ["ultracite/biome/core", "ultracite/biome/react"],
"linter": {
"rules": {
"style": {
"useConst": "error",
"noVar": "error"
},
"correctness": {
"noUnusedVariables": "warn" // Downgrade to warning
},
"suspicious": {
"noExplicitAny": "off" // Disable rule
}
}
}
}Performance Optimization
For Large Codebases
{
"extends": ["ultracite/biome/core"],
"files": {
"maxSize": 1000000, // 1MB file size limit
"ignore": [
"**/node_modules/**",
"**/dist/**",
"**/.next/**",
"**/build/**",
"**/*.generated.ts" // Ignore generated files
]
}
}Parallel Processing
Biome automatically uses all CPU cores. No configuration needed.
Editor Integration
VS Code
Install the Biome extension:
code --install-extension biomejs.biomeAdd to .vscode/settings.json:
{
"[javascript]": {
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true
},
"[typescript]": {
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true
},
"[javascriptreact]": {
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true
},
"[typescriptreact]": {
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true
}
}CLI Commands
# Check files (linting only)
npx ultracite check .
# Format files
npx ultracite format .
# Fix issues automatically
npx ultracite fix .
# Check with verbose output
npx ultracite check . --verbose
# Dry run (no changes)
npx ultracite fix . --dry-run
# Check specific files
npx ultracite check src/**/*.tsDiagnostics
Run diagnostics to validate configuration:
npx ultracite doctorChecks:
- Configuration file validity
- Preset path correctness (v6 vs v7)
- File permissions
- Editor integration
- Git hooks status
Limitations
CSS Linting
- Basic CSS support only
- For advanced CSS/SCSS linting, use ESLint provider or add Stylelint separately
ESLint Plugin Ecosystem
- No direct ESLint plugin support
- Most common patterns covered by Biome's built-in rules
- For specific ESLint plugins, consider ESLint provider
Framework Support
- Angular/Ember support is basic
- Vue/Svelte support improving with each release
Troubleshooting
"Preset not found" Error
Problem: ultracite/core not found
Solution: Update to v7 preset paths:
{
"extends": ["ultracite/biome/core"] // Add /biome/ segment
}Format on Save Not Working
Check: 1. Biome extension installed in VS Code 2. editor.formatOnSave: true in settings 3. biomejs.biome set as default formatter
Fix:
# Reinstall Biome extension
code --install-extension biomejs.biome --forceSlow Performance
Solutions: 1. Add files.ignore patterns for large directories 2. Set files.maxSize limit 3. Exclude generated files
Resources
Related skills
How it compares
Pick a tool-specific quality skill when your project already uses that tool; pick a general review skill when you need broader guidance across many linters and checkers.
FAQ
What does ultracite help with in a workflow?
ultracite helps developers run or reason about Ultracite-based code quality and review steps tied to concrete code changes. ultracite is most useful before shipping when a developer needs consistent quality gates and actionable outputs that point to specific files or diffs.
When should ultracite be invoked?
ultracite should be invoked when a developer asks to apply Ultracite checks, enforce consistent standards, or prepare changes for merge and release. ultracite fits a ship-phase workflow where review and quality steps reduce regressions before deployment.