mrkeyoor.com_
Tue 01 Sept 17:45 UTC
Dev Toolsevaluationupdated 26 Aug 2026

anti-slop review

anti-slop is a set of opinionated Oxlint rules for TypeScript and JavaScript code that throws away type evidence or hides unsafe assumptions. It is distributed as source to vendor into a repository, with a Claude Code compatible agent skill that can copy and configure it.

+241stars / 7d
Verdict

Our anti-slop run installed 11 packages in 25 seconds and passed its tests in 10 seconds, but adoption means owning 15 generic rules as vendored source. Use it when your team agrees with those exact restrictions and will tune false positives instead of accepting them as doctrine. Stay with packaged lint rules if easy upgrades or ESLint compatibility matters more.

We ran it

Lab card: what happened when we ran anti-slopScreenshot of anti-slop (github.com/dmmulroy/anti-slop)
Install✓ · 25s11 packages · 64 MB
Buildn/ano build script
Tests✓ · 10sran, no count parsed
Repo66 files~5,236 lines of source · 0.2 MB · 1 CI workflows

Answers from our run

Does anti-slop build from source?

Dependencies installed in 25 seconds (11 packages), and the project has no separate build step. We cloned commit 6d53855 into a clean Debian container with 3 CPUs and no project-specific setup.

Do anti-slop's tests pass?

The test command failed in our container, and its output did not report a pass or fail count.

Who should not use anti-slop?

ESLint-only teams that cannot add Oxlint: open issue 23 asks for ESLint support, while the README documents only Oxlint and Vite+ configuration.

What are the alternatives to anti-slop?

typescript-eslint, Biome, Oxlint. Our anti-slop run installed 11 packages in 25 seconds and passed its tests in 10 seconds, but adoption means owning 15 generic rules as vendored source.

Setup3/525-second install, but integration means vendoring and config edits
Docs4/5All rules, examples, manual setup, and the agent skill are explained
Community3/53,704 stars and active issue discussion in August 2026
Maturity2/5No releases, with open false-positive and update-path requests

Who it’s for

TypeScript teams already using Oxlint and willing to enforce stricter rules than its standard presets.
Codebase owners who want every non-const type assertion to carry a written safety reason.
Teams comfortable owning a vendored lint plugin and changing its policy when local conventions differ.
Claude Code users who want an agent skill to perform the initial installation.

Who it’s NOT for

ESLint-only teams that cannot add Oxlint: open issue 23 asks for ESLint support, while the README documents only Oxlint and Vite+ configuration.
Teams that want plugin updates through a package manager: the README says to vendor the source, and issue 13 says this makes updates difficult.
Large codebases expecting a low-noise preset: issue 18 found 117 of 150 reports from one rule added no type information in the reporter's monorepo.
Projects whose boundary code legitimately accepts unknown or uses runtime typeof checks widely: those patterns are rejected unless they fit the documented narrow exceptions.

Setup reality

Our sandbox installed 11 pnpm packages in 25 seconds and used 64 MB on disk. There was no build script, so we skipped that step. The tests succeeded in 10 seconds. The commit contained 66 files and about 5,236 source lines.

Using it in another project takes more work than installing those 11 packages. The README tells you to copy the plugin source, install matching current Oxlint packages, merge ignores and plugin entries into the existing config, and enable each rule. The agent skill automates that first pass.

Vendoring is a deliberate maintenance choice: your copy will not update through npm. Effect users also need the separate opt-in plugin, while ESLint users have no documented route. No credentials or hosted services are required.

Fifteen rules enforce one narrow TypeScript philosophy

anti-slop targets code that compiles while discarding information the type checker once knew. Its 15 generic rules reject patterns such as chained assertions, parameters typed as object, contracts returning unknown, module mocking, Reflect.get, and dictionaries whose values use weak types. Another rule requires a safety comment before every non-const assertion. The premise is coherent: make unsafe boundaries explicit and keep precise inferred types intact for as long as possible.

This is policy, not a neutral correctness layer. no-runtime-typeof rejects ordinary narrowing outside type predicates unless its option allows guards. no-module-mocking pushes tests toward dependency seams. no-shape-in-symbol-names even rejects the word shape in identifiers. A team adopting all 15 rules is agreeing to a style of architecture and testing, not merely catching syntax mistakes. Read every rule before letting an installation agent switch them all to errors.

The plugin belongs in your repository, not node_modules

