返回 Skills 目錄
haydenbleasel/ultracite包含需要注意的行為

SKILL DETAIL

ultracite

haydenbleasel/ultracite/ultracite

Ultracite is a zero-config linting and formatting preset for JavaScript/TypeScript projects. Use when: (1) Setting up or initializing Ultracite in a project, or migrating its existing lint and format config onto Ultracite (ultracite init), (2) Running linting or formatting commands (check, fix, doctor), (3) Writing or reviewing JS/TS code in a project that uses Ultracite — to follow its code standards, (4) Troubleshooting linting/formatting issues, (5) Upgrading Ultracite or bringing its configuration up to a newer release (ultracite upgrade), (6) User mentions 'ultracite', 'lint', 'format', 'code quality', or 'biome/eslint/oxlint' in a project with Ultracite installed.

安裝量 · 347查看來源

Installation

npx skills add https://github.com/haydenbleasel/ultracite --skill ultracite

技能檔案

SKILL.md

最近同步 · 2026年10月21日

references/code-standards.md›
# Ultracite Code Standards

Formatting is intentionally handled by your project's configured linter or formatter. Respect the repository's existing quote, width, semicolon, trailing comma, and line ending settings instead of forcing one global formatting style.

## Core Principles

Write code that is **accessible, performant, type-safe, and maintainable**. Focus on clarity and explicit intent over brevity.

## Type Safety & Explicitness

- Use explicit types for function parameters and return values when they enhance clarity
- Prefer `unknown` over `any` when the type is genuinely unknown
- Use const assertions (`as const`) for immutable values and literal types
- Leverage TypeScript's type narrowing instead of type assertions
- Use meaningful variable names instead of magic numbers — extract constants with descriptive names

## Modern JavaScript/TypeScript

- Use arrow functions for callbacks and short functions
- Prefer `for...of` loops over `.forEach()` and indexed `for` loops
- Use optional chaining (`?.`) and nullish coalescing (`??`) for safer property access
- Prefer template literals over string concatenation
- Use destructuring for object and array assignments
- Use `const` by default, `let` only when reassignment is needed, never `var`

## Async & Promises

- Always `await` promises in async functions — don't forget to use the return value
- Use `async/await` syntax instead of promise chains for better readability
- Handle errors appropriately in async code with try-catch blocks
- Don't use async functions as Promise executors

## React & JSX

- Use function components over class components
- Call hooks at the top level only, never conditionally
- Specify all dependencies in hook dependency arrays correctly
- Use the `key` prop for elements in iterables (prefer unique IDs over array indices)
- Nest children between opening and closing tags instead of passing as props
- Don't define components inside other components
- Use semantic HTML and ARIA attributes for accessibility:
  - Provide meaningful alt text for images
  - Use proper heading hierarchy
  - Add labels for form inputs
  - Include keyboard event handlers alongside mouse events
  - Use semantic elements (`<button>`, `<nav>`, etc.) instead of divs with roles

## Error Handling & Debugging

- Remove `console.log`, `debugger`, and `alert` statements from production code
- Throw `Error` objects with descriptive messages, not strings or other values
- Use `try-catch` blocks meaningfully — don't catch errors just to rethrow them
- Prefer early returns over nested conditionals for error cases

## Code Organization

- Keep functions focused and under reasonable cognitive complexity limits
- Extract complex conditions into well-named boolean variables
- Use early returns to reduce nesting
- Prefer simple conditionals over nested ternary operators
- Group related code together and separate concerns
- Avoid import cycles; move shared code into a module both sides import

## Security

- Add `rel="noopener noreferrer"` when using `target="_blank"` on links
- Avoid `dangerouslySetInnerHTML` unless absolutely necessary
- Don't use `eval()` or assign directly to `document.cookie`
- Validate and sanitize user input

## Performance

- Avoid spread syntax in accumulators within loops
- Use top-level regex literals instead of creating them in loops
- Prefer specific imports over namespace imports
- Avoid barrel files (index files that re-export everything)
- Use proper image components (e.g., Next.js `<Image>`) over `<img>` tags

## Framework-Specific

