Skip to content
| Marketplace
Sign in
Visual Studio Code>Linters>LLM Slop DetectorNew to Visual Studio Code? Get it now.
LLM Slop Detector

LLM Slop Detector

thias.se

| (0) | Free
Highlights invisible Unicode, AI-style punctuation, and telltale LLM phrases in markdown and plain text.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

LLM Slop Detector

Install on VS Code Marketplace License: MIT

A VS Code extension and CLI that flag invisible Unicode, AI-style punctuation, and telltale LLM phrases in markdown and plaintext files. The CLI shares its rule engine with the editor, so local and CI findings stay in sync.

LLM Slop Detector in action

Features

  • Flags zero-width, BOM, non-breaking spaces, and other invisible Unicode that hides in text and wrecks diffs
  • Flags AI-style punctuation: em and en dashes, curly quotes, horizontal ellipsis, angle quotes
  • Configurable phrase rules: ~40 built-in core rules plus six opt-in packs (academic, cliches, fiction, claudeisms, structural, security) totalling 285+ curated regex patterns
  • Markdown-aware: skips fenced and inline code, link URLs, and YAML frontmatter so technical prose doesn't drown in false positives
  • Inline-ignore comments (<!-- slop-disable -->, <!-- slop-disable-next-line -->, <!-- slop-disable-line -->) for one-off exceptions
  • Hover over any flagged range for the rule selector plus a ready-to-copy slop-disable-next-line snippet
  • Per-workspace overrides via .llmsloprc.json and per-user overrides via settings
  • One-click quick fixes for deterministic character replacements, plus a "fix all" action
  • Status-bar slop counter for the active file, click to toggle
  • No bundler, no runtime dependencies, no telemetry

Example

The following sentence is intentionally sloppy. Open this README inside VS Code with the extension enabled and the quoted line below should light up with several diagnostics at once -- an em dash, curly quotes, and a handful of telltale LLM phrases:

“It’s worth noting” — we’ll delve into the rich tapestry of ideas.

The em dash and curly quotes have one-click quick fixes. The phrases are flagged for you to reword by hand, because "delve" has no single right replacement.

What it flags

Warnings (yellow): zero-width characters, non-breaking spaces, BOM, line and paragraph separators. Stuff that hides in the text and wrecks diffs.

Info (blue, non-intrusive): em and en dashes, curly quotes, horizontal ellipsis, angle quotes, and a configurable list of phrase regexes like delve, it's worth noting, tapestry of, leverage, etc.

Diagnostics show which rule source flagged a match ([built-in], [your-list-name]) so you can tell where a rule came from.

Quick fixes

Most flagged characters have deterministic fixes available via the lightbulb menu (Cmd/Ctrl+.):

  • zero-width, BOM, joiners: delete
  • no-break / narrow no-break space: regular space
  • line / paragraph separator: newline
  • em dash, en dash: hyphen
  • ellipsis: three dots
  • curly quotes: straight quotes

No default fix for angle quotes (« »), primes (′ ″), or middle dot (·). These are legitimate punctuation in many locales. You can still force a fix via the llmSlopDetector.charReplacements setting.

Phrases have no quick fix by design. No deterministic replacement exists for "delve".

A Fix all LLM slop characters in file action is offered whenever the cursor is on a fixable character diagnostic.

Status bar

Right-aligned status bar item shows the slop count for the active markdown or plaintext file:

  • $(warning) N slop with a warning background when issues exist
  • $(check) No slop when the file is clean
  • $(circle-slash) Slop off when disabled

Click toggles the detector. Hidden when the active editor is a different language.

Scope and ignores

