Loading...
Loading...
Catalogue of preferred linter rules, TypeScript flags, and architectural boundary checks for making bug classes and design drift mechanically impossible. Use when setting up linting in a new project, hardening an existing project, responding to a class of bug by encoding a rule, or deciding which linter to reach for on a given stack. Pairs with the `hk` skill which handles wiring hooks.
npx skill4agent add connorads/dotfiles mechanical-enforcementhkstrictno-restricted-importsno-restricted-syntaxfix = true@commitlint/config-conventionalnext/core-web-vitalsreferences/hk| Stack | Formatter | Primary linter | Also | Type-check | Notes |
|---|---|---|---|---|---|
| TypeScript / React / Next | Biome (via Ultracite presets | Biome | ESLint flat config — only for | | Ultracite is the default for new projects. Raw Biome only if Ultracite doesn't support the framework. |
| TypeScript (library / node) | Biome | Biome | — | | Skip ESLint entirely unless you need boundary rules. |
| Python | ruff format | ruff | — | basedpyright strict (or pyright) | |
| Rust | rustfmt | clippy ( | — | | |
| Go | gofmt / gofumpt | golangci-lint | — | | Enable |
| Shell | shfmt | shellcheck | — | — | |
| Markdown | rumdl | rumdl | — | — | Handles frontmatter too. |
| Nix | nixfmt | deadnix + statix | — | — | |
| YAML | — | yamllint | — | — | |
| Commit messages | — | commitlint ( | — | — | One-line config. See |
| Secrets | — | gitleaks | — | — | Always add — cheap, high-signal. |
| Typos | — | typos | — | — | Fast, auto-fixes, tiny false-positive rate. |
| Rule | Encode with | Prevents | Notes |
|---|---|---|---|
| Full strict mode | | Most null/undefined footguns | Non-negotiable. |
Indexed access returns | | | See |
| Dead code fails build | | Drifted imports, zombie variables | Prefix with |
| Only erasable TS syntax | | | Enables deno/bun/swc/esbuild interop without a TS runtime. Breaks existing code using |
No | Biome | Escape hatch from the type system | Use |
No | ESLint | Silent lies to the compiler | Allowed exceptions (document each with |
No | ESLint | Silent runtime crashes | Use a proper null check or throw a narrowed error. |
Prefer | Biome | Accidental runtime imports of type-only modules | Auto-fixable. |
| Rule | Encode with | Prevents | Notes |
|---|---|---|---|
No bare | Biome | Errors disappearing into the void | Narrow in the catch ( |
| No catch-all re-throw without cause | Custom | Losing error context | Required pattern: |
| Prefer Result types at domain boundaries | Convention + review; no linter | Exception-driven control flow in pure code | Exceptions live at the imperative shell only. |
No | Biome | Logs leaking to user consoles | Use the project's logger. |
no-restricted-importsno-restricted-syntaxfiles: ["src/utilities/**"]no-restricted-importsnext/cachenext/headersnext/navigationallowTypeImports: truequeries.tsrevalidate.tsignoresfiles: ["src/components/**"]no-restricted-imports patterns@/collections/*no-restricted-syntaxTaggedTemplateExpression[tag.name='sql']src/db/**ImportDeclaration[source.value='postgres']import()no-restricted-syntaxImportExpressionnext/dynamicReact.lazyreferences/eslint-boundaries.mjs| Rule | Encode with | Prevents | Notes |
|---|---|---|---|
No raw | | Drift from the design system | Exempt the UI library path ( |
| ESLint | Accessibility regressions | Turn off |
| No inline styles | Biome | Design-system bypass | Allow |
| default in Ultracite | Regex recompiled on every call; inline regex in test assertions | Prefer |
| Rule | Encode with | Prevents |
|---|---|---|
| Sorted + grouped imports | Biome | Merge conflicts; inconsistency |
| No cycles | madge ( | Module init-order bugs |
| No default exports (optional) | Biome | Inconsistent naming at import sites; poor rename refactoring. Exempt Next.js pages/layouts where defaults are required. |
| Unique function names | | Duplicate helpers being written instead of discovered. Grep check catches the cross-file case ESLint can't. |
| Rule | Encode with | Prevents |
|---|---|---|
No | Biome | Accidentally skipping the rest of the suite in CI |
| No inline regex in assertions | Biome | Flaky matches and poor error messages |
| Coverage threshold enforced pre-commit | hk step running | Untested branches slipping in. Use |
| No mocks in unit tests | Convention + review | Tests that pass but mask integration bugs |
| Rule | Encode with | Prevents |
|---|---|---|
| No committed secrets | gitleaks pre-commit step | Token leaks |
| Pinned dependencies with quarantine | pnpm | Compromised releases |
No | Documented in project CLAUDE.md / AGENTS.md; not technically preventable | Bypassing the whole gate. Cultural rule — reinforce in every project's agent docs. |
// commitlint.config.js
export default { extends: ["@commitlint/config-conventional"] };commit-msgreferences/hk-steps.pklhkhktier 1 (format/fix) → trailing-whitespace, newlines, typos, rumdl, biome fix
tier 2 (lint/gate) → biome check, eslint, gitleaks, yamllint, check-merge-conflict
tier 3 (typecheck) → tsc --noEmit (or tsgo)
tier 4 (test) → vitest run --coverage
commit-msg → commitlintfix = truestash = "git"references/hk-steps.pklreferences/references/typescript-strict.jsonccompilerOptionsreferences/biome-ultracite.jsoncreferences/eslint-boundaries.mjsno-restricted-importsno-restricted-syntaxreferences/hk-steps.pklreferences/commitlint.config.js