**Next.js:** Use `<Image>` component for images. Use `next/head` or the App Router metadata API for head elements. Use Server Components for async data fetching instead of async Client Components.

**React 19+:** Use ref as a prop instead of `React.forwardRef`.

**Solid/Svelte/Vue/Qwik:** Use `class` and `for` attributes (not `className` or `htmlFor`).

## Testing

- Write assertions inside `it()` or `test()` blocks
- Avoid done callbacks in async tests — use async/await instead
- Don't use `.only` or `.skip` in committed code
- Keep test suites reasonably flat — avoid excessive `describe` nesting

## When Your Linter Can't Help

Your configured linter or formatter will catch most mechanical issues automatically. Focus your attention on:

1. Business logic correctness
2. Meaningful naming
3. Architecture decisions
4. Edge cases
5. User experience
6. Documentation for genuinely complex logic
references/upgrades/v5.md›
# Upgrading to Ultracite v5

Ultracite v5 moved to Biome 2, whose configuration format differs from Biome 1's. Every later release uses Biome 2 too.

## Does the project need it?

Yes, if the Biome config (`biome.json` or `biome.jsonc`) still uses Biome 1's format: its `$schema` points at a 1.x schema (such as `https://biomejs.dev/schemas/1.9.4/schema.json`), or it has a top-level `organizeImports`, `files.ignore` or `files.include`.

## Steps

1. Set `$schema` to `./node_modules/@biomejs/biome/configuration_schema.json`. Leave `"extends": ["ultracite"]` as it is; the v6 and v7 guides rename it.

2. Move Biome 1 settings to their Biome 2 form:

   - `files.ignore` and `files.include` become a single `files.includes` list. Start it with `"**"`, then add each ignored path with a leading `!`. Globs no longer get an implicit `**/` prefix, so an ignored `dist` becomes `"!**/dist"`.
   - `organizeImports` moves to `assist.actions.source.organizeImports`, set to `"on"` or `"off"`.
   - `linter.rules.all` is gone, with no replacement. Remove it.
   - Paths and globs are now relative to the config file, not the folder Biome runs in.

   If you can run commands, `npx @biomejs/biome migrate --write` makes most of these changes. Review what it writes.

3. Biome 2 reads suppression comments as `// biome-ignore lint/<group>/<rule>: <reason>`. Rewrite any in the old `lint(<group>/<rule>)` form.

4. `biome.json` keeps working. v5 wrote `biome.jsonc` for new projects, but there's no need to rename an existing file.

## Check

`npx ultracite check` runs without a configuration error.
references/upgrades/v6.md›
# Upgrading to Ultracite v6

Ultracite v6 split the single Biome preset into a `core` preset and one preset per framework, which a project combines in `extends`.

## Does the project need it?

Yes, if a Biome config (`biome.json` or `biome.jsonc`) extends the bare `ultracite` preset: `"extends": ["ultracite"]`.

## Steps

1. Replace `"ultracite"` in `extends` with `ultracite/core`, followed by the preset for each framework the project uses, judging by its `package.json` dependencies:

   | Dependency | Preset |
   | --- | --- |
   | `react` | `ultracite/react` |
   | `next` | `ultracite/next`, after `ultracite/react` |
   | `solid-js` | `ultracite/solid` |
   | `vue` | `ultracite/vue` |
   | `svelte` | `ultracite/svelte` |
   | `@builder.io/qwik` or `@qwik.dev/core` | `ultracite/qwik` |
   | `@angular/core` | `ultracite/angular` |
   | `@remix-run/react` | `ultracite/remix` |
   | `astro` | `ultracite/astro` |

   Keep every other setting in the file.

   ```jsonc title="biome.jsonc"
   {
     // v5: "extends": ["ultracite"]
     "extends": ["ultracite/core", "ultracite/react", "ultracite/next"],
   }
   ```

2. These are the v6 preset names. When you're upgrading to v7 or later, follow the v7 guide too, or write the v7 names (`ultracite/biome/core`, `ultracite/biome/react`, and so on) directly.

## Check

`npx ultracite check` runs without a configuration error.
references/upgrades/v7.md›
# Upgrading to Ultracite v7

