anti-slop
An opinionated set of Oxlint rules, copied into your repository rather than installed, that rejects “low-evidence” TypeScript and JavaScript such as unknown parameters, chained type assertions and ad hoc typeof checks.
- What it is
- Linters, formatters and type checkers (linters)
- Part of
- Built on Oxc
- Type
- Open source
- Made by
- Dillon Mulroy (personal project)
- License
- MIT
- Facts checked
- 23 October 2026
What it is
Despite the name, anti-slop checks code, not prose. It is one engineer’s personal rule set, a JavaScript plugin for Oxlint (the linter in the Oxc project), and its README says plainly that it reflects the author’s preferences rather than a universal standard. Most of its 18 generic rules target code that claims more than it can prove: no-chained-type-assertions rejects input as object as User, no-unknown-parameters and no-unknown-returns reject unknown in function contracts, no-runtime-typeof asks for parsing at the boundary instead of scattered typeof checks, and require-safety-comment-for-type-assertion demands a // SAFETY: comment explaining each as. Others reject Jest and Vitest module mocking, Reflect.get, eager filter().map() chains and copying the accumulator inside reduce. A separate opt-in group of five rules covers code written with the Effect library.
There is deliberately no npm package. You copy the src/ folder into your repository, register it under jsPlugins in oxlint.config.ts, and then own and edit the rules; an agent skill (npx skills add dmmulroy/anti-slop) lets a coding agent do the copy, configuration and later three-way-merge updates. The rules use Oxlint’s syntax-tree and scope APIs, not the TypeScript type checker, so they resolve type aliases within one file but can’t see imported types or call signatures from other files.
Why teams pick it
- Pushes TypeScript code toward parsed, explicitly typed boundaries, which catches the casts and
unknownplumbing that slip through ordinary lint rules - Runs at Oxlint speed, with each rule documented by examples of what it rejects and what to write instead
- Vendored on purpose, so a team can read every rule and change the policy to fit
Watch out for
- One person’s taste, not a standard: several rules, such as banning
typeofchecks or module mocking, will clash with many codebases - No npm package: you copy the code (tagged up to v0.1.2) and maintain your copy, and
oxlintand@oxlint/pluginsmust be pinned to the same exact version - Single-file analysis without a type checker, so some patterns across modules go unseen
Two rules from the README: rejected code, then what passes · ts
// no-array-filter-map: two eager passes over the array
const emails = users.filter(user => user.active).map(user => user.email);
// allowed: lazy iterator helpers
const emails2 = users.values().filter(u => u.active).map(u => u.email).toArray();
// require-safety-comment-for-type-assertion
const id = value as UserId; // rejected
// SAFETY: parseUserId validated the identifier before branding it.
const userId = value as UserId; // allowedSee it in a real stack
No architecture uses anti-slop yet. Drop it into the playground and wire it up yourself.Open playground →Where it came from2026
Dillon Mulroy, a software engineer at Cloudflare, extracted the rules he uses with his own work, projects and team into a standalone Oxlint plugin in August 2026 and added an opt-in Effect rule group a week later. The repository has since gathered over 5,000 GitHub stars, and outside contributors have added Effect rules, tests and refinements to the spacing rule.
Why it’s built this way
- Vendor the rules instead of publishing a package
- The rules encode one team’s policy; copying them makes each adopter read and own the policy, and community packages can manage their own releases.
- Build on Oxlint’s JavaScript plugin API
- Rules written in TypeScript against Oxlint’s ESTree and scope APIs run inside the fast Rust linter without a TypeScript type-checking pass.
Timeline
- 2026
August: rules extracted into a standalone Oxlint plugin
- 2026
August: opt-in Effect rules; contributors add more by September
- 2026
October: latest changes to
require-readable-spacing