In markdown files, the scanner skips content where slop rules would only produce noise:

  • Fenced code blocks (``` and ~~~) and inline code spans (`foo`)
  • Markdown link URLs ([text](https://github.com/mandakan/llm-slop-detector/blob/HEAD/url) -- the URL part) and autolinks (<https://...>)
  • YAML frontmatter at the top of the file (--- ... --- or --- ... ...)

Link text, headings, and regular paragraphs are still scanned as before. Plain-text files are scanned in full; they have no markdown structure to skip.

Inline ignore comments

For one-off exceptions in either markdown or plaintext, drop an HTML-style directive:

<!-- slop-disable-next-line -->
This line can delve as much as it wants.

Text before <!-- slop-disable-line --> robust tapestry leverage -- all silenced.

<!-- slop-disable -->
Everything between these two markers is silenced,
including multiple paragraphs.
<!-- slop-enable -->

Three forms:

  • <!-- slop-disable-line --> -- silence the line the comment is on.
  • <!-- slop-disable-next-line --> -- silence the line after the comment.
  • <!-- slop-disable --> ... <!-- slop-enable --> -- silence everything between the two directives.

By default a directive silences every rule on the covered range. To scope it to one rule, append a phrase:<pattern> or char:<literal-or-codepoint> spec:

<!-- slop-disable-next-line phrase:\bdelve(s|d|ing)?\b -->
This delve is fine but leverage still gets flagged.

<!-- slop-disable-next-line char:U+2014 -->
Em dashes allowed on this line -- but curly "quotes" still flag.

The phrase: value must match the rule's pattern field exactly (the literal regex string from the rule file, not the matched text). The char: value can be the literal character or a U+XXXX codepoint. Directives inside fenced or inline code are ignored, so README examples like this one don't accidentally silence the whole file.

Source code comments (opt-in)

LLM slop frequently turns up in JSDoc, Python docstrings, Rust /// blocks, and // comments. Turn on llmSlopDetector.scanCodeComments to scan those ranges too:

"llmSlopDetector.scanCodeComments": true,
"llmSlopDetector.codeCommentLanguages": [
  "typescript", "javascript", "python", "rust", "go"
]

Only comments and docstrings are scanned -- identifiers, string literals, and regular code are ignored. Supported language IDs: typescript, javascript, typescriptreact, javascriptreact, python, rust, go, java, csharp, cpp, c, ruby, php, shellscript, swift, kotlin, scala, dart, perl, r, yaml. Unknown IDs are silently ignored.

Known limitations

Comment detection is lexical, not AST-based. This means:

  • Python triple-quoted strings are scanned whether they are docstrings or data. x = """some data with delve""" will flag. If that matters, put the data on the same line as an inline ignore directive, or switch to a regular string.
  • Regex literals in JavaScript (/foo/) aren't specially recognised; odd edge cases like /** @regex /x/ */ can misparse. File an issue if you hit a real false positive.
  • Indented code blocks in Markdown (four-space) are still scanned -- use fenced blocks instead.

If a comment contains a legitimate flagged word, use an inline ignore directive as usual:

/**
 * <!-- slop-disable-next-line phrase:\bdelve(s|d|ing)?\b -->
 * We intentionally delve into the cache layout here because...
 */

Rule packs

The core list is deliberately conservative: ~40 phrase rules covering the buzzwords everyone agrees on (delve, leverage, seamless, paradigm shift, etc.). For more coverage, opt into one or more packs via llmSlopDetector.enabledPacks:

  • academic -- words over-represented in LLM-authored academic writing (bolster, elucidate, facilitate, showcase, noteworthy, ~90 entries). Severity hint so the Problems panel stays usable. Derived from berenslab/llm-excess-vocab (MIT).
  • cliches -- general LLM cliche vocabulary (captivating, pinnacle, galvanize, journey/landscape/symphony metaphors). Derived from nanxstats/llm-cliches (MIT).
  • fiction -- fiction and creative-writing tells (breath hitched, heart hammering, shivers down spine, chestnut eyes, LLM-cliche character names). Includes adult-fiction markers. Derived from SicariusSicariiStuff/SLOP_Detector (Apache-2.0).
  • claudeisms -- Claude-specific mannerisms: sycophantic openers, consent-theater phrasing, "important to note that" hedges. Derived from SLOP_Detector.
  • structural -- structural LLM tells: "not X but Y" negation pivots, sycophantic line openers, "in this section we'll" meta-commentary, "at the end of the day" closers. Original content.
  • security -- LLM-weaponized invisibles above the BMP: tag characters (U+E0020-U+E007F, used in ASCII-smuggler prompt injection) and variation selectors (U+FE00-U+FE0E + U+E0100-U+E01EF, used for arbitrary-data smuggling in emoji and CJK). Severity error. Skips U+FE0F (emoji presentation selector) to avoid false positives. Opt in if you copy-paste LLM output into files you don't fully trust.

Enable one or more in your settings:

"llmSlopDetector.enabledPacks": ["academic", "structural"]

Attribution and license texts for each pack's source are in THIRD_PARTY_NOTICES.md.

Tuning a pack

Packs are merged after the core list, so a pack entry wins if it targets the same char as core. Phrase rules accumulate. If a specific pack rule is too noisy for your writing, either:

  1. Disable the whole pack (remove from enabledPacks), or
  2. Keep the pack enabled and override locally via a .llmsloprc.json file at your workspace root -- a later layer's chars override earlier layers on the same character; phrases are additive, so there's no way to silence a single phrase without forking the pack.

If a whole pack is unusable in your workflow, file an issue.

Configuration

Settings (Cmd/Ctrl+, then search "LLM Slop"):

  • llmSlopDetector.enabled: toggle on/off
  • llmSlopDetector.useBuiltinRules: load the shipped built-in list (default true). Turn off to rely only on local rule files and user settings.
  • llmSlopDetector.enabledPacks: opt-in extra rule packs (see Rule packs). Default: [].
  • llmSlopDetector.phrases: additional regex patterns, appended to the built-in list.
  • llmSlopDetector.charReplacements: override quick-fix replacements per character.

Commands

Cmd/Ctrl+Shift+P:

  • LLM Slop Detector: Toggle: enable/disable
  • LLM Slop Detector: Open settings: jump to this extension's settings filtered by @ext: query
  • LLM Slop Detector: Show loaded rule sources: quick pick listing every active source with name, version, and rule counts
  • LLM Slop Detector: Show onboarding: re-show the onboarding prompt (useful if you dismissed it too early)
  • LLM Slop Detector: Scan selection: list slop findings in the current selection (or the current line if nothing is selected) in a quick pick -- clicking a finding jumps to it. Useful for checking a pasted paragraph without scrolling through every diagnostic in the file.

Rule sources

Rules merge from these layers (later overrides earlier on the same char or pattern):

  1. Built-in core list shipped with the extension
  2. Optional built-in packs listed in llmSlopDetector.enabledPacks
  3. Local .llmsloprc.json in a workspace folder's root (auto-loaded, live-reloaded). Skipped in untrusted workspaces -- see Workspace trust.
  4. User settings

Workspace trust

Local .llmsloprc.json files contain arbitrary regex patterns compiled and executed by the extension. A catastrophic-backtracking pattern in a repo you opened for the first time could hang the extension host. So:

  • In a trusted workspace, all four rule layers load as usual.
  • In an untrusted workspace (VS Code's Restricted Mode), local rule files are skipped. Built-in rules, packs, and user-level settings still apply, so the extension remains useful out of the box.

Trust is granted per-workspace via VS Code's "Manage Workspace Trust" command. The extension listens for trust grants and re-scans open documents when you flip a workspace to trusted.

.llmsloprc.json format

{
  "name": "my-project",
  "version": "1.0.0",
  "description": "Extra phrases for this repo",
  "chars": [
    { "char": "--", "name": "EM DASH", "severity": "information", "replacement": " - " }
  ],
  "phrases": [
    { "pattern": "\\bour pet phrase\\b", "reason": "we banned this" }
  ]
}

Each char rule: char required. name, severity (error | warning | information | hint), replacement, suggestion optional.

Each phrase rule: pattern required. reason, severity optional.

Patterns are JavaScript regex, case-insensitive. Use \\b for word boundaries.

Quick user overrides (no rule file needed)

"llmSlopDetector.phrases": ["\\byour own pet phrase\\b"],
"llmSlopDetector.charReplacements": { "--": " - " }

CLI

The same rule engine ships as a CLI, useful for pre-commit hooks and CI. It produces identical findings to the extension for the same input and config.

llm-slop [options] <paths...>

Paths may be files or directories. Directories are walked recursively; files with extensions .md, .markdown, .mdown, .txt, or .text are scanned. node_modules, out, and dot-prefixed entries are skipped.

Options:

  • -f, --format <pretty|json|sarif> -- output format (default pretty)
  • --pack <name,...> -- enable rule packs (comma-separated)
  • --no-builtin -- skip the built-in core rule list
  • --config <path> -- explicit .llmsloprc.json path (default: nearest ancestor of cwd)
  • -s, --severity <level> -- fail threshold: error | warning | information | hint (default information)
  • --scan-comments -- also scan comments and docstrings in source code files (.ts, .py, .rs, etc). Off by default.
  • -q, --quiet -- suppress the summary line
  • -h, --help / -v, --version

Exit code: 0 if no findings at or above the severity threshold, 1 if any, 2 on argument errors.

Running locally

From a clone:

npm install
npm run compile
./out/cli.js README.md
# or
npm run slop -- README.md

From an installed copy of the extension (the VSIX bundles the CLI): link it globally.

cd ~/.vscode/extensions/thias-se.llm-slop-detector-*
npm link   # optional -- exposes `llm-slop` on PATH

Pre-commit hook

.pre-commit-hooks.yaml ships at the repo root so you can wire it up via pre-commit.com:

repos:
  - repo: https://github.com/mandakan/llm-slop-detector
    rev: v0.4.0
    hooks:
      - id: llm-slop

Pin to a released tag. The hook runs on staged markdown and plaintext files and fails the commit on any finding (override with args: [--severity, error] to only fail on errors).

To also scan source-code comments, extend the hook:

- id: llm-slop
  args: [--scan-comments]
  types_or: [markdown, plain-text, python, typescript, javascript, rust, go]

GitHub Actions

The SARIF output plugs into code-scanning:

- run: npx llm-slop-detector --format=sarif . > slop.sarif
- uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: slop.sarif

Install

From the VS Code Marketplace

Search for LLM Slop Detector in the Extensions view, or:

code --install-extension thias-se.llm-slop-detector

From a GitHub Release

Grab the latest .vsix from Releases, then:

code --install-extension llm-slop-detector-<version>.vsix

From source

git clone https://github.com/mandakan/llm-slop-detector.git
cd llm-slop-detector
npm install
npm run compile
npm run package
code --install-extension llm-slop-detector-*.vsix

Reload VS Code. Open any .md or .txt file. Diagnostics appear in the Problems panel and as squiggles inline.

Alternatives

This extension deliberately overlaps with a few existing tools. If one of these fits your workflow better, use it -- and if you landed here while searching for one of them, what follows is what this adds.

  • Gremlins tracker -- the long-standing VS Code option for surfacing invisible and lookalike characters. General-purpose, not AI-specific, no phrase rules.
  • Invisible AI Character Detector & Remover -- the closest single alternative on the character side. Targets AI-watermark invisibles (zero-widths, BOM, bidi, special spaces). Character-only, no phrase list.
  • Hidden Character Detector -- security framing (ASCII smuggling, prompt-injection payloads) rather than style.
  • LanguageTool Linter -- grammar and style for prose in VS Code. Doesn't target LLM tells specifically.
  • Sloppy Joe and SlopDetector -- web-based paste-in tools for LLM phrase detection. No editor integration.

What this extension combines that the others don't: invisible Unicode and AI-style punctuation and curated LLM phrase packs, all as inline diagnostics on markdown and plaintext, with workspace- and user-level rule overrides.

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2026 Microsoft