The README explicitly says to vendor the source. Manual setup means copying src/ into a tool directory, installing matching current versions of Oxlint and its plugin package, registering a local TypeScript entry point, merging a list of agent-directory ignores, and enabling the rules. The supplied skill can do that initial work and validate the result. Afterward, the copied files belong to your project.

That choice makes local edits simple. A team can weaken no-runtime-typeof, remove a rule that conflicts with existing boundaries, or add project-specific tests without waiting on an upstream release. It also removes the normal package update path. Open issue 13 asks for an npm package because vendored code is harder to update. There is no latest GitHub release, so buyers cannot use release tags as a clean upgrade ledger either.

What happened when we ran it

Our sandbox installed 11 pnpm packages in 25 seconds and consumed 64 MB on disk. The checkout at commit 6d53855 held 66 files, roughly 5,236 source lines, and measured 0.2 MB before installation. There was no build target, so we skipped the build rather than inventing one. The repository's test command succeeded in 10 seconds.

Those numbers describe the plugin repository, not the cost of applying it to a mature codebase. We did not run its rules across another project or count violations, so our run says nothing about migration volume. The repository has one CI workflow and no Dockerfile or tests directory. The successful command is still useful evidence that the checked-out rule suite completed in a fresh Node 22 Debian container without secrets.

False positives can turn a principle into cleanup work

Open issue 18 gives the most useful adoption evidence. Its reporter ran no-known-value-widening over a 568,000-line TypeScript monorepo and found that 117 of 150 binding-position reports involved Record with a closed union of keys. In those examples, replacing the annotation with satisfies preserved the same missing-key checks and type information. The issue argues that 78 percent of that cohort creates churn without recovering evidence.

Other open reports are narrower but point in the same direction. Issue 29 says unions containing unknown can evade one rule, while issue 24 says an empty SAFETY marker can satisfy the assertion-comment check. Issue 27 reports that a valid safety comment above an exported constant is missed. These are normal problems for young static-analysis rules, yet they matter because anti-slop recommends enabling every generic rule as an error. Trial it on a representative directory before making CI block the whole repository.

Oxlint is required and ESLint support is absent

The configuration examples register JavaScript plugins through Oxlint or Vite+. Open issue 23 asks for ESLint support because some projects cannot replace their current linter. The README offers no ESLint adapter. Teams with custom ESLint rules, editor integrations, or shareable configs must decide whether running a second linter is worth the extra command and configuration.

Effect projects get one additional rule in a separate plugin. It rejects relative imports of exported service constructors outside test files and pushes runtime callers toward the owning Layer and contextual service. Keeping that rule opt-in prevents an Effect architecture preference from affecting ordinary projects. Package imports and static constructors remain outside its scope, which is more careful than applying a name pattern everywhere.

August issue traffic shows interest, not settled behavior

GitHub recorded 3,704 stars, 19 combined open issues and pull requests, and a last push on August 18, 2026 when we fetched the repository. Issue updates continued through August 24, including detailed reports with proposed patches. That is active user scrutiny. It also means several edge cases and distribution questions remain unresolved after the last push.

anti-slop is worth a branch-level trial for teams already unhappy with how easily TypeScript assertions and broad types spread. The 25-second install and 10-second passing test run make inspection cheap. Adoption is the expensive part: review each diagnostic, measure noise in your own code, keep the rules that expose real risk, and accept that your vendored copy is now part of the codebase you maintain.

Alternatives

ProjectWhat it isPick it when
typescript-eslintThe standard ESLint tooling and rule collection for typed TypeScript linting.pick this instead when ESLint compatibility and a packaged plugin ecosystem matter more than anti-slop's narrower policy.
Biome gh↗A formatter and linter with a broad built-in rule set and one-tool workflow.pick this instead when you want maintained defaults without vendoring a custom JavaScript plugin.
Oxlint gh↗The fast linter that anti-slop extends, with its own standard and type-aware rules.pick this instead when the built-in Oxlint rules are enough and you do not want local plugin source.

What people are saying

  1. [velocity-scout] dmmulroy/anti-slop

Sources

  1. anti-slop README
  2. GitHub repository metadata
  3. Issue 18: closed-key Record false positives
  4. Issue 13: npm package request
  5. Issue 23: ESLint support request

More dev tools reviews

workmux · v2rayNG · SecLists · hashcat · eslint · fastfetch · the whole board →