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 forOxlint
Biome
ESLint
Add a members list to the team settings page
Write(src/components/user-list.tsx)
⎿ Wrote 22 lines
PostToolUse hook bunx ultracite fix --hook
⎿ ✕ 11 problems in user-list.tsx · 333 ms
Fixing all 11: typing the users, adding
teamIdto the effect dependencies, adding alt text, and replacing the loose comparisons and nested ternary with a lookup.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]}
PostToolUse hook bunx ultracite fix --hook
⎿ ✓ No problems · 334 ms
Done.
UserListis typed, accessible and passes the project’s lint rules.
ultracite fix on every file the agent writes and hands what’s left back to the agent.Used by engineering teams at
…and thousands of open source projects →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.
import { useEffect, useState } from "react";export function UserList({ teamId }: { teamId: string }) {func-style · function-component-definition const [users, setUsers] = useState<any[]>([]);no-explicit-any useEffect(() => { fetch(`/api/teams/${teamId}/users`)exhaustive-deps .then((res) => res.json())prefer-await-to-then .then((data) => setUsers(data));prefer-await-to-then }, []);exhaustive-effect-dependencies return ( <ul> {users.map((user) => ( <li key={user.id}> <img src={user.avatar} />jsx-a11y/alt-text {user.role == "admin" ? "Admin" : user.role == "owner" ? "Owner" : "Member"}no-nested-ternary · eqeqeq ×2 </li> ))} </ul> );}- 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,
unknownleaking 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
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.
$ 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,fixanddoctor, and how to troubleshoot the result.# 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
- 40 agents
2 · Before it writes
The standard, in your agent’s context
initwrites the rules into AGENTS.md, which all 40 agents read, so generated code starts close to passing..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.
$ 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 --claudeor--codexsends 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,
});{
"$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
"extends": [
"ultracite/biome/core",
"ultracite/biome/react",
"ultracite/biome/next"
]
}import core from "ultracite/eslint/core";
import react from "ultracite/eslint/react";
import next from "ultracite/eslint/next";
export default [
...core,
...react,
...next,
];import config from "ultracite/prettier";
export default {
...config,
plugins: ["prettier-plugin-tailwindcss"],
};export { default } from "ultracite/stylelint";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@shadcni can't work under the iron gauntlet of @haydenbleasel's ultracite, but you can be fuckin sure i make these robots conform
Joel Hooks@joelhooksthanks for building Ultracite @haydenbleasel, it's awesome.
JB@julianbenegas8Ship less slop
One command sets up your linter, formatter, editor and agents. Works with Oxlint, Biome and ESLint.