by dmmulroy
Opinionated Oxlint rules for rejecting low-evidence TypeScript and JavaScript patterns
# Add to your Claude Code skills
git clone https://github.com/dmmulroy/anti-slopanti-slop is an open-source ai agents skill for AI coding assistants such as Claude Code, Codex CLI, and ChatGPT, built by dmmulroy. Opinionated Oxlint rules for rejecting low-evidence TypeScript and JavaScript patterns. It has 227 GitHub stars.
anti-slop's catalog security scan is still queued. You can run an instant dependency and prompt-injection check now with the "Scan for vulnerabilities" button above.
Clone the repository with "git clone https://github.com/dmmulroy/anti-slop" and add it to your Claude Code skills directory (see the Installation section above).
anti-slop is primarily written in TypeScript. It is open-source under dmmulroy on GitHub, so you can review or fork the full source.
Yes. SkillsLLM lists many other AI Agents skills you can browse and compare side by side. Open the AI Agents category from the badge at the top of this page, or use the Related Skills and comparison links further down to weigh anti-slop against similar tools.
No comments yet. Be the first to share your thoughts!
Unlocks once the catalog security scan passes (runs nightly).
The deep catalog scan for this skill is still queued. Run an instant dependency check now instead.
Opinionated Oxlint rules that reject low-evidence and low-signal TypeScript and JavaScript patterns.
This project is meant to be vendored, not treated as a fixed npm dependency. Copy the rules into your repository, read them, and change them to match your team's standards. The bundled agent skill handles the initial copy and configuration; after that, the vendored files are yours to maintain and make your own.
npx skills add dmmulroy/anti-slop --skill install-anti-slop
Then ask your coding agent to install or configure anti-slop in the current repository. The skill copies the plugin, installs current Oxlint dependencies, merges the plugin into the existing lint configuration, enables every rule, and validates the result.
To inspect available skills first:
npx skills add dmmulroy/anti-slop --list
Copy src/ into the target repository, for example at tools/oxlint/anti-slop/, and install matching current versions of oxlint and @oxlint/plugins.
Register the copied entry point in oxlint.config.ts:
import { defineConfig } from "oxlint";
export default defineConfig({
jsPlugins: [
{ name: "anti-slop", specifier: "./tools/oxlint/anti-slop/index.ts" },
],
rules: {
"anti-slop/no-chained-type-assertions": "error",
"anti-slop/no-conditional-empty-object-spread": "error",
"anti-slop/no-known-value-widening": "error",
"anti-slop/no-object-parameters": "error",
"anti-slop/no-runtime-typeof": "error",
"anti-slop/no-shape-in-symbol-names": "error",
"anti-slop/no-unknown-parameters": "error",
"anti-slop/no-unknown-type-aliases": "error",
"anti-slop/no-unsafe-dictionary-type": "error",
"anti-slop/no-widen-then-assert": "error"
}
});
The same jsPlugins entry and rules work under lint in a Vite+ config.
no-chained-type-assertions — rejects nested type assertions that fabricate evidence.no-conditional-empty-object-spread — rejects conditional spreads that use {} to omit fields.no-known-value-widening — rejects explicit broad target types that discard known value evidence.no-object-parameters — rejects the broad object type on function inputs.no-runtime-typeof — requires boundary parsing instead of ad hoc typeof narrowing.no-shape-in-symbol-names — rejects shape in symbol names.no-unknown-parameters — rejects unknown inputs except the explicit cause convention.no-unknown-type-aliases — rejects aliases that merely conceal unknown.no-unsafe-dictionary-type — rejects dictionary value contracts based on unknown, any, object, {}, and semantic equivalents.no-widen-then-assert — rejects local flows that widen known values and later assert them back.Each snippet below is rejected by the named rule.
no-chained-type-assertionsconst user = input as object as User;
no-conditional-empty-object-spreadconst options = {
...(timeout !== undefined ? { timeout } : {}),
};
no-known-value-wideningconst handlers: Record<string, Handler> = {
start: startHandler,
};
This discards the known start key. Preserve inference or use satisfies Record<string, Handler> instead.
no-object-parametersfunction save(value: object) {}
no-runtime-typeofif (typeof input === "string") {
useName(input);
}
no-shape-in-symbol-namesinterface UserShape {
id: string;
}
no-unknown-parametersfunction handle(input: unknown) {}
no-unknown-type-aliasestype ExternalValue = unknown;
no-unsafe-dictionary-typetype Metadata = Record<string, unknown>;
type OtherMetadata = { [key: string]: object };
no-widen-then-assertconst loaded: User = loadUser();
const stored: unknown = loaded;
const user = stored as User;
pnpm install
pnpm check
src/ is canonical. After changing production source, run pnpm sync:skill-assets; CI checks that the skill's bundled copy remains identical.
MIT