Ultracite v7 supports three linters (Oxlint + Oxfmt, Biome, and ESLint + Prettier + Stylelint), so every preset path names its linter. It also removed the `lint` and `format` commands, which v5.3 had already renamed to `check` and `fix`. Projects set up on v6 or earlier use Biome.

## Does the project need it?

Yes, if either of these is true:

- A Biome config (`biome.json` or `biome.jsonc`, including nested ones in monorepo packages) extends an Ultracite preset without a linter segment, such as `ultracite/core` or `ultracite/react` instead of `ultracite/biome/core`.
- Something still runs `ultracite lint` or `ultracite format`: a `package.json` script, a Husky hook in `.husky/`, a lint-staged config (in `package.json`, `.lintstagedrc*` or `lint-staged.config.*`), `lefthook.yml`, `.pre-commit-config.yaml`, or a CI workflow in `.github/workflows/`.

## Steps

1. In every Biome config, rename each `ultracite/<preset>` entry in `extends` to `ultracite/biome/<preset>`. The v6 presets are `core`, `react`, `next`, `solid`, `vue`, `svelte`, `qwik`, `angular`, `remix` and `astro`. Keep the order of `extends` and every other setting in the file.

   ```jsonc title="biome.jsonc"
   {
     // v6: "extends": ["ultracite/core", "ultracite/react", "ultracite/next"]
     "extends": [
       "ultracite/biome/core",
       "ultracite/biome/react",
       "ultracite/biome/next",
     ],
   }
   ```

2. Replace `ultracite lint` with `ultracite check`, and `ultracite format` with `ultracite fix`, everywhere they run. Keep their arguments, including file paths and `--unsafe`.

3. Keep the project on Biome. v7 can move a project to Oxlint or ESLint, but that's the user's choice to make with `npx ultracite init --linter oxlint` (or `eslint`), not part of the upgrade.

## Check

`npx ultracite doctor` passes, and `npx ultracite check` runs without a configuration error.
references/upgrades/v8.md›
# Upgrading to Ultracite v8

Ultracite v8 stops running Prettier inside ESLint and Stylelint, moves the Cypress and Storybook rules and the type-checked rules out of the ESLint core preset into presets of their own, and turns on Oxlint's type-aware linting when `oxlint-tsgolint` is installed. `ultracite init` also has a `--yes` flag for skipping prompts, which `--quiet` no longer does.

## Does the project need it?

Yes, if any of these is true:

- An ESLint config (`eslint.config.*`) or Stylelint config (`stylelint.config.*`, `.stylelintrc*`) sets the `prettier/prettier` rule.
- The project uses ESLint with Ultracite's presets, depends on `cypress`, and its ESLint config doesn't import `ultracite/eslint/cypress`.
- The project uses ESLint with Ultracite's presets, depends on `storybook` or an `@storybook/*` package, and its ESLint config doesn't import `ultracite/eslint/storybook`.
- The project uses ESLint with Ultracite's presets, its ESLint config sets one of the rules under [Rules that need type information](#rules-that-need-type-information) to anything other than `"off"`, and it doesn't import `ultracite/eslint/type-aware` or set `parserOptions.projectService` itself.
- The project uses Oxlint, has `oxlint-tsgolint` in its dependencies, and its Oxlint config (`oxlint.config.ts`, `oxlint.config.mts` or `.oxlintrc.json`) doesn't set `typeAware: true` in `options`.
- The project uses ESLint with Ultracite's presets, and `.zed/settings.json` formats a language with the `eslint` language server: `"formatter": { "language_server": { "name": "eslint" } }`, on its own or in a list.
- Something runs `ultracite init` with `--quiet` but without `--yes` (or `-y`): a `package.json` script or a CI workflow in `.github/workflows/`.

## Steps

1. Remove every `prettier/prettier` entry from the ESLint and Stylelint configs. v8 doesn't load `eslint-plugin-prettier` or `stylelint-prettier`, so ESLint and Stylelint would stop with an unknown rule. Prettier still checks and formats every file, as its own step of `ultracite check` and `fix`. Leave the rest of each `rules` object as it is.

