llm-slop-detector 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +66 -0
- package/LICENSE +21 -0
- package/README.md +429 -0
- package/THIRD_PARTY_NOTICES.md +310 -0
- package/builtin-packs/academic.json +105 -0
- package/builtin-packs/claudeisms.json +47 -0
- package/builtin-packs/cliches.json +57 -0
- package/builtin-packs/fiction.json +88 -0
- package/builtin-packs/security.json +359 -0
- package/builtin-packs/structural.json +31 -0
- package/builtin-rules.json +84 -0
- package/out/cli.js +421 -0
- package/out/core/comments.js +179 -0
- package/out/core/ignore.js +147 -0
- package/out/core/rules.js +301 -0
- package/out/core/scan.js +321 -0
- package/out/core/types.js +10 -0
- package/out/extension.js +607 -0
- package/out/mcp.js +265 -0
- package/out/rules.js +46 -0
- package/package.json +228 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.5.0](https://github.com/mandakan/llm-slop-detector/compare/llm-slop-detector-v0.4.0...llm-slop-detector-v0.5.0) (2026-04-23)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* add "Scan selection" command for one-off checks ([#32](https://github.com/mandakan/llm-slop-detector/issues/32)) ([88ccd41](https://github.com/mandakan/llm-slop-detector/commit/88ccd41ace395bb6cc59b822ed0a626fa4e20dcc))
|
|
9
|
+
* link diagnostics to rule documentation ([#34](https://github.com/mandakan/llm-slop-detector/issues/34)) ([683fefb](https://github.com/mandakan/llm-slop-detector/commit/683fefb0098359baca7e6139362d154ed7364e4a))
|
|
10
|
+
* opt-in scanning of code comments and docstrings ([#30](https://github.com/mandakan/llm-slop-detector/issues/30)) ([cd73cdd](https://github.com/mandakan/llm-slop-detector/commit/cd73cdd701a55d2112ef20f3e254f22e4c8ae547))
|
|
11
|
+
* ship CLI and pre-commit hook sharing the extension's rule engine ([#28](https://github.com/mandakan/llm-slop-detector/issues/28)) ([37575cb](https://github.com/mandakan/llm-slop-detector/commit/37575cb6c2ed2283b3c455d1df486603b489dc5c))
|
|
12
|
+
* show rule selector and ignore snippet on hover ([#33](https://github.com/mandakan/llm-slop-detector/issues/33)) ([6a36158](https://github.com/mandakan/llm-slop-detector/commit/6a36158536eac724654d73fc06e980fe6e6b16ec))
|
|
13
|
+
* skip code fences, link URLs, and ignore directives in markdown ([#26](https://github.com/mandakan/llm-slop-detector/issues/26)) ([26b5f40](https://github.com/mandakan/llm-slop-detector/commit/26b5f40d17b0097a24b727e219b4112af31d5f78))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Bug Fixes
|
|
17
|
+
|
|
18
|
+
* list all six built-in packs in the onboarding toast ([#31](https://github.com/mandakan/llm-slop-detector/issues/31)) ([b3e8c67](https://github.com/mandakan/llm-slop-detector/commit/b3e8c67ed956614173a09677b3fc4923fc15ca32))
|
|
19
|
+
* skip local rule files on untrusted workspaces ([#35](https://github.com/mandakan/llm-slop-detector/issues/35)) ([c0e217e](https://github.com/mandakan/llm-slop-detector/commit/c0e217e206faa73ac01571402f2b97dc501f2f3a))
|
|
20
|
+
|
|
21
|
+
## [0.4.0](https://github.com/mandakan/llm-slop-detector/compare/llm-slop-detector-v0.3.1...llm-slop-detector-v0.4.0) (2026-04-23)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
### Features
|
|
25
|
+
|
|
26
|
+
* add security rule pack for LLM-weaponized invisibles ([b90c4fb](https://github.com/mandakan/llm-slop-detector/commit/b90c4fbfc07f5280acea0b45c4d39be01ded9d7c))
|
|
27
|
+
* expand built-in char set with invisible-char safeguards ([f264cfb](https://github.com/mandakan/llm-slop-detector/commit/f264cfbee2e4c8862b5bcc22d83eaf66694f5b03))
|
|
28
|
+
* expand built-in char set with invisible-char safeguards ([f41945f](https://github.com/mandakan/llm-slop-detector/commit/f41945fcd7f47f8a9238453ad63953e2e0d311be))
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
### Bug Fixes
|
|
32
|
+
|
|
33
|
+
* exclude docs/ from vsix ([40e2292](https://github.com/mandakan/llm-slop-detector/commit/40e2292a27658f44bd5edf081164c7a6de08faa6))
|
|
34
|
+
* exclude docs/ from vsix ([13ad9cb](https://github.com/mandakan/llm-slop-detector/commit/13ad9cb20c81458b5fe64515d241fbb7286d66a4)), closes [#14](https://github.com/mandakan/llm-slop-detector/issues/14)
|
|
35
|
+
|
|
36
|
+
## [0.3.1](https://github.com/mandakan/llm-slop-detector/compare/llm-slop-detector-v0.3.0...llm-slop-detector-v0.3.1) (2026-04-23)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
### Bug Fixes
|
|
40
|
+
|
|
41
|
+
* stop structural negation-pivot from crossing sentence boundaries ([c6aa3cb](https://github.com/mandakan/llm-slop-detector/commit/c6aa3cb3de8b390bb9ab157d9e95722440d72073))
|
|
42
|
+
* stop structural negation-pivot from matching across sentences ([203cac1](https://github.com/mandakan/llm-slop-detector/commit/203cac1c7706d8b99ec77407f41558dfbf3318e2))
|
|
43
|
+
|
|
44
|
+
## [0.3.0](https://github.com/mandakan/llm-slop-detector/compare/llm-slop-detector-v0.2.0...llm-slop-detector-v0.3.0) (2026-04-23)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
### Features
|
|
48
|
+
|
|
49
|
+
* add "Open settings" command ([3de9da1](https://github.com/mandakan/llm-slop-detector/commit/3de9da103a888d251e01df6972b7b438b369e7aa))
|
|
50
|
+
* add opt-in rule packs (academic, cliches, fiction, claudeisms, structural) ([1b7f4bb](https://github.com/mandakan/llm-slop-detector/commit/1b7f4bbf5bd90490fe8ee6331d80947ed68449a0))
|
|
51
|
+
* first-run onboarding toast and README reorder ([e69500d](https://github.com/mandakan/llm-slop-detector/commit/e69500dc86800763c6c2d77b1266715c669d4853))
|
|
52
|
+
* rule packs, onboarding, and marketplace publish prep ([4bb3cce](https://github.com/mandakan/llm-slop-detector/commit/4bb3cce2197ae083d71b2640c066ba559a7bca2b))
|
|
53
|
+
|
|
54
|
+
## [0.2.0](https://github.com/mandakan/llm-slop-detector/compare/llm-slop-detector-v0.1.0...llm-slop-detector-v0.2.0) (2026-04-23)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
### Features
|
|
58
|
+
|
|
59
|
+
* add code action quick fixes for auto-fixable characters ([f57b7d6](https://github.com/mandakan/llm-slop-detector/commit/f57b7d6d08b4153ddfee12817fdb7f595226367f))
|
|
60
|
+
* add status bar indicator with slop count ([5f856e9](https://github.com/mandakan/llm-slop-detector/commit/5f856e9842c777f8f3afa39bc3ab17453fcaf586))
|
|
61
|
+
* layered rule sources with provenance and local rule files ([c0096da](https://github.com/mandakan/llm-slop-detector/commit/c0096dacdfcc112cd1a414eb4077c21e020b36d1))
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
### Bug Fixes
|
|
65
|
+
|
|
66
|
+
* only offer "Fix all" action on fixable char diagnostics ([68ac4c5](https://github.com/mandakan/llm-slop-detector/commit/68ac4c5b31f9c6f3372077e290a8b0372f791486))
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mathias Axell
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
# LLM Slop Detector
|
|
2
|
+
|
|
3
|
+
[](https://marketplace.visualstudio.com/items?itemName=thias-se.llm-slop-detector)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
|
|
6
|
+
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.
|
|
7
|
+
|
|
8
|
+

|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- Flags zero-width, BOM, non-breaking spaces, and other invisible Unicode that hides in text and wrecks diffs
|
|
13
|
+
- Flags AI-style punctuation: em and en dashes, curly quotes, horizontal ellipsis, angle quotes
|
|
14
|
+
- Configurable phrase rules: ~40 built-in core rules plus six opt-in packs (`academic`, `cliches`, `fiction`, `claudeisms`, `structural`, `security`) totalling 285+ curated regex patterns
|
|
15
|
+
- Markdown-aware: skips fenced and inline code, link URLs, and YAML frontmatter so technical prose doesn't drown in false positives
|
|
16
|
+
- Inline-ignore comments (`<!-- slop-disable -->`, `<!-- slop-disable-next-line -->`, `<!-- slop-disable-line -->`) for one-off exceptions
|
|
17
|
+
- Hover over any flagged range for the rule selector plus a ready-to-copy `slop-disable-next-line` snippet
|
|
18
|
+
- Per-workspace overrides via `.llmsloprc.json` and per-user overrides via settings
|
|
19
|
+
- One-click quick fixes for deterministic character replacements, plus a "fix all" action
|
|
20
|
+
- Status-bar slop counter for the active file, click to toggle
|
|
21
|
+
- No bundler, no runtime dependencies, no telemetry
|
|
22
|
+
|
|
23
|
+
## Example
|
|
24
|
+
|
|
25
|
+
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:
|
|
26
|
+
|
|
27
|
+
> “It’s worth noting” — we’ll delve into the rich tapestry of ideas.
|
|
28
|
+
|
|
29
|
+
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.
|
|
30
|
+
|
|
31
|
+
## What it flags
|
|
32
|
+
|
|
33
|
+
**Warnings (yellow):** zero-width characters, non-breaking spaces, BOM, line and paragraph separators. Stuff that hides in the text and wrecks diffs.
|
|
34
|
+
|
|
35
|
+
**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.
|
|
36
|
+
|
|
37
|
+
Diagnostics show which rule source flagged a match (`[built-in]`, `[your-list-name]`) so you can tell where a rule came from.
|
|
38
|
+
|
|
39
|
+
## Quick fixes
|
|
40
|
+
|
|
41
|
+

|
|
42
|
+
|
|
43
|
+
Most flagged characters have deterministic fixes available via the lightbulb menu (`Cmd/Ctrl+.`):
|
|
44
|
+
|
|
45
|
+
- zero-width, BOM, joiners: delete
|
|
46
|
+
- no-break / narrow no-break space: regular space
|
|
47
|
+
- line / paragraph separator: newline
|
|
48
|
+
- em dash, en dash: hyphen
|
|
49
|
+
- ellipsis: three dots
|
|
50
|
+
- curly quotes: straight quotes
|
|
51
|
+
|
|
52
|
+
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.
|
|
53
|
+
|
|
54
|
+
Phrases have no quick fix by design. No deterministic replacement exists for "delve".
|
|
55
|
+
|
|
56
|
+
A **Fix all LLM slop characters in file** action is offered whenever the cursor is on a fixable character diagnostic.
|
|
57
|
+
|
|
58
|
+
## Status bar
|
|
59
|
+
|
|
60
|
+
Right-aligned status bar item shows the slop count for the active `markdown` or `plaintext` file:
|
|
61
|
+
|
|
62
|
+
- `$(warning) N slop` with a warning background when issues exist
|
|
63
|
+
- `$(check) No slop` when the file is clean
|
|
64
|
+
- `$(circle-slash) Slop off` when disabled
|
|
65
|
+
|
|
66
|
+
Click toggles the detector. Hidden when the active editor is a different language.
|
|
67
|
+
|
|
68
|
+
## Scope and ignores
|
|
69
|
+
|
|
70
|
+
In `markdown` files, the scanner skips content where slop rules would only produce noise:
|
|
71
|
+
|
|
72
|
+
- Fenced code blocks (` ``` ` and `~~~`) and inline code spans (`` `foo` ``)
|
|
73
|
+
- Markdown link URLs (`[text](url)` -- the URL part) and autolinks (`<https://...>`)
|
|
74
|
+
- YAML frontmatter at the top of the file (`---` ... `---` or `---` ... `...`)
|
|
75
|
+
|
|
76
|
+
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.
|
|
77
|
+
|
|
78
|
+
### Inline ignore comments
|
|
79
|
+
|
|
80
|
+
For one-off exceptions in either `markdown` or `plaintext`, drop an HTML-style directive:
|
|
81
|
+
|
|
82
|
+
```markdown
|
|
83
|
+
<!-- slop-disable-next-line -->
|
|
84
|
+
This line can delve as much as it wants.
|
|
85
|
+
|
|
86
|
+
Text before <!-- slop-disable-line --> robust tapestry leverage -- all silenced.
|
|
87
|
+
|
|
88
|
+
<!-- slop-disable -->
|
|
89
|
+
Everything between these two markers is silenced,
|
|
90
|
+
including multiple paragraphs.
|
|
91
|
+
<!-- slop-enable -->
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Three forms:
|
|
95
|
+
|
|
96
|
+
- `<!-- slop-disable-line -->` -- silence the line the comment is on.
|
|
97
|
+
- `<!-- slop-disable-next-line -->` -- silence the line after the comment.
|
|
98
|
+
- `<!-- slop-disable -->` ... `<!-- slop-enable -->` -- silence everything between the two directives.
|
|
99
|
+
|
|
100
|
+
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:
|
|
101
|
+
|
|
102
|
+
```markdown
|
|
103
|
+
<!-- slop-disable-next-line phrase:\bdelve(s|d|ing)?\b -->
|
|
104
|
+
This delve is fine but leverage still gets flagged.
|
|
105
|
+
|
|
106
|
+
<!-- slop-disable-next-line char:U+2014 -->
|
|
107
|
+
Em dashes allowed on this line -- but curly "quotes" still flag.
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
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.
|
|
111
|
+
|
|
112
|
+
## Source code comments (opt-in)
|
|
113
|
+
|
|
114
|
+

|
|
115
|
+
|
|
116
|
+
LLM slop frequently turns up in JSDoc, Python docstrings, Rust `///` blocks, and `//` comments. Turn on `llmSlopDetector.scanCodeComments` to scan those ranges too:
|
|
117
|
+
|
|
118
|
+
```json
|
|
119
|
+
"llmSlopDetector.scanCodeComments": true,
|
|
120
|
+
"llmSlopDetector.codeCommentLanguages": [
|
|
121
|
+
"typescript", "javascript", "python", "rust", "go"
|
|
122
|
+
]
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
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.
|
|
126
|
+
|
|
127
|
+
### Known limitations
|
|
128
|
+
|
|
129
|
+
Comment detection is lexical, not AST-based. This means:
|
|
130
|
+
|
|
131
|
+
- **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.
|
|
132
|
+
- 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.
|
|
133
|
+
- Indented code blocks in Markdown (four-space) are still scanned -- use fenced blocks instead.
|
|
134
|
+
|
|
135
|
+
If a comment contains a legitimate flagged word, use an inline ignore directive as usual:
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
/**
|
|
139
|
+
* <!-- slop-disable-next-line phrase:\bdelve(s|d|ing)?\b -->
|
|
140
|
+
* We intentionally delve into the cache layout here because...
|
|
141
|
+
*/
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Rule packs
|
|
145
|
+
|
|
146
|
+
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`:
|
|
147
|
+
|
|
148
|
+
- **`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`](https://github.com/berenslab/llm-excess-vocab) (MIT).
|
|
149
|
+
- **`cliches`** -- general LLM cliche vocabulary (`captivating`, `pinnacle`, `galvanize`, journey/landscape/symphony metaphors). Derived from [`nanxstats/llm-cliches`](https://github.com/nanxstats/llm-cliches) (MIT).
|
|
150
|
+
- **`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`](https://github.com/SicariusSicariiStuff/SLOP_Detector) (Apache-2.0).
|
|
151
|
+
- **`claudeisms`** -- Claude-specific mannerisms: sycophantic openers, consent-theater phrasing, "important to note that" hedges. Derived from SLOP_Detector.
|
|
152
|
+
- **`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.
|
|
153
|
+
- **`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.
|
|
154
|
+
|
|
155
|
+
Enable one or more in your settings:
|
|
156
|
+
|
|
157
|
+
```json
|
|
158
|
+
"llmSlopDetector.enabledPacks": ["academic", "structural"]
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Attribution and license texts for each pack's source are in [`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md).
|
|
162
|
+
|
|
163
|
+
### Tuning a pack
|
|
164
|
+
|
|
165
|
+
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, use `llmSlopDetector.severityOverrides` (see [Severity overrides](#severity-overrides)) to downgrade or disable it from one place, without forking the pack.
|
|
166
|
+
|
|
167
|
+
If a whole pack is unusable in your workflow, file an issue.
|
|
168
|
+
|
|
169
|
+
## Severity overrides
|
|
170
|
+
|
|
171
|
+
`llmSlopDetector.severityOverrides` is a map from a rule selector to a severity level (or `off` to disable the rule entirely). Use it to downgrade a noisy pack, silence one rule, or promote a source that matters more in your repo -- all from a single setting, no fork needed.
|
|
172
|
+
|
|
173
|
+
```json
|
|
174
|
+
"llmSlopDetector.severityOverrides": {
|
|
175
|
+
"pack:academic": "hint",
|
|
176
|
+
"phrase:\\bdelve(s|d|ing)?\\b": "off",
|
|
177
|
+
"char:U+2014": "information",
|
|
178
|
+
"source:built-in": "warning"
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Selectors (same shape as the inline-ignore directive specs):
|
|
183
|
+
|
|
184
|
+
- `pack:<name>` -- every rule from a built-in pack (`pack:academic`, `pack:cliches`, etc.)
|
|
185
|
+
- `phrase:<pattern>` -- matches a phrase rule's `pattern` field exactly. Hover over a flagged phrase to copy its pattern.
|
|
186
|
+
- `char:<literal>` or `char:U+XXXX` -- matches a char rule by literal or codepoint.
|
|
187
|
+
- `source:<name>` -- matches `RuleSource.name` (`built-in`, `pack:academic`, `user settings`, or the `name` field from your `.llmsloprc.json`).
|
|
188
|
+
|
|
189
|
+
Values: `error`, `warning`, `information`, `hint`, or `off`. Invalid values are dropped with a console warning.
|
|
190
|
+
|
|
191
|
+
Precedence: most-specific wins. `phrase:` / `char:` beats `pack:`, which beats `source:`. If two selectors of the same specificity both match (for example `char:—` and `char:U+2014`), the literal form wins.
|
|
192
|
+
|
|
193
|
+
The CLI takes the same settings via a repeatable `--severity-override key=value`:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
llm-slop --severity-override pack:academic=hint --severity-override 'phrase:\bdelve(s|d|ing)?\b=off' README.md
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
The "Show loaded rule sources" command reports how many rules were affected by overrides on a trailing line.
|
|
200
|
+
|
|
201
|
+
## Configuration
|
|
202
|
+
|
|
203
|
+
Settings (Cmd/Ctrl+, then search "LLM Slop"):
|
|
204
|
+
|
|
205
|
+
- `llmSlopDetector.enabled`: toggle on/off
|
|
206
|
+
- `llmSlopDetector.useBuiltinRules`: load the shipped built-in list (default `true`). Turn off to rely only on local rule files and user settings.
|
|
207
|
+
- `llmSlopDetector.enabledPacks`: opt-in extra rule packs (see [Rule packs](#rule-packs)). Default: `[]`.
|
|
208
|
+
- `llmSlopDetector.phrases`: additional regex patterns, appended to the built-in list.
|
|
209
|
+
- `llmSlopDetector.charReplacements`: override quick-fix replacements per character.
|
|
210
|
+
- `llmSlopDetector.scanCommitMessages`: scan Git commit editor buffers (`git-commit`) and the VS Code Source Control input box (`scminput`). Default `true`.
|
|
211
|
+
|
|
212
|
+
## Commands
|
|
213
|
+
|
|
214
|
+
`Cmd/Ctrl+Shift+P`:
|
|
215
|
+
- **LLM Slop Detector: Toggle**: enable/disable
|
|
216
|
+
- **LLM Slop Detector: Open settings**: jump to this extension's settings filtered by `@ext:` query
|
|
217
|
+
- **LLM Slop Detector: Show loaded rule sources**: quick pick listing every active source with name, version, and rule counts
|
|
218
|
+
- **LLM Slop Detector: Show onboarding**: re-show the onboarding prompt (useful if you dismissed it too early)
|
|
219
|
+
- **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.
|
|
220
|
+
|
|
221
|
+
## Rule sources
|
|
222
|
+
|
|
223
|
+
Rules merge from these layers (later overrides earlier on the same char or pattern):
|
|
224
|
+
|
|
225
|
+
1. Built-in core list shipped with the extension
|
|
226
|
+
2. Optional built-in packs listed in `llmSlopDetector.enabledPacks`
|
|
227
|
+
3. Local `.llmsloprc.json` in a workspace folder's root (auto-loaded, live-reloaded). Skipped in untrusted workspaces -- see [Workspace trust](#workspace-trust).
|
|
228
|
+
4. User settings
|
|
229
|
+
|
|
230
|
+
After merging, `llmSlopDetector.severityOverrides` is applied -- it can downgrade or disable any rule from any layer without editing the source. See [Severity overrides](#severity-overrides).
|
|
231
|
+
|
|
232
|
+
### Workspace trust
|
|
233
|
+
|
|
234
|
+
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:
|
|
235
|
+
|
|
236
|
+
- In a **trusted** workspace, all four rule layers load as usual.
|
|
237
|
+
- 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.
|
|
238
|
+
|
|
239
|
+
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.
|
|
240
|
+
|
|
241
|
+
### `.llmsloprc.json` format
|
|
242
|
+
|
|
243
|
+
```json
|
|
244
|
+
{
|
|
245
|
+
"$schema": "https://raw.githubusercontent.com/mandakan/llm-slop-detector/main/schemas/llmsloprc.schema.json",
|
|
246
|
+
"name": "my-project",
|
|
247
|
+
"version": "1.0.0",
|
|
248
|
+
"description": "Extra phrases for this repo",
|
|
249
|
+
"chars": [
|
|
250
|
+
{ "char": "--", "name": "EM DASH", "severity": "information", "replacement": " - " }
|
|
251
|
+
],
|
|
252
|
+
"phrases": [
|
|
253
|
+
{ "pattern": "\\bour pet phrase\\b", "reason": "we banned this" }
|
|
254
|
+
]
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Each char rule: `char` required. `name`, `severity` (`error | warning | information | hint`), `replacement`, `suggestion` optional.
|
|
259
|
+
|
|
260
|
+
Each phrase rule: `pattern` required. `reason`, `severity` optional.
|
|
261
|
+
|
|
262
|
+
Patterns are JavaScript regex, case-insensitive. Use `\\b` for word boundaries.
|
|
263
|
+
|
|
264
|
+
The extension ships a JSON Schema and registers it via `contributes.jsonValidation`, so opening `.llmsloprc.json` in VS Code gives you key completion, hover docs, severity-enum suggestions, and red squigglies on unknown fields or wrong types. The `$schema` line above is optional (VS Code matches by filename) but makes the file self-describing for editors and tools outside VS Code.
|
|
265
|
+
|
|
266
|
+
### Quick user overrides (no rule file needed)
|
|
267
|
+
|
|
268
|
+
```json
|
|
269
|
+
"llmSlopDetector.phrases": ["\\byour own pet phrase\\b"],
|
|
270
|
+
"llmSlopDetector.charReplacements": { "--": " - " }
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
## CLI
|
|
274
|
+
|
|
275
|
+
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.
|
|
276
|
+
|
|
277
|
+
```bash
|
|
278
|
+
llm-slop [options] <paths...>
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+

|
|
282
|
+
|
|
283
|
+
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.
|
|
284
|
+
|
|
285
|
+
Options:
|
|
286
|
+
|
|
287
|
+
- `-f, --format <pretty|json|sarif>` -- output format (default `pretty`)
|
|
288
|
+
- `--pack <name,...>` -- enable rule packs (comma-separated)
|
|
289
|
+
- `--no-builtin` -- skip the built-in core rule list
|
|
290
|
+
- `--config <path>` -- explicit `.llmsloprc.json` path (default: nearest ancestor of cwd)
|
|
291
|
+
- `-s, --severity <level>` -- fail threshold: `error | warning | information | hint` (default `information`)
|
|
292
|
+
- `--severity-override <selector>=<level>` -- override severity for a selector (see [Severity overrides](#severity-overrides)). Repeatable. Level may be `off` to disable.
|
|
293
|
+
- `--scan-comments` -- also scan comments and docstrings in source code files (`.ts`, `.py`, `.rs`, etc). Off by default.
|
|
294
|
+
- `-q, --quiet` -- suppress the summary line
|
|
295
|
+
- `-h, --help` / `-v, --version`
|
|
296
|
+
|
|
297
|
+
Exit code: `0` if no findings at or above the severity threshold, `1` if any, `2` on argument errors.
|
|
298
|
+
|
|
299
|
+
### Install
|
|
300
|
+
|
|
301
|
+
From npm:
|
|
302
|
+
|
|
303
|
+
```bash
|
|
304
|
+
npx llm-slop-detector README.md # one-shot
|
|
305
|
+
npm install -g llm-slop-detector # or put `llm-slop` on PATH
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
From a clone (for hacking on the rules):
|
|
309
|
+
|
|
310
|
+
```bash
|
|
311
|
+
npm install
|
|
312
|
+
npm run compile
|
|
313
|
+
./out/cli.js README.md
|
|
314
|
+
# or
|
|
315
|
+
npm run slop -- README.md
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### Pre-commit hook
|
|
319
|
+
|
|
320
|
+
`.pre-commit-hooks.yaml` ships at the repo root so you can wire it up via [pre-commit.com](https://pre-commit.com/):
|
|
321
|
+
|
|
322
|
+
```yaml
|
|
323
|
+
repos:
|
|
324
|
+
- repo: https://github.com/mandakan/llm-slop-detector
|
|
325
|
+
rev: v0.4.0
|
|
326
|
+
hooks:
|
|
327
|
+
- id: llm-slop
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
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).
|
|
331
|
+
|
|
332
|
+
There's also a `commit-msg` stage hook that scans the commit message itself before it lands:
|
|
333
|
+
|
|
334
|
+
```yaml
|
|
335
|
+
repos:
|
|
336
|
+
- repo: https://github.com/mandakan/llm-slop-detector
|
|
337
|
+
rev: v0.5.0
|
|
338
|
+
hooks:
|
|
339
|
+
- id: llm-slop-commit-msg
|
|
340
|
+
stages: [commit-msg]
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
The CLI recognises `COMMIT_EDITMSG`, `MERGE_MSG`, `TAG_EDITMSG`, and `EDIT_DESCRIPTION` by basename and treats them as `git-commit`: `#` comment lines and the post-scissors (`>8`) diff block are skipped automatically. Use both hooks together or pick the one that fits your workflow.
|
|
344
|
+
|
|
345
|
+
To also scan source-code comments, extend the hook:
|
|
346
|
+
|
|
347
|
+
```yaml
|
|
348
|
+
- id: llm-slop
|
|
349
|
+
args: [--scan-comments]
|
|
350
|
+
types_or: [markdown, plain-text, python, typescript, javascript, rust, go]
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### GitHub Actions
|
|
354
|
+
|
|
355
|
+
The SARIF output plugs into code-scanning:
|
|
356
|
+
|
|
357
|
+
```yaml
|
|
358
|
+
- run: npx llm-slop-detector --format=sarif . > slop.sarif
|
|
359
|
+
- uses: github/codeql-action/upload-sarif@v3
|
|
360
|
+
with:
|
|
361
|
+
sarif_file: slop.sarif
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
## Use from Claude / MCP
|
|
365
|
+
|
|
366
|
+
The same rule engine also ships as a stdio [MCP](https://modelcontextprotocol.io) server, so an agent can scan its own output before writing it to disk. Findings are identical to the CLI for the same input and config.
|
|
367
|
+
|
|
368
|
+
Configure your MCP client (Claude Code, Claude Desktop, etc.):
|
|
369
|
+
|
|
370
|
+
```json
|
|
371
|
+
{
|
|
372
|
+
"mcpServers": {
|
|
373
|
+
"llm-slop": {
|
|
374
|
+
"command": "npx",
|
|
375
|
+
"args": ["-y", "-p", "llm-slop-detector", "llm-slop-mcp"]
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
Pass `--pack`, `--no-builtin`, or `--config` as extra `args`, or set `LLM_SLOP_PACKS`, `LLM_SLOP_NO_BUILTIN`, or `LLM_SLOP_CONFIG` in `env` to match your CLI setup.
|
|
382
|
+
|
|
383
|
+
Tools exposed:
|
|
384
|
+
|
|
385
|
+
- `scan_text` -- `{ text, language?, packs? }` returns an array of findings with `line`, `col`, `endLine`, `endCol`, `code`, `severity`, `message`, `source`, `rulePattern`. `language` defaults to `markdown`; use `plaintext` to scan everything, or a code language id (e.g. `typescript`) to scan only comments. `packs` overrides the server's startup packs for one call.
|
|
386
|
+
- `list_rules` -- `{ source? }` returns loaded sources with rule counts, plus the full char and phrase rule lists, optionally filtered by source name.
|
|
387
|
+
|
|
388
|
+
## Install
|
|
389
|
+
|
|
390
|
+
### From the VS Code Marketplace
|
|
391
|
+
|
|
392
|
+
Search for **LLM Slop Detector** in the Extensions view, or:
|
|
393
|
+
|
|
394
|
+
```bash
|
|
395
|
+
code --install-extension thias-se.llm-slop-detector
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
### From a GitHub Release
|
|
399
|
+
|
|
400
|
+
Grab the latest `.vsix` from [Releases](https://github.com/mandakan/llm-slop-detector/releases), then:
|
|
401
|
+
|
|
402
|
+
```bash
|
|
403
|
+
code --install-extension llm-slop-detector-<version>.vsix
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
### From source
|
|
407
|
+
|
|
408
|
+
```bash
|
|
409
|
+
git clone https://github.com/mandakan/llm-slop-detector.git
|
|
410
|
+
cd llm-slop-detector
|
|
411
|
+
npm install
|
|
412
|
+
npm run compile
|
|
413
|
+
npm run package
|
|
414
|
+
code --install-extension llm-slop-detector-*.vsix
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
Reload VS Code. Open any `.md` or `.txt` file. Diagnostics appear in the Problems panel and as squiggles inline.
|
|
418
|
+
|
|
419
|
+
## Alternatives
|
|
420
|
+
|
|
421
|
+
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.
|
|
422
|
+
|
|
423
|
+
- [**Gremlins tracker**](https://marketplace.visualstudio.com/items?itemName=nhoizey.gremlins) -- the long-standing VS Code option for surfacing invisible and lookalike characters. General-purpose, not AI-specific, no phrase rules.
|
|
424
|
+
- [**Invisible AI Character Detector & Remover**](https://marketplace.visualstudio.com/items?itemName=proflead.invisible-ai-chart-detector) -- the closest single alternative on the character side. Targets AI-watermark invisibles (zero-widths, BOM, bidi, special spaces). Character-only, no phrase list.
|
|
425
|
+
- [**Hidden Character Detector**](https://marketplace.visualstudio.com/items?itemName=YusufDanis.hidden-character-detector) -- security framing (ASCII smuggling, prompt-injection payloads) rather than style.
|
|
426
|
+
- [**LanguageTool Linter**](https://marketplace.visualstudio.com/items?itemName=davidlday.languagetool-linter) -- grammar and style for prose in VS Code. Doesn't target LLM tells specifically.
|
|
427
|
+
- [**Sloppy Joe**](https://sloppyjoe.io/) and [**SlopDetector**](https://slopdetector.org/) -- web-based paste-in tools for LLM phrase detection. No editor integration.
|
|
428
|
+
|
|
429
|
+
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.
|