chore: replace Biome with oxlint, oxfmt and Knip - #17
Open
Thomasims wants to merge 7 commits into
Open
Conversation
Adopts the shared @antelopejs/tooling-configs presets: oxlint with the vendored anti-slop rules, oxfmt for formatting and Knip for dead code. Type-aware linting needs a tsconfig tsgolint accepts, so the removed moduleResolution node10 option goes away. The module stays on commonjs so the emit keeps using require, which is what the AntelopeJS resolver hooks; the compiled output is byte-identical apart from the reordered requires the import sorter produced. The only fixes the linter forced were import order. Knip's one finding is the Logging namespace, exported from src/logging/index.ts both named and as the default: consumers across the ecosystem use both spellings, so the duplicate is published contract. Knip's tag filter does not reach the duplicate-export check, so that issue type is switched off in knip.config.ts with the reason recorded there. No export changes: this package is a contract, so its surface is reachable only from consumers Knip cannot see.
Biome is gone, so the directives suppress nothing. The explanations they carried are kept as plain comments.
Switching the `duplicates` issue type off for the whole repository hid the check everywhere, not just on the one export that needs it. Knip's `ignoreIssues` silences an issue type per path, so the Logging named/default pair is ignored where it lives and any future accidental duplicate export is still reported.
Biome is gone, so they suppressed nothing. AGENTS.md mandates self-documenting code without non-TSDoc comments, so the directives are dropped rather than demoted to plain comments.
Thomasims
marked this pull request as ready for review
September 7, 2026 16:10
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Moves this repository off Biome and onto the shared
@antelopejs/tooling-configspresets, in step with the rest of the ecosystem.
Tooling swap
@biomejs/biomeandbiome.jsonare gone.oxlint(pinned to1.81.0, the version the presets' JS plugin API matches),oxfmt,knip,oxlint-tsgolintandeslint-plugin-perfectionistcome in asdev dependencies.
oxlint.config.ts,oxfmt.config.tsandknip.config.ts, each extendingthe shared preset.
lint→oxlint,lint:fix→oxlint --fix,format→oxfmt .,plus new
format:checkandknip. Every other script is untouched. CI gainspnpm format:checkandpnpm knipnext to the existingpnpm lint, in itsown
ci:commit.The
.github/ISSUE_TEMPLATE/**ignore inoxfmt.config.tsis temporary: thosefiles are Markdown templates with a
.ymlextension, which oxfmt cannot parse.It goes away once
tooling-configs#5 ships
the shared ignore.
tsconfig
Type-aware linting runs through tsgolint, which rejects compiler options
TypeScript 7 removed and auto-discovers each file's
tsconfig.json. The onlyoffender here was
"moduleResolution": "node"(the removednode10), so thefield is dropped; tsgolint only objects to the explicit value, and the default
for
module: "commonjs"is the same resolver, so the emit is unaffected."module": "commonjs"deliberately stays. Raising it tonode16looks like theobvious fix and is a runtime break: tsc would stop downlevelling dynamic imports
and emit native ESM ones, bypassing the CommonJS resolver detour the
ajsruntime installs.
What the linter forced
Import order, and nothing else.
perfectionist(sort-imports)autofixed everyerror;
import(no-cycle)found no cycles in this tree. Nothing was disabled andno rule was silenced. The remaining oxlint output is warnings only
(
no-redundant-type-constituentson the decorator overload unions,unbound-method,no-base-to-string) — the deliberate backlog the presets shipwith, left alone here.
Knip
One real finding:
src/logging/index.tsexports theLoggingnamespace bothnamed and as the default, which Knip reports as a duplicate export. Both
spellings are used by consumers across the ecosystem (
import { Logging } from "@antelopejs/interface-core/logging"andimport Logging from …both appear inshipped modules), so this is published contract, not an oversight. Knip's
tagsfilter does not reach the duplicate-export check, so the issue is silenced by
path in
knip.config.tswithignoreIssues: { "src/logging/index.ts": ["duplicates"] }; the duplicate-exportcheck stays on for the rest of the repository, and the reason is recorded
inline.
No exports were removed. This package is a versioned contract: its surface is
reachable only from consumers Knip cannot see, so an "unused export" here would
never be evidence of dead code.
Verification
distwas built from untouchedorigin/mainand from this branch, and the runtime export keys of every module reachable
through the
exportsmap (.,./config,./logging,./logging/*and the./*wildcard — 11 modules in all) were diffed: identical. The.d.tsfileset is identical too, and the only
.d.tsbyte difference is a reorderedimport line in
modules.d.ts. The compiled.jsdifferences are likewisereordered
requirecalls and nothing else.pnpm teston untouchedorigin/main: 75 passing, 0 failing. Onthis branch: 75 passing, 0 failing.
pnpm test:packagefails identically onboth — it shells out to
corepack, which is not on this machine — so it isenvironmental and pre-existing, not a regression from this change.
pnpm lint,pnpm knipandpnpm buildall exit 0.Commits
The oxfmt pass is its own commit and is recorded in
.git-blame-ignore-revs, sogit blamestays readable. oxfmt also normalizespackage.jsonkey order andsorts
keywords; that is expected.