Skip to content
brix.v2 stable

Search documentation

70 guides

Documentation menu
Docs / Project toolingRead Markdown ↗

Linting and formatting

Brix manages Oxfmt, Oxlint, type-aware linting, and Brix-specific rules as one versioned project policy. Use brix format to write formatting changes and brix check to verify formatting, lint, types, and project structure. Do not install or invoke the underlying tools separately.

Keep native configuration files

A standalone project keeps oxfmt.config.mts and oxlint.config.mts at its root. They call helpers from the exact installed Brix version, so command-line checks and the official Oxc editor extension use the same baseline:

oxfmt.config.mts
import { defineBrixOxfmtConfig } from "brix/config";

export default defineBrixOxfmtConfig();
oxlint.config.mts
import { defineBrixOxlintConfig } from "brix/config";

export default defineBrixOxlintConfig();

Keep these executable native configs. Do not move formatting or lint options into vite.config.ts, replace the helpers with copied defaults, or add legacy .oxfmtrc.json and .oxlintrc.json files. Brix maintains the project-local Oxc declarations needed by editors; select Oxc as the formatter in personal editor settings rather than committing editor preferences for the team.

defineBrixOxfmtConfig accepts native Oxfmt options, appends project ignores after the managed **/dist/** and **/.brix/** ignores, and preserves project overrides. defineBrixOxlintConfig accepts native Oxlint categories and options; project rules merge over managed rules, jsPlugins append without removing Brix's plugin, and project ignores and overrides follow the managed ones.

Understand the managed lint baseline

The baseline enforces ordinary correctness and type-aware checks plus application architecture. It rejects direct imports of framework-owned dependencies, CommonJS require(), Brix test entry points in production modules, and parent-relative imports from src/features/**. Tests may import from brix/test; application code should use the supported brix/* facades. brix doctor additionally checks imports, exports, statically known dynamic imports, and require() calls, so lint is not a substitute for diagnosis.

Five Brix rules are errors by default:

  • brix/no-unknown-type-aliases keeps genuinely untrusted values visibly unknown until validated.
  • brix/no-widen-then-assert prevents erasing a known immutable value's type and asserting it back.
  • brix/no-reflect-get prefers typed property access over Reflect.get.
  • brix/no-reflect-apply prefers typed calls over Reflect.apply.
  • brix/no-module-mocking prevents Vitest or Jest module replacement, including through brix/test.

Runtime validation, unknown boundary parameters, typeof, vi.fn, and vi.spyOn remain valid. For tests, exercise routes through the route harness, mock HTTP consumed by clients with MSW, or use an existing dependency-injection seam instead of replacing a module.

Optional project-policy rules use the same brix/ prefix: no-chained-type-assertions, no-conditional-empty-object-spread, no-known-value-widening, no-object-parameters, no-runtime-typeof, no-shape-in-symbol-names, no-unknown-parameters, no-unknown-returns, no-unsafe-dictionary-type, and require-safety-comment-for-type-assertion. They are not managed defaults; enable only rules that express a deliberate team policy.

Configure shared policy and scoped exceptions

Pass native options to the helper. Prefer overrides when policy applies only to particular code:

oxlint.config.mts
import { defineBrixOxlintConfig } from "brix/config";

export default defineBrixOxlintConfig({
  rules: { "no-console": "error" },
  overrides: [
    {
      files: ["src/domain/**/*.ts"],
      rules: { "brix/no-unsafe-dictionary-type": "error" },
    },
    {
      files: ["scripts/**/*.ts"],
      rules: { "no-console": "off" },
    },
  ],
});

Globs are relative to the config file. A genuine one-statement exception should be narrower than an override and explain the invariant it preserves:

// eslint-disable-next-line brix/no-reflect-get -- Preserve the receiver supplied to this proxy accessor.
return Reflect.get(target, key, receiver);

Keep regression coverage for such exceptions. Avoid blanket file exclusions and comments that only claim an assertion or mock is safe. A deliberate project-wide rule change is supported, but turning off a managed rule globally should be rarer than a local, reasoned exception.

Oxfmt options and ignore patterns follow the same root-relative ownership model:

oxfmt.config.mts
import { defineBrixOxfmtConfig } from "brix/config";

export default defineBrixOxfmtConfig({
  singleQuote: true,
  ignorePatterns: ["generated/**"],
});

Use the exact option names supported by the Brix-pinned Oxfmt version. Keep generated output ignored rather than formatting it by hand.

Configure a workspace at the root

A workspace root owns .node-version, oxfmt.config.mts, oxlint.config.mts, local Oxc tools, managed skills, and Git hooks. Members inherit them and should not contain generated copies. Put shared decisions in the root configs and use workspace-relative globs for member-specific policy:

oxlint.config.mts
import { defineBrixOxlintConfig } from "brix/config";

export default defineBrixOxlintConfig({
  overrides: [
    {
      files: ["apps/admin/src/**/*.ts", "apps/admin/src/**/*.tsx"],
      rules: { "no-console": "error" },
    },
    {
      files: ["packages/generated-contracts/src/**/*.ts"],
      rules: { "brix/no-unknown-type-aliases": "off" },
    },
  ],
});

Open the workspace root in the editor so it discovers the shared configs and binaries. Add a member config only when a tool genuinely needs a separate boundary. A local config replaces ancestor discovery; it does not automatically extend the root. Keep the Brix helper and explicitly compose any root options the member must retain. Member brix init and workspace upgrades remove only unchanged generated member configs and matching Node pins; customized files remain untouched.

Git hook policy likewise belongs only at the Git root under .brix-hooks/. brix hooks enable and brix hooks disable control dispatch for the current clone. The standard pre-commit hook runs brix staged against the exact index without rewriting unstaged work.

Run and repair checks

brix format
brix check
brix doctor
brix hooks status
brix staged

Format first, review the diff, and stage the intended result. brix check never applies formatter or linter fixes. In a workspace, root commands cover all members; focused commands such as brix check#checkout-bff select one project while still preparing its shared libraries. Hooks are early feedback only—brix verify and CI remain authoritative.

Continue with project structure, testing, and workspaces.