2. If the project depends on `cypress`, import Ultracite's Cypress preset in the ESLint config and spread it after `core`, in the same style as the presets already there. Do the same with `ultracite/eslint/storybook` if the project depends on `storybook` or an `@storybook/*` package. v7 applied both rule sets from the core preset.

   ```js title="eslint.config.mjs"
   import core from "ultracite/eslint/core";
   import react from "ultracite/eslint/react";
   import cypress from "ultracite/eslint/cypress";
   import storybook from "ultracite/eslint/storybook";

   export default [...core, ...react, ...cypress, ...storybook];
   ```

3. If the ESLint config sets one of the rules under [Rules that need type information](#rules-that-need-type-information) to anything other than `"off"`, and doesn't set `parserOptions.projectService` itself, import `ultracite/eslint/type-aware` and spread it after `core`, and for each of the `angular`, `jest`, `nestjs`, `qwik`, `tanstack` and `vitest` presets the config imports, import its add-on, `ultracite/eslint/<framework>/type-aware`, and spread it right after that preset. v7's core preset gave every TypeScript file type information, so the project relied on it. Without the type-aware preset, most of these rules stop ESLint with "You have used a rule which requires type information", and the SonarJS and Unicorn ones report nothing. Keep the project's own setting for each rule.

   ```js title="eslint.config.mjs"
   import core from "ultracite/eslint/core";
   import typeAware from "ultracite/eslint/type-aware";
   import vitest from "ultracite/eslint/vitest";
   import vitestTypeAware from "ultracite/eslint/vitest/type-aware";

   export default [...core, ...typeAware, ...vitest, ...vitestTypeAware];
   ```

4. If the project uses Oxlint and has `oxlint-tsgolint` installed, add `typeAware: true` to `options` in the root Oxlint config, creating `options` when the config has none. v7 installed `oxlint-tsgolint` for `init --type-aware` without turning it on. If a `package.json` script passes `--type-aware` to `ultracite check` or `fix`, it can stay.

   ```ts title="oxlint.config.ts"
   export default defineConfig({
     env: core.env,
     extends: [core],
     ignorePatterns: core.ignorePatterns,
     options: { typeAware: true },
   });
   ```

5. Wherever `ultracite init` runs with `--quiet` and without `--yes`, add `--yes`. In v8, `--quiet` only hides progress output and no longer skips the prompts. Keep `--quiet` and every other flag.

6. In `.zed/settings.json`, change every `formatter` that names the `eslint` language server to `"prettier"`, and leave the `code_actions_on_format` next to it as it is. v7 ran Prettier as an ESLint rule, so ESLint's language server formatted too. In v8, Zed's Prettier integration formats after ESLint's fixes, with the project's own Prettier config and plugins.

   ```jsonc title=".zed/settings.json"
   "TypeScript": {
     "code_actions_on_format": {
       "source.fixAll.eslint": true,
       "source.organizeImports.eslint": true,
     },
     // v7: "formatter": { "language_server": { "name": "eslint" } }
     "formatter": "prettier",
   }
   ```

7. Apart from step 3, don't add `ultracite/eslint/type-aware`. v8 runs ESLint's type-checked rules only in projects that ask for them, with `npx ultracite init --type-aware`, and unless the config already sets one of those rules, that's the user's choice to make, not part of the upgrade.

The Git hooks (Husky, Lefthook, pre-commit) and agent hooks v7 wrote keep working. Re-running `npx ultracite init` with the same `--integrations` and `--hooks` updates them to fix only the staged files and to run the installed `ultracite` directly; that's for the user to run, not part of this guide.

## Check

`npx ultracite doctor` passes, and `npx ultracite check` runs without a configuration error.

## Rules that need type information

The rules v8 runs only with `ultracite/eslint/type-aware` and the framework add-ons. v7 ran all of them with type information.

- typescript-eslint: `@typescript-eslint/await-thenable`, `@typescript-eslint/consistent-return`, `@typescript-eslint/consistent-type-exports`, `@typescript-eslint/dot-notation`, `@typescript-eslint/naming-convention`, `@typescript-eslint/no-array-delete`, `@typescript-eslint/no-base-to-string`, `@typescript-eslint/no-confusing-void-expression`, `@typescript-eslint/no-deprecated`, `@typescript-eslint/no-duplicate-type-constituents`, `@typescript-eslint/no-floating-promises`, `@typescript-eslint/no-for-in-array`, `@typescript-eslint/no-generated-empty-object-type`, `@typescript-eslint/no-implied-eval`, `@typescript-eslint/no-meaningless-void-operator`, `@typescript-eslint/no-misused-promises`, `@typescript-eslint/no-misused-spread`, `@typescript-eslint/no-mixed-enums`, `@typescript-eslint/no-redundant-type-constituents`, `@typescript-eslint/no-unnecessary-boolean-literal-compare`, `@typescript-eslint/no-unnecessary-condition`, `@typescript-eslint/no-unnecessary-qualifier`, `@typescript-eslint/no-unnecessary-template-expression`, `@typescript-eslint/no-unnecessary-type-arguments`, `@typescript-eslint/no-unnecessary-type-assertion`, `@typescript-eslint/no-unnecessary-type-conversion`, `@typescript-eslint/no-unnecessary-type-parameters`, `@typescript-eslint/no-unsafe-argument`, `@typescript-eslint/no-unsafe-assignment`, `@typescript-eslint/no-unsafe-call`, `@typescript-eslint/no-unsafe-enum-assignment`, `@typescript-eslint/no-unsafe-enum-comparison`, `@typescript-eslint/no-unsafe-member-access`, `@typescript-eslint/no-unsafe-return`, `@typescript-eslint/no-unsafe-type-assertion`, `@typescript-eslint/no-unsafe-unary-minus`, `@typescript-eslint/no-useless-default-assignment`, `@typescript-eslint/non-nullable-type-assertion-style`, `@typescript-eslint/only-throw-error`, `@typescript-eslint/prefer-destructuring`, `@typescript-eslint/prefer-find`, `@typescript-eslint/prefer-includes`, `@typescript-eslint/prefer-nullish-coalescing`, `@typescript-eslint/prefer-optional-chain`, `@typescript-eslint/prefer-promise-reject-errors`, `@typescript-eslint/prefer-readonly`, `@typescript-eslint/prefer-readonly-parameter-types`, `@typescript-eslint/prefer-reduce-type-parameter`, `@typescript-eslint/prefer-regexp-exec`, `@typescript-eslint/prefer-return-this-type`, `@typescript-eslint/prefer-string-starts-ends-with`, `@typescript-eslint/promise-function-async`, `@typescript-eslint/related-getter-setter-pairs`, `@typescript-eslint/require-array-sort-compare`, `@typescript-eslint/require-await`, `@typescript-eslint/restrict-plus-operands`, `@typescript-eslint/restrict-template-expressions`, `@typescript-eslint/return-await`, `@typescript-eslint/strict-boolean-expressions`, `@typescript-eslint/strict-void-return`, `@typescript-eslint/switch-exhaustiveness-check`, `@typescript-eslint/unbound-method`, `@typescript-eslint/use-unknown-in-catch-callback-variable`
- SonarJS: `sonarjs/argument-type`, `sonarjs/array-callback-without-return`, `sonarjs/assertions-in-tests`, `sonarjs/deprecation`, `sonarjs/different-types-comparison`, `sonarjs/disabled-resource-integrity`, `sonarjs/existing-groups`, `sonarjs/function-return-type`, `sonarjs/in-operator-type-error`, `sonarjs/index-of-compare-to-positive-number`, `sonarjs/jsx-no-leaked-render`, `sonarjs/new-operator-misuse`, `sonarjs/no-alphabetical-sort`, `sonarjs/no-array-delete`, `sonarjs/no-associative-arrays`, `sonarjs/no-async-constructor`, `sonarjs/no-for-in-iterable`, `sonarjs/no-ignored-return`, `sonarjs/no-in-misuse`, `sonarjs/no-incompatible-assertion-types`, `sonarjs/no-incorrect-string-concat`, `sonarjs/no-misleading-array-reverse`, `sonarjs/no-return-type-any`, `sonarjs/no-selector-parameter`, `sonarjs/no-try-promise`, `sonarjs/no-undefined-argument`, `sonarjs/no-useless-intersection`, `sonarjs/non-number-in-arithmetic-expression`, `sonarjs/null-dereference`, `sonarjs/operation-returning-nan`, `sonarjs/post-message`, `sonarjs/prefer-read-only-props`, `sonarjs/prefer-regexp-exec`, `sonarjs/strings-comparison`, `sonarjs/synchronous-exception-assertions`, `sonarjs/unused-named-groups`, `sonarjs/values-not-convertible-to-numbers`
- Unicorn: `unicorn/no-non-function-verb-prefix`
- Angular (`ultracite/eslint/angular/type-aware`): `@angular-eslint/no-developer-preview`, `@angular-eslint/no-experimental`, `@angular-eslint/no-uncalled-signals`, `@angular-eslint/prefer-signal-model`, `@angular-eslint/prefer-signals`, `@angular-eslint/reactive-context-must-read-signal`
- Jest (`ultracite/eslint/jest/type-aware`): `jest/no-error-equal`, `jest/no-unnecessary-assertion`, `jest/unbound-method`, `jest/valid-expect-with-promise`
- NestJS (`ultracite/eslint/nestjs/type-aware`): `@darraghor/nestjs-typed/all-properties-have-explicit-defined`, `@darraghor/nestjs-typed/api-enum-property-best-practices`, `@darraghor/nestjs-typed/validated-non-primitive-property-needs-type-decorator`
- Qwik (`ultracite/eslint/qwik/type-aware`): `qwik/valid-lexical-scope`
- TanStack Start (`ultracite/eslint/tanstack/type-aware`): `@tanstack/start/no-async-client-component`, `@tanstack/start/no-client-code-in-server-component`
- Vitest (`ultracite/eslint/vitest/type-aware`): `vitest/unbound-method`
SKILL.md›
---
name: ultracite
description: "Ultracite is a zero-config linting and formatting preset for JavaScript/TypeScript projects. Use when: (1) Setting up or initializing Ultracite in a project, or migrating its existing lint and format config onto Ultracite (ultracite init), (2) Running linting or formatting commands (check, fix, doctor), (3) Writing or reviewing JS/TS code in a project that uses Ultracite — to follow its code standards, (4) Troubleshooting linting/formatting issues, (5) Upgrading Ultracite or bringing its configuration up to a newer release (ultracite upgrade), (6) User mentions 'ultracite', 'lint', 'format', 'code quality', or 'biome/eslint/oxlint' in a project with Ultracite installed."
---

# Ultracite

Zero-config linting and formatting for JS/TS projects. Supports three linter backends: **Oxlint** + Oxfmt (recommended), **Biome**, and **ESLint** + Prettier + Stylelint.

## Detecting Ultracite

Check if `ultracite` is in `package.json` dependencies or devDependencies. Detect the active linter by looking for (searching upward from the current directory):

- `biome.json` / `biome.jsonc` → Biome
- `eslint.config.*` (`.mjs`, `.js`, `.cjs`, `.ts`, `.mts`, `.cts`) → ESLint (with Prettier for formatting)
- `oxlint.config.ts`, `oxlint.config.mts` or `.oxlintrc.json` → Oxlint (with `oxfmt.config.ts` or `oxfmt.config.mts` for formatting; init writes the `.mts` form in a package that isn't an ES module)

## CLI Commands

```bash
# Check for issues (read-only)
bunx ultracite check

# Auto-fix issues
bunx ultracite fix

# Diagnose setup problems
bunx ultracite doctor

# Initialize in a new project
bunx ultracite init
```

Replace `bunx` with `npx`, `pnpm exec`, or `yarn` depending on the package manager, so the project's installed Ultracite runs (`pnpm dlx` and `yarn dlx` download the latest release instead, and Yarn 1 has no `dlx`). Only `init` in a project without Ultracite needs a download runner such as `pnpm dlx`.

`check` and `fix` accept optional file paths: `bunx ultracite check src/index.ts`. Unknown options are passed through to the underlying linter (e.g. `bunx ultracite check --max-warnings 0`).

## Initialization

`bunx ultracite init` runs an interactive setup. For non-interactive (CI) use, pass flags:

```bash
bunx ultracite init \
  --pm bun \
  --linter biome \
  --editors universal \
  --agents claude copilot \
  --frameworks react next \
  --integrations husky lint-staged \
  --yes
```

**Flags:**

- `--pm` — `npm` | `yarn` | `pnpm` | `bun` | `deno` | `nub` | `aube`
- `--linter` — `oxlint` (recommended) | `biome` | `eslint`
- `--editors` — `universal` (writes `.vscode/settings.json` for every VS Code-based editor) | `vscode` | `cursor` | `devin` | `codebuddy` | `antigravity` | `bob` | `kiro` | `trae` | `void` | `zed`
- `--agents` — every choice writes the rules to `AGENTS.md`. `universal` writes only that; `claude`, `gemini`, `aider` and `replit` also add the import, settings or copy that agent needs to read them; IDs like `codex`, `copilot`, `cline`, `amp` and `cursor-cli` (40 agents supported) need nothing more
- `--frameworks` — `react` | `next` | `solid` | `vue` | `svelte` | `qwik` | `remix` | `tanstack` | `angular` | `astro` | `nestjs` | `jest` | `vitest` | `cypress` | `storybook`
- `--integrations` — `husky` | `lefthook` | `lint-staged` | `pre-commit`
- `--hooks` — Enable auto-fix hooks: `claude` | `codex` | `copilot` | `cursor` | `devin` | `codebuddy` | `deepagents` | `grok`
- `--js-plugins` — Opt-in Oxlint JS plugins: `@shadcn/lint` | `anti-slop` | `eslint-plugin-github` | `eslint-plugin-jsdoc` | `eslint-plugin-sonarjs` | `eslint-plugin-tsdoc` | `oxlint-plugin-react-doctor`
- `--type-aware` — Enable type-aware linting (ESLint and Biome: extend their `type-aware` preset; Oxlint: installs `oxlint-tsgolint` and sets `typeAware`), and turn on `strictNullChecks` in tsconfig files
- `--install-skill` — Install the reusable Ultracite skill after setup
- `--skip-install` — Skip dependency installation
- `--yes`, `-y` — Take the defaults without prompting (automatic when `CI=true` or there's no terminal); defaults to `oxlint` when `--linter` is omitted
- `--quiet` — Only print warnings and errors

Init creates config that extends Ultracite presets:

```jsonc
// biome.jsonc
{ "extends": ["ultracite/biome/core", "ultracite/biome/react"] }
```

```ts
// eslint.config.mjs — arrays of flat configs, spread together
import core from "ultracite/eslint/core";
import react from "ultracite/eslint/react";
export default [...core, ...react];
```

```ts
// oxlint.config.ts — imports passed to extends
import { defineConfig } from "oxlint";
import core from "ultracite/oxlint/core";
export default defineConfig({
  env: core.env,
  extends: [core],
  ignorePatterns: core.ignorePatterns,
});
```

Presets available per linter (`ultracite/<linter>/<preset>`): `core`, `react`, `next`, `solid`, `vue`, `svelte`, `qwik`, `remix`, `tanstack`, `angular`, `astro`, `nestjs`, `jest`, `vitest`, `cypress`, `storybook` (`cypress` and `storybook` only have rules on ESLint; on Oxlint and Biome they're empty). ESLint and Biome also have `type-aware`, the rules that need type information, and ESLint has a `<framework>/type-aware` add-on for `angular`, `jest`, `nestjs`, `qwik`, `tanstack` and `vitest`, extended after that framework's preset. Oxlint also has `js-plugins` (`eslint-plugin-github`, `eslint-plugin-sonarjs` and `oxlint-plugin-react-doctor` run through oxlint's JS plugin support, with `next/js-plugins` and `tanstack/js-plugins` adding framework-specific React Doctor rules), `anti-slop` and `shadcn`. These are opt-in: init only adds them when picked in its prompt or passed with `--js-plugins`. Oxlint and ESLint also have `gdp`, for codebases that use gdp-ts authorization proofs (`@gdp-ts/core` ships the plugin); init never adds it, so extend it by hand after `core`.

## Migrating an Existing Project

Migrating means moving the project's own ESLint, Prettier, Stylelint, Biome or Oxlint configuration onto Ultracite's presets; the project can keep its linter. Run `init` (it preselects the linter it finds), carry over rules the presets don't cover after Ultracite's presets, and run `ultracite fix` to format everything in one commit. Then fix what `check` still reports, or migrate progressively:

- Turn off each failing rule after Ultracite's presets: in `rules` for Oxlint (`ultracite check -f json` lists them as `plugin(rule)`, written `plugin/rule`), or `linter.rules` and `assist.actions.source` for Biome (`ultracite check --reporter=summary`). On ESLint, `ultracite check --suppress-all` records today's errors in `eslint-suppressions.json` instead.
- Turn them back on a few at a time: remove an override (or prune with `ultracite check --prune-suppressions`), run `ultracite fix`, fix the rest, one rule per change.

Full steps: https://www.ultracite.ai/docs/migrate.md

## Upgrading

```bash
npx ultracite@latest upgrade
```

`upgrade` installs the latest Ultracite (or the release `--version 7` names), reinstalls the linter at the versions that release supports, and runs `doctor`. Major releases also change how the configuration looks; `upgrade` lists the guides the project still needs, and with `--claude` or `--codex` it has that agent CLI apply them.

To apply them yourself, follow each guide that applies, oldest first. Each one says how to tell whether the project needs it:

- [references/upgrades/v5.md](references/upgrades/v5.md): Biome 1's config format to Biome 2's
- [references/upgrades/v6.md](references/upgrades/v6.md): the single `ultracite` preset to `ultracite/core` plus framework presets
- [references/upgrades/v7.md](references/upgrades/v7.md): `ultracite/<preset>` to `ultracite/biome/<preset>`, and the `lint` and `format` commands to `check` and `fix`
- [references/upgrades/v8.md](references/upgrades/v8.md): removing `prettier/prettier` from ESLint and Stylelint configs, the Cypress and Storybook presets, ESLint configs that set type-checked rules, Oxlint's `typeAware` option, `init --yes`, and Zed's formatter on ESLint

## Code Standards

When writing code in a project with Ultracite, follow these standards. For the full rules reference, see [references/code-standards.md](references/code-standards.md).

Key rules at a glance:

Formatting is handled by the project's configured linter/formatter. Respect the repository's existing formatter settings instead of forcing one fixed line width, quote style, or trailing comma policy.

**Type safety:** Use explicit types when they improve clarity. Prefer `unknown` over `any`. Use `as const` for immutable values and rely on type narrowing over blunt assertions.

**Modern JavaScript/TypeScript:** Prefer `const`, destructuring, optional chaining, nullish coalescing, template literals, `for...of`, and concise arrow functions.

**Async and correctness:** Always `await` promises in async functions. Prefer `async/await` over promise chains. Remove `console.log`, `debugger`, and `alert` from production code.

**React and accessibility:** Use function components, keep hooks top-level with correct deps, avoid nested component definitions, and use semantic HTML with the right labels, headings, alt text, and keyboard affordances.

**Organization, security, performance, and testing:** Keep functions focused, prefer early returns, avoid `dangerouslySetInnerHTML` and `eval()`, prefer specific imports and top-level regex, and keep tests free of `.only` and `.skip`.

## Troubleshooting

Run `bunx ultracite doctor` to diagnose. It checks:

1. Linter and formatter installation (Biome; or ESLint + Prettier + Stylelint; or Oxlint + oxfmt)
2. Config validity (extends the ultracite presets correctly)
3. Ultracite in package.json dependencies
4. Conflicting tools when not using the ESLint backend (legacy `.eslintrc.*` files, `.prettierrc.*`/`prettier.config.*`)

Common fixes:

- **Conflicting configs**: After moving to Oxlint or Biome, delete leftover `.eslintrc.*` and `.prettierrc.*` files. On ESLint, `.eslintrc.*` files are inert (ESLint 10 only reads `eslint.config.*`) and `.prettierrc.*` is the formatter's config, so neither is a conflict
- **Missing dependency**: Run `bunx ultracite init` again or manually add `ultracite` to devDependencies
- **Rules not applying**: Ensure config file extends the correct presets for your framework