Skip to content
Ultracite
Esc
↑↓navigate↵open⌘Jpreview
v8.0.0Read the latest release notes

The linter and formatter for agentic development

Agents write most of the code now. Ultracite checks every edit they make against hundreds of strict rules in under half a second, so what reaches review is consistent, type-safe code instead of slop.

Zero-config forOxlintBiomeESLint

agent session — ~/acme/web
  1. Add a members list to the team settings page

  2. Write(src/components/user-list.tsx)

    ⎿  Wrote 22 lines

  3. PostToolUse hook bunx ultracite fix --hook

    ⎿ ✕ 11 problems in user-list.tsx · 333 ms

  4. Fixing all 11: typing the users, adding teamId to the effect dependencies, adding alt text, and replacing the loose comparisons and nested ternary with a lookup.

  5. Update(src/components/user-list.tsx)

    - const [users, setUsers] = useState<any[]>([]);+ const [users, setUsers] = useState<User[]>([]);  …-   }, []);+   }, [teamId]);  …-   <img src={user.avatar} />+   <img alt={user.name} src={user.avatar} />-   {user.role == "admin" ? "Admin" : user.role == "owner" ? …}+   {roleLabels[user.role]}
  6. PostToolUse hook bunx ultracite fix --hook

    ⎿ ✓ No problems · 334 ms

  7. Done. UserList is typed, accessible and passes the project’s lint rules.

Real diagnostics and timings from Ultracite’s Oxlint preset, replayed. In Claude Code, a PostToolUse hook runs ultracite fix on every file the agent writes and hands what’s left back to the agent.

Strict enough to catch what agents get wrong

Models write confident code with loose types, stale effect dependencies and missing alt text. Ultracite turns on hundreds of rules across type safety, React, accessibility and async code, so those patterns fail the check instead of reaching your review queue.

src/components/user-list.tsx11 problems
1import { useEffect, useState } from "react";
2
3export function UserList({ teamId }: { teamId: string }) {func-style · function-component-definition
4 const [users, setUsers] = useState<any[]>([]);no-explicit-any
5
6 useEffect(() => {
7 fetch(`/api/teams/${teamId}/users`)exhaustive-deps
8 .then((res) => res.json())prefer-await-to-then
9 .then((data) => setUsers(data));prefer-await-to-then
10 }, []);exhaustive-effect-dependencies
11
12 return (
13 <ul>
14 {users.map((user) => (
15 <li key={user.id}>
16 <img src={user.avatar} />jsx-a11y/alt-text
17 {user.role == "admin" ? "Admin" : user.role == "owner" ? "Owner" : "Member"}no-nested-ternary · eqeqeq ×2
18 </li>
19 ))}
20 </ul>
21 );
22}
Type safety
no-explicit-anyno-non-null-assertionno-floating-promises
React and hooks
exhaustive-depsjsx-keybutton-has-type
Accessibility
alt-textanchor-is-validaria-role
Async and correctness
eqeqeqrequire-awaitno-await-in-loop
Anti-slopOpt-in
Dillon Mulroy’s rules against unjustified type assertions, unknown leaking through signatures and other escape hatches.

Fast enough to run after every edit

Agents check their work after nearly every change. Ultracite answers in about a third of a second, so the check never becomes the slow part of the loop.

One agent turn

Your agent reads, thinks and writes the edit · seconds to minutes, depending on the model and task

ultracite check · 330 ms

Check the file your agent just edited
330ms
Check a whole 42-file project
340ms
The same project on Biome
257ms
Agent time isn’t drawn to scale. Check times are medians on an Apple M1 Pro, end to end through the ultracite CLI on Oxlint unless noted: the single file is the component in the session above, and the project is the repo’s benchmark fixture (bun ./benchmark/index.ts).

Wired into the agent loop, start to finish

Your agent learns the standard before it writes, gets checked after every edit, and takes over whatever autofix can’t settle. Nothing waits for CI.

  1. $ npx skills add haydenbleasel/ultracite

    skills/ultracite/SKILL.md

    description: Ultracite is a zero-config linting and formatting preset for JavaScript/TypeScript projects. Use when setting up Ultracite, running check, fix or doctor, writing code that follows its standards, or troubleshooting.

    1 · Setup

    Let your agent install it

    Add the Ultracite skill and ask for it. Your agent learns how to run init, check, fix and doctor, and how to troubleshoot the result.

  2. # Ultracite Code Standards

    - Prefer `unknown` over `any` when the type is genuinely unknown

    - Specify all dependencies in hook dependency arrays correctly

    - Provide meaningful alt text for images

    • Claude Code
    • Codex
    • Gemini CLI
    • GitHub Copilot
    • OpenCode
    • Warp
    • Qwen Code
    • 40 agents

    2 · Before it writes

    The standard, in your agent’s context

    init writes the rules into AGENTS.md, which all 40 agents read, so generated code starts close to passing.

  3. .claude/settings.json

    {
      "hooks": {
        "PostToolUse": [
          {
            "hooks": [{ "command": "bunx ultracite fix --hook", "type": "command" }],
            "matcher": "Write|Edit"
          }
        ]
      }
    }

    3 · After every edit

    Hooks that check each file it touches

    A hook fixes every file your agent edits in Cursor, Devin Desktop, CodeBuddy, Claude Code, Codex, Deep Agents, GitHub Copilot, and Grok Build. In Claude Code, CodeBuddy, Codex, Devin Desktop, Deep Agents, Grok Build and VS Code’s Local agent, it hands what it can’t fix back to the agent.

  4. $ npx ultracite fix --codex
    ┌  ultracite fix — powered by Codex
    ◇  Autofix complete. 9 issues in 3 files left for Codex.
    ✓ src/queue.ts:2:22  no-async-promise-executor
    ✓ src/queue.ts:23:26  require-await
    ⠋ src/config-loader.ts:3:10  no-eval
    ⠋ src/config-loader.ts:10:22  eqeqeq

    4 · When autofix can’t

    Your agent CLI fixes the rest

    ultracite fix --claude or --codex sends what’s left to Claude Code or Codex, which repairs the codebase file by file with edit-only permissions.

One command, your choice of engine

ultracite init detects your stack, writes the config for the engine you pick, and sets up your editor, agents and git hooks. Every rule stays yours to override.

import { defineConfig } from "oxlint";
import core from "ultracite/oxlint/core";
import react from "ultracite/oxlint/react";
import next from "ultracite/oxlint/next";

export default defineConfig({
  extends: [core, react, next],
  ignorePatterns: core.ignorePatterns,
});
import { defineConfig } from "oxfmt";
import ultracite from "ultracite/oxfmt";

export default defineConfig({
  ...ultracite,
});

15 framework presets

  • React
  • Next.js
  • Solid
  • Vue
  • Svelte
  • Qwik
  • Remix
  • TanStack
  • Angular
  • Astro
  • NestJS
  • Jest
  • Vitest
  • Cypress
  • Storybook

Pre-commit, your way

Husky · Lefthook · lint-staged · pre-commit

Set the bar on day one

I’ve switched to Ultracite for most of my projects now. Can recommend.

shadcn@shadcn

i can't work under the iron gauntlet of @haydenbleasel's ultracite, but you can be fuckin sure i make these robots conform

Joel Hooks@joelhooks

thanks for building Ultracite @haydenbleasel, it's awesome.

JB@julianbenegas8

Ship less slop

One command sets up your linter, formatter, editor and agents. Works with Oxlint, Biome and ESLint.