zero-slop 2.8.11 → 2.9.1
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/.mcp.json +8 -0
- package/README.md +15 -38
- package/SKILL.md +1 -1
- package/gemini-extension.json +12 -0
- package/mcp.json +9 -0
- package/package.json +7 -1
- package/plugin.json +14 -0
- package/scripts/rescue.py +32 -27
package/.mcp.json
ADDED
package/README.md
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
<p align="center">
|
|
2
2
|
<a href="https://zero-slop.ai">
|
|
3
|
-
<img src="assets/logo/
|
|
3
|
+
<img src="assets/logo/studio/zero-slop-mark-300-transparent.png" width="112" alt="Zero Slop">
|
|
4
4
|
</a>
|
|
5
5
|
</p>
|
|
6
6
|
|
|
7
|
+
Zero Slop crossed 100 GitHub stars and 2,000 npm downloads in its first 12 days.
|
|
8
|
+
|
|
7
9
|
<h1 align="center">Zero Slop</h1>
|
|
8
10
|
|
|
9
11
|
<p align="center"><strong>Find AI-sounding writing. Keep the source intact.</strong></p>
|
|
@@ -25,7 +27,7 @@
|
|
|
25
27
|
|
|
26
28
|
<p align="center">
|
|
27
29
|
<a href="https://github.com/manavmishra/ZeroSlop/actions/workflows/validate.yml"><img alt="Validate" src="https://github.com/manavmishra/ZeroSlop/actions/workflows/validate.yml/badge.svg"></a>
|
|
28
|
-
<img alt="Version 2.
|
|
30
|
+
<img alt="Version 2.9.1" src="https://img.shields.io/badge/version-2.9.1-72528F">
|
|
29
31
|
<a href="https://www.npmjs.com/package/zero-slop"><img alt="npm version" src="https://img.shields.io/npm/v/zero-slop?color=72528F"></a>
|
|
30
32
|
<a href="https://www.npmjs.com/package/zero-slop"><img alt="npm downloads" src="https://img.shields.io/npm/dm/zero-slop?color=227B5B"></a>
|
|
31
33
|
<a href="https://github.com/manavmishra/ZeroSlop/stargazers"><img alt="GitHub stars" src="https://img.shields.io/github/stars/manavmishra/ZeroSlop?style=flat&color=b0442a"></a>
|
|
@@ -37,15 +39,15 @@
|
|
|
37
39
|
npx skills add manavmishra/ZeroSlop --global
|
|
38
40
|
```
|
|
39
41
|
|
|
40
|
-
<a href="assets/zero-slop-demo.mp4">
|
|
42
|
+
<a href="assets/zero-slop-demo.mp4?v=dark-shell-restored-20260906">
|
|
41
43
|
<picture>
|
|
42
|
-
<source media="(prefers-reduced-motion: reduce)" srcset="assets/zero-slop-demo-poster.png">
|
|
43
|
-
<source type="image/webp" srcset="assets/zero-slop-demo.webp">
|
|
44
|
-
<img src="assets/zero-slop-demo.gif" width="
|
|
44
|
+
<source media="(prefers-reduced-motion: reduce)" srcset="assets/zero-slop-demo-poster.png?v=dark-shell-restored-20260906">
|
|
45
|
+
<source type="image/webp" srcset="assets/zero-slop-demo.webp?v=dark-shell-restored-20260906">
|
|
46
|
+
<img src="assets/zero-slop-demo.gif?v=dark-shell-restored-20260906" width="900" alt="Dark-shell demo: install Zero Slop, edit with your assistant, and check scores while preserving 40%.">
|
|
45
47
|
</picture>
|
|
46
48
|
</a>
|
|
47
49
|
|
|
48
|
-
<p align="center"><a href="assets/zero-slop-demo.mp4">
|
|
50
|
+
<p align="center"><a href="assets/zero-slop-demo.mp4?v=dark-shell-restored-20260906">Watch the 15-second shell demo</a> · <sub>The original demo uses a longer sample than the example below.</sub></p>
|
|
49
51
|
|
|
50
52
|
## Before and after
|
|
51
53
|
|
|
@@ -81,32 +83,14 @@ Zero Slop is a writing tool. It does not detect authorship; its score describes
|
|
|
81
83
|
|
|
82
84
|
To try Zero Slop first, paste a draft into [zero-slop.ai/try](https://zero-slop.ai/try/). The free editor returns the edit, the before-and-after scores, and the exact phrases that triggered the scorer.
|
|
83
85
|
|
|
84
|
-
The portable installer works with Claude Code, Codex, Cursor, OpenCode, Warp, Zed, and other Agent Skills-compatible tools:
|
|
85
|
-
|
|
86
|
-
```sh
|
|
87
|
-
npx skills add manavmishra/ZeroSlop --global
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
Or use the package-specific installer and scoring command:
|
|
91
|
-
|
|
92
|
-
```sh
|
|
93
|
-
npx zero-slop install
|
|
94
|
-
npx zero-slop score draft.md
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
Choose a harness explicitly when needed:
|
|
98
|
-
|
|
99
|
-
```sh
|
|
100
|
-
npx zero-slop install --harness codex
|
|
101
|
-
# claude | codex | cursor | opencode | zed
|
|
102
|
-
```
|
|
103
|
-
|
|
104
86
|
| Environment | Fastest route |
|
|
105
87
|
|---|---|
|
|
106
88
|
| Claude Code, Codex, Cursor, OpenCode, Warp, Zed | `npx skills add manavmishra/ZeroSlop --global` |
|
|
89
|
+
| Gemini CLI | `gemini extensions install https://github.com/manavmishra/ZeroSlop --auto-update` |
|
|
90
|
+
| Claude Code plugin | `/plugin marketplace add manavmishra/ZeroSlop`, then `/plugin install zero-slop@zero-slop` |
|
|
107
91
|
| Any assistant with file uploads | Download the [single-file bundle](https://github.com/manavmishra/ZeroSlop/releases/latest/download/zero-slop-single-file.md) |
|
|
108
92
|
| Claude.ai | Upload the [latest skill ZIP](https://github.com/manavmishra/ZeroSlop/releases/latest/download/zero-slop.zip) |
|
|
109
|
-
| ChatGPT or another MCP client | Connect the optional [hosted MCP server](mcp/README.md) |
|
|
93
|
+
| ChatGPT, Claude, Grok, Gemini, Cursor, or another MCP client | Connect the optional [hosted MCP server](mcp/README.md) |
|
|
110
94
|
|
|
111
95
|
Once installed, ask your AI assistant to edit a draft:
|
|
112
96
|
|
|
@@ -142,15 +126,7 @@ Connect the [Zero Slop MCP](https://zero-slop.ai/#mcp) once to edit drafts insid
|
|
|
142
126
|
https://mcp.zero-slop.ai/mcp
|
|
143
127
|
```
|
|
144
128
|
|
|
145
|
-
|
|
146
|
-
# Codex
|
|
147
|
-
codex mcp add zero-slop --url https://mcp.zero-slop.ai/mcp
|
|
148
|
-
|
|
149
|
-
# Claude Code
|
|
150
|
-
claude mcp add --transport http zero-slop --scope user https://mcp.zero-slop.ai/mcp
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
Follow the [MCP setup guide](https://zero-slop.ai/#mcp) for ChatGPT and other clients.
|
|
129
|
+
See [`DISTRIBUTION.md`](DISTRIBUTION.md) for direct connector commands and directory status.
|
|
154
130
|
|
|
155
131
|
## What the workflow adds
|
|
156
132
|
|
|
@@ -249,7 +225,7 @@ stress case took 2.2932 seconds, and learning from an 8,000-word edit took
|
|
|
249
225
|
0.1592 seconds. The measurements and machine details are in
|
|
250
226
|
[`bench/performance-results.json`](bench/performance-results.json).
|
|
251
227
|
|
|
252
|
-
Across 12 interleaved runs against 2.7.7, we measured 0.
|
|
228
|
+
Across 12 interleaved runs against 2.7.7, we measured 0.17% lower median throughput,
|
|
253
229
|
which is effectively unchanged. The separate two-way replay used
|
|
254
230
|
Zero Slop v2.6.0.
|
|
255
231
|
|
|
@@ -299,6 +275,7 @@ learn cadence, tone, or a complete writing style.
|
|
|
299
275
|
| [`examples/`](examples/) | Reproducible before-and-after edits |
|
|
300
276
|
| [`bench/`](bench/) | Frozen benchmarks, provenance, and limitations |
|
|
301
277
|
| [`mcp/`](mcp/) | Optional hosted MCP server documentation |
|
|
278
|
+
| [`DISTRIBUTION.md`](DISTRIBUTION.md) | Direct installs, marketplace submissions, and release synchronization |
|
|
302
279
|
|
|
303
280
|
## Contributing and support
|
|
304
281
|
|
package/SKILL.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: zero-slop
|
|
3
3
|
license: MIT
|
|
4
4
|
metadata:
|
|
5
|
-
version: "2.
|
|
5
|
+
version: "2.9.1"
|
|
6
6
|
author: manavmishra
|
|
7
7
|
description: Turn drafts into sharp, natural prose or inspect them without rewriting. Zero Slop runs inside the user's existing AI assistant; Claude, GPT, or another compatible model reads and edits in context while local tools point to exact phrases and protect the source. Use when the user asks to humanize or de-slop writing, inspect AI-sounding patterns, fix text that reads like ChatGPT, polish outward-facing prose, draft social or LinkedIn content, or apply a final quality check to prose the agent generated. The workflow preserves facts, voice, and format and learns privately from repeated, reason-labelled human edits.
|
|
8
8
|
---
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "zero-slop",
|
|
3
|
+
"version": "2.9.1",
|
|
4
|
+
"description": "Find and fix canned AI writing while preserving the facts, voice, and format.",
|
|
5
|
+
"mcpServers": {
|
|
6
|
+
"zero-slop": {
|
|
7
|
+
"httpUrl": "https://mcp.zero-slop.ai/mcp",
|
|
8
|
+
"includeTools": ["deslop"],
|
|
9
|
+
"timeout": 45000
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
package/mcp.json
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zero-slop",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.9.1",
|
|
4
4
|
"description": "An Agent Skill that scores AI-sounding prose locally, guides the host AI through an editorial rewrite, and checks changed source details. The local tools run offline with zero dependencies.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"zero-slop": "bin/zero-slop.mjs"
|
|
@@ -42,11 +42,17 @@
|
|
|
42
42
|
"data/",
|
|
43
43
|
"README.md",
|
|
44
44
|
"LICENSE",
|
|
45
|
+
"plugin.json",
|
|
46
|
+
"mcp.json",
|
|
47
|
+
".mcp.json",
|
|
48
|
+
"gemini-extension.json",
|
|
45
49
|
"!scripts/build_bundle.py",
|
|
46
50
|
"!scripts/build_onepager_pdf.py",
|
|
47
51
|
"!scripts/build_plugin.py",
|
|
48
52
|
"!scripts/build_skill_zip.py",
|
|
49
53
|
"!scripts/check_svg.py",
|
|
54
|
+
"!scripts/check_distribution_manifests.py",
|
|
55
|
+
"!scripts/check_release_version.py",
|
|
50
56
|
"!scripts/check_release_surfaces.py",
|
|
51
57
|
"!scripts/contextual.py",
|
|
52
58
|
"!scripts/contextual-signals.md",
|
package/plugin.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
|
|
3
|
+
"name": "zero-slop",
|
|
4
|
+
"version": "2.9.1",
|
|
5
|
+
"description": "Find and fix canned AI writing while preserving the facts, voice, and format.",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "Manav Mishra",
|
|
8
|
+
"url": "https://github.com/manavmishra"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://zero-slop.ai/",
|
|
11
|
+
"repository": "https://github.com/manavmishra/ZeroSlop",
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"keywords": ["writing", "editing", "ai-slop", "agent-skill", "mcp"]
|
|
14
|
+
}
|
package/scripts/rescue.py
CHANGED
|
@@ -24,12 +24,13 @@ PROTECTED = re.compile(
|
|
|
24
24
|
TOKEN = re.compile(r"\ue000(\d+)\ue001")
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
def
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
def _without_wrapper(match: re.Match[str]) -> str:
|
|
28
|
+
prefix, word = match.group(1), match.group(2)
|
|
29
|
+
# Capitalize the exposed sentence, but leave names such as iOS and eBay
|
|
30
|
+
# byte-for-byte. This applies only where a sentence wrapper was removed.
|
|
31
|
+
if word.islower():
|
|
32
|
+
word = word[:1].upper() + word[1:]
|
|
33
|
+
return prefix + word
|
|
33
34
|
|
|
34
35
|
|
|
35
36
|
def rescue_text(text: str) -> str:
|
|
@@ -43,6 +44,11 @@ def rescue_text(text: str) -> str:
|
|
|
43
44
|
|
|
44
45
|
masked = PROTECTED.sub(mask, original)
|
|
45
46
|
out = re.sub(r"[\u00a0\u202f]", " ", masked)
|
|
47
|
+
out = re.sub(
|
|
48
|
+
r"(^|[.!?][ \t]+|\n[ \t]*)(?:it is important to note that|it is worth noting that)"
|
|
49
|
+
r"[ \t]+([A-Za-z][A-Za-z0-9_-]*)",
|
|
50
|
+
_without_wrapper, out, flags=re.IGNORECASE,
|
|
51
|
+
)
|
|
46
52
|
rules: list[tuple[str, str | object]] = [
|
|
47
53
|
(
|
|
48
54
|
r"\bwe are thrilled to unveil ([^,\n]+),\s+a transformative release that "
|
|
@@ -69,8 +75,8 @@ def rescue_text(text: str) -> str:
|
|
|
69
75
|
(r"\bour journey\b", "our work"),
|
|
70
76
|
(r"\bour transformative journey\b", "our work"),
|
|
71
77
|
(r"\bin today'?s rapidly evolving (?:landscape|world)\b", "Today"),
|
|
72
|
-
(r"\bit is important to note that\b", ""),
|
|
73
|
-
(r"\bit is worth noting that\b", ""),
|
|
78
|
+
(r"\bit is important to note that\b[ \t]*", ""),
|
|
79
|
+
(r"\bit is worth noting that\b[ \t]*", ""),
|
|
74
80
|
(r"\bwhat we did not realize was just how deeply it impacted everything downstream\.",
|
|
75
81
|
"We underestimated its effect on the work that followed."),
|
|
76
82
|
(r"\bonboarding is not a checklist\.\s*it is a promise\.",
|
|
@@ -88,34 +94,33 @@ def rescue_text(text: str) -> str:
|
|
|
88
94
|
lambda m: m.group(1).upper()),
|
|
89
95
|
(r"\bthe results speak for themselves\.\s*", ""),
|
|
90
96
|
(r"\bbut here is the thing nobody talks about\.\s*", ""),
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
(r"\bthe real win isn['’]t just ([^.]+)\.\s*it['’]s ([^.]+)\.",
|
|
94
|
-
lambda m: _sentence_pair(m, past=False)),
|
|
97
|
+
# A contrast may carry a substantive position. A local rule cannot
|
|
98
|
+
# infer that the thing rejected in the source nevertheless mattered.
|
|
95
99
|
(r"\bthat is the kind of impact that keeps us going\b", "That result keeps us going"),
|
|
96
|
-
(r"\
|
|
97
|
-
|
|
100
|
+
(r"\bseamlessly (integrates?)\b",
|
|
101
|
+
lambda m: m.group(1).capitalize() if m.group(0)[0].isupper() else m.group(1)),
|
|
98
102
|
(r"\bjust how deeply\b", "how much"),
|
|
99
103
|
(r"\bgame[-\u2011]changing\b", "useful"),
|
|
100
104
|
(r"\bcutting[-\u2010\u2011 ]edge\b", "current"),
|
|
101
105
|
(r"\bredefines what(?:['’]s| is) possible in\b", "updates"),
|
|
102
106
|
(r"\bin order to\b", "to"),
|
|
103
107
|
(r"\bat the end of the day\b", "ultimately"),
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
(r"\bwe do not\b", "we don't"),
|
|
107
|
-
(r"\bi am\b", "I'm"),
|
|
108
|
-
(r"\bit is\b", "it's"),
|
|
109
|
-
(r"\bthey are\b", "they're"),
|
|
110
|
-
(r"\byou are\b", "you're"),
|
|
111
|
-
(r"\bthere is\b", "there's"),
|
|
112
|
-
(r"\bdoes not\b", "doesn't"),
|
|
113
|
-
(r"\bis not\b", "isn't"),
|
|
114
|
-
(r"\bare not\b", "aren't"),
|
|
115
|
-
(r"\bcannot\b", "can't"),
|
|
108
|
+
# Contractions alone are not evidence of better writing. Leave clean
|
|
109
|
+
# source sentences unchanged instead of manufacturing an edit.
|
|
116
110
|
]
|
|
117
111
|
for pattern, replacement in rules:
|
|
118
|
-
|
|
112
|
+
def replace(match: re.Match[str]) -> str:
|
|
113
|
+
if callable(replacement):
|
|
114
|
+
return replacement(match)
|
|
115
|
+
value = replacement
|
|
116
|
+
if not value:
|
|
117
|
+
return value
|
|
118
|
+
if match.group(0)[0].isupper():
|
|
119
|
+
return value[:1].upper() + value[1:]
|
|
120
|
+
if not value.startswith("I'"):
|
|
121
|
+
return value[:1].lower() + value[1:]
|
|
122
|
+
return value
|
|
123
|
+
out = re.sub(pattern, replace, out, flags=re.IGNORECASE)
|
|
119
124
|
out = re.sub(r"[ \t]+\n", "\n", out)
|
|
120
125
|
out = re.sub(r" {2,}", " ", out).strip()
|
|
121
126
|
|