npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

slopcatcher

v1.0.0

Published

Catch LLM slop patterns in your source files

Readme

slopcatcher

Catch LLM slop patterns before they ship.

Agentic coding is the new normal. The side effect: codebases filling up with defensive fallbacks, swallowed errors, stub log calls, and over-engineered null guards that exist because the model didn't trust the data model it was given. slopcatcher is a static analysis CLI that flags these patterns at the file level so you catch them in review — or in CI before they ever merge.

npx slopcatcher src/usecases/alertDispatch.js

The problem

This is slop:

// Why does a business rule need a fallback to []?
// If contactGroupIds is absent, that's a DATA bug — fix the schema.
const contactGroupIds = rule.contactGroupIds ?? [];

// Why is this catch returning null?
// Callers think this succeeded. It didn't.
} catch {
  return { name: null, provider: null };
}

// Why is a service being constructed inside a constructor?
// This class is now impossible to test without a real DatabaseService.
this.databaseService = new DatabaseService(firestoreRepository);

// Why is there a log that says "would send"?
// Either send it or delete this code path.
logExec(`Email stub: would send to ${contact.email}`);

LLMs generate this because they optimise for "the code runs" not "the code is correct". slopcatcher treats these patterns as the errors they are.


Installation

# Global install
npm install -g slopcatcher

# Or use without installing
npx slopcatcher src/usecases/alertDispatch.js

Usage

# Single file
slopcatcher src/usecases/alertDispatch.js

# Multiple files
slopcatcher src/**/*.js

# JSON output (for tooling)
slopcatcher --json src/usecases/alertDispatch.js

# Filter by minimum severity
slopcatcher --min-severity error src/usecases/alertDispatch.js

Exit code 0 = clean. Exit code 1 = slop found. Drop it in CI and it becomes a gate.


Rules

| Rule | Severity | What it flags | |------|----------|---------------| | constructor-service-init | error | new Service() inside a constructor. Inject your dependencies — don't build them. | | unnecessary-fallbacks | error | ?? [] / ?? {} / ?? null on business data. If that value can be absent, fix the data model. | | swallowed-errors | error | catch blocks that return null or empty instead of throwing. Callers deserve to know something failed. | | stub-code | warn | Log calls containing "would send", "stub", TODO, FIXME. Stubs have no place in production logic. | | optional-chain-overdose | warn | ?. chains 3+ levels deep. If the shape is guaranteed, drop the guards. If it isn't, fix the contract. | | magic-timeout | warn | Raw number literals passed to setTimeout / setInterval. Extract to a named constant. | | jsdoc-slop | info | JSDoc @param descriptions that just restate the parameter name word-for-word. |


Adding rules

Each rule is a module in src/rules/ that follows the Babel visitor pattern:

// src/rules/my-rule.js
module.exports = {
  meta: {
    id: "my-rule",
    description: "What this rule catches",
    severity: "warn", // "error" | "warn" | "info"
  },
  create({ addFinding }) {
    return {
      CallExpression(path) {
        // Inspect the AST node
        addFinding({
          rule: "my-rule",
          message: "Explain what's wrong and how to fix it.",
          severity: "warn",
          line: path.node.loc.start.line,
          column: path.node.loc.start.column,
        });
      },
    };
  },
};

Register it in src/rules/index.js:

module.exports = [
  // ...existing rules
  require("./my-rule"),
];

Philosophy

If a value can be absent, that's a data-model bug — not something JavaScript needs to paper over.

slopcatcher takes a deliberate stance: defensive fallbacks on business logic are wrong. An EmailService either exists or the code shouldn't be running. A contactGroupIds array either has a schema guarantee or that schema needs to be fixed. Masking those problems with ?? [] doesn't make the code safer — it makes failures silent and harder to trace.

New patterns will be added as the field of LLM slop matures.