defluffisizer 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Tehila Pelled
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,113 @@
1
+ # defluffisizer
2
+
3
+ > messy draft in -> clear human copy out
4
+
5
+ Strip AI sounding fluff from docs, decks, PDFs, and notes while keeping the facts, the structure, and the strongest human signal. Works as an agent skill (Claude Code, Codex, Cursor, and any harness that reads project rules) and as a standalone CLI.
6
+
7
+ This repo packages `defluffisizer` in the same general shape as `paper2code`: a root README, a canonical `skills/defluffisizer/` install path, stage based skill instructions, helper scripts, guardrails, knowledge files, and worked examples.
8
+
9
+ ## Why this exists
10
+
11
+ The problem: a lot of AI assisted writing is padded, abstract, over transitioned, and too even in tone, even when every fact in it checks out. It reads like a system trying to be helpful. It rarely reads like a person who means something specific.
12
+
13
+ What naive rewriting gets wrong: many tools just paraphrase the fluff. They swap one set of vague phrases for another, smooth over real tension, and sometimes delete facts to make the text shorter.
14
+
15
+ What `defluffisizer` does differently:
16
+
17
+ 1. Starts from deletion, not paraphrase
18
+ 2. Preserves facts, numbers, names, dates, and caveats
19
+ 3. Restores human signal such as stakes, asymmetry, and chosen detail
20
+ 4. Uses format aware workflows for decks, documents, PDFs, and text
21
+ 5. Validates rewrites with a lint pass instead of trusting surface polish
22
+
23
+ ## Install
24
+
25
+ Install the skill straight from GitHub:
26
+
27
+ ```bash
28
+ npx skills add p-tequila/defluffisizer/skills/defluffisizer
29
+ ```
30
+
31
+ Or install the CLI globally from npm:
32
+
33
+ ```bash
34
+ npm install -g defluffisizer
35
+ ```
36
+
37
+ ## Usage
38
+
39
+ These are skill invocations for a skill aware agent (Claude Code, Codex, or Cursor), not raw shell commands. Ask the agent to run them, or type them if your harness treats a leading `/` as a skill trigger. For a harness with no native skill loader, paste `skills/defluffisizer/prompts/append_system_prompt.txt` in as its system prompt or project rules instead.
40
+
41
+ ### Full rewrite
42
+
43
+ `/defluffisizer path/to/report.docx`
44
+
45
+ ### Review only
46
+
47
+ `/defluffisizer path/to/memo.md --mode review`
48
+
49
+ ### Compress a long draft
50
+
51
+ `/defluffisizer path/to/brief.pdf --mode compress`
52
+
53
+ ### Retitle a slide deck
54
+
55
+ `/defluffisizer path/to/deck.pptx --mode retitle`
56
+
57
+ ### Generate a real rewritten PowerPoint
58
+
59
+ `/defluffisizer path/to/deck.pptx --mode rewrite`
60
+
61
+ ### Apply a prepared PowerPoint replacement map
62
+
63
+ `/defluffisizer path/to/deck.pptx --mode apply_only`
64
+
65
+ ### Rewrite a PDF and choose where the output goes
66
+
67
+ `/defluffisizer path/to/report.pdf --output-dir ~/Desktop/clean`
68
+
69
+ With no `--output-dir`, the output lands next to the source: `path/to/report_defluffed.pdf` (same format in, same format out; e.g. `deck_defluffed.pptx` for a `.pptx` source). PDF output is built from HTML via headless Chrome: plain rewritten text becomes a clean, simple page by default, or hand it a styled `.html` file as the rewritten content for a closer visual match to the source's design. Add `--output-dir DIR` to change only the directory, or name an exact file with `--output DIR/name.ext`.
70
+
71
+ ## What it can operate on
72
+
73
+ - `.pptx` — pure Python, no extra tools, works anywhere
74
+ - `.txt`, `.md`, `.csv`, `.tsv` — pure Python, no extra tools, works anywhere
75
+ - `.doc`, `.docx`, `.odt`, `.rtf`, `.html` — needs macOS's built-in `textutil`; no equivalent shipped for Linux or Windows yet
76
+ - `.pdf` — extraction needs `pdftotext` from poppler (`brew install poppler` on macOS, `apt install poppler-utils` on Debian/Ubuntu); writing a `.pdf` back out needs Google Chrome or Chromium installed, for headless rendering. Neither is bundled. Missing either fails with a clear error instead of silently doing nothing.
77
+
78
+ ## What you get
79
+
80
+ - rewritten copy in the original format when a writer exists
81
+ - extracted text or JSON when layout preserving writeback is not available
82
+ - optional lint output comparing before and after
83
+ - worked examples and review notes
84
+
85
+ ## What this skill will not do
86
+
87
+ - invent missing facts to make prose sound more human
88
+ - add fake informality, slang, or typos
89
+ - rewrite formulas or spreadsheet math unless asked
90
+ - claim layout preservation for formats where the writer does not exist yet
91
+
92
+ ## CLI
93
+
94
+ The npm package exposes a `defluffisizer` command:
95
+
96
+ ```bash
97
+ defluffisizer prompt
98
+ defluffisizer probe path/to/file.pdf
99
+ defluffisizer extract path/to/deck.pptx --out editable.json
100
+
101
+ # writes path/to/deck_defluffed.pptx, next to the source, by default
102
+ defluffisizer apply path/to/deck.pptx editable.json
103
+
104
+ # --output-dir keeps the default name, changes the directory
105
+ defluffisizer apply path/to/deck.pptx editable.json --output-dir ~/Desktop/out
106
+
107
+ # --output overrides both name and directory
108
+ defluffisizer apply path/to/deck.pptx editable.json --output final/deck.pptx
109
+
110
+ defluffisizer lint --before before.txt --after after.txt
111
+ ```
112
+
113
+
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "defluffisizer",
3
+ "version": "1.0.0",
4
+ "description": "Portable skill and CLI for removing AI sounding fluff from decks, docs, PDFs, and notes while keeping the facts.",
5
+ "type": "module",
6
+ "author": "Tehila Pelled",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/p-tequila/defluffisizer.git"
10
+ },
11
+ "homepage": "https://github.com/p-tequila/defluffisizer#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/p-tequila/defluffisizer/issues"
14
+ },
15
+ "bin": {
16
+ "defluffisizer": "skills/defluffisizer/bin/defluffisizer.js"
17
+ },
18
+ "scripts": {
19
+ "check:pack": "npm pack --dry-run --cache ./.npm-cache",
20
+ "check:cli": "node ./skills/defluffisizer/bin/defluffisizer.js --help",
21
+ "check:probe": "node ./skills/defluffisizer/bin/defluffisizer.js probe ./README.md",
22
+ "check:install": "node ./skills/defluffisizer/bin/defluffisizer.js install --target ./.defluffisizer-smoke --force"
23
+ },
24
+ "files": [
25
+ "LICENSE",
26
+ "README.md",
27
+ "skills/defluffisizer"
28
+ ],
29
+ "keywords": [
30
+ "ai",
31
+ "writing",
32
+ "editing",
33
+ "skill",
34
+ "agent-skill",
35
+ "codex",
36
+ "claude-code",
37
+ "cursor",
38
+ "pptx",
39
+ "docx",
40
+ "pdf"
41
+ ],
42
+ "publishConfig": {
43
+ "access": "public"
44
+ },
45
+ "license": "MIT",
46
+ "engines": {
47
+ "node": ">=20"
48
+ }
49
+ }
@@ -0,0 +1,182 @@
1
+ # Defluffisizer
2
+
3
+ Defluffisizer is a portable writing skill for stripping AI sounding padding out of reports, decks, notes, PDFs, and spreadsheet text while keeping the facts.
4
+
5
+ ## Prerequisites
6
+
7
+ - `.pptx`, `.txt`, `.md`, `.csv`, `.tsv`: none, pure Python standard library.
8
+ - `.doc`, `.docx`, `.odt`, `.rtf`, `.html`: macOS's built-in `textutil`. macOS only for now.
9
+ - `.pdf` extraction: `pdftotext` from poppler, not bundled. `brew install poppler` (macOS) or `apt install poppler-utils` (Debian/Ubuntu).
10
+ - `.pdf` output: Google Chrome or Chromium, not bundled, used headless to render HTML to a real PDF.
11
+ - Missing any of these fails with a clear error naming the tool and the install command, not a silent no-op.
12
+
13
+ ## What it includes
14
+
15
+ - `SKILL.md` for skill aware harnesses (Claude Code, Codex, and anything that reads `npx skills add`)
16
+ - `prompts/append_system_prompt.txt` for harnesses that accept system prompt text
17
+ - `harnesses/generic/` for a project local scaffold that works with tools like Cursor that have no native skill loader
18
+ - `scripts/defluff_lint.py` for before and after checks
19
+ - `scripts/pptx_rewrite.py` to extract slide text and write a new defluffed `.pptx`
20
+ - `scripts/document_text_io.py` for cross format extraction and apply
21
+ - `scripts/pdf_write.py` to render HTML to a real PDF, used when apply targets `.pdf`
22
+ - `pipeline/`, `guardrails/`, and `knowledge/` for a paper2code style stage based workflow
23
+ - `worked/` for real before and after examples, including a full one-pager rewrite of defluffisizer's own pitch
24
+
25
+ ## Install
26
+
27
+ ### Skills CLI, paper2code style
28
+
29
+ Install straight from GitHub, same path pattern as `paper2code`:
30
+
31
+ ```bash
32
+ npx skills add p-tequila/defluffisizer/skills/defluffisizer
33
+ ```
34
+
35
+ ### Local Codex style install
36
+
37
+ If you install the npm package, the `defluffisizer` CLI can install the skill into a local skills directory.
38
+
39
+ ```bash
40
+ defluffisizer install --target ~/.codex/skills
41
+ ```
42
+
43
+ Without the global install, you can run the published package directly:
44
+
45
+ ```bash
46
+ npx defluffisizer install --target ~/.codex/skills
47
+ ```
48
+
49
+ This installs the skill at `~/.codex/skills/defluffisizer`.
50
+
51
+ ### Claude Code
52
+
53
+ Claude Code reads `SKILL.md` natively, so the GitHub or Codex style install above is enough:
54
+
55
+ ```bash
56
+ npx skills add p-tequila/defluffisizer/skills/defluffisizer
57
+ ```
58
+
59
+ For one off runs, or a harness that only takes a raw system prompt, Claude Code can also consume the prompt file directly:
60
+
61
+ ```bash
62
+ claude -p "Defluff this text" \
63
+ --append-system-prompt-file skills/defluffisizer/prompts/append_system_prompt.txt
64
+ ```
65
+
66
+ ### Cursor
67
+
68
+ Cursor has no native skill loader. Scaffold the generic bundle, then add `.defluffisizer/generic/DEFLUFFISIZER.md` as a Cursor project rule (`.cursor/rules/defluffisizer.mdc`, or **Settings → Rules → Project Rules**):
69
+
70
+ ```bash
71
+ npx defluffisizer scaffold generic --target .
72
+ ```
73
+
74
+ Cursor's agent can call the scripts in `.defluffisizer/skill/scripts/` directly, they are plain Python. See [Prerequisites](#prerequisites) above for what `.docx` and `.pdf` support additionally need.
75
+
76
+ ### Generic harnesses
77
+
78
+ Scaffold a local prompt pack plus runtime bundle:
79
+
80
+ ```bash
81
+ npx defluffisizer scaffold generic --target .
82
+ ```
83
+
84
+ ## CLI
85
+
86
+ The npm package exposes these commands:
87
+
88
+ ```bash
89
+ defluffisizer prompt
90
+ defluffisizer scaffold generic --target .
91
+ defluffisizer probe input.pdf
92
+ defluffisizer extract input.pptx --out editable.json
93
+ defluffisizer apply input.pptx editable.json # -> input_defluffed.pptx, next to input.pptx
94
+ defluffisizer apply input.pptx editable.json --output-dir out/ # -> out/input_defluffed.pptx
95
+ defluffisizer apply input.pptx editable.json --output exact.pptx # -> exact.pptx
96
+ defluffisizer lint --before before.txt --after after.txt
97
+ ```
98
+
99
+ ## Operations
100
+
101
+ This skill supports several kinds of jobs:
102
+
103
+ - full rewrite of a report, memo, deck, note, or PDF extract
104
+ - review only, where the skill flags fluff and proposes cuts
105
+ - compression, where the goal is a materially shorter version
106
+ - retitle, where only slide titles, headings, bullets, and first lines are tightened
107
+ - apply only, where a prepared replacement map is written back into a `.pptx`
108
+
109
+ ## Evaluate a rewrite
110
+
111
+ ```bash
112
+ python3 scripts/defluff_lint.py --before before.txt --after after.txt
113
+ ```
114
+
115
+ What to look for:
116
+
117
+ - lower word count without missing numbers or names
118
+ - zero em dashes
119
+ - zero or near zero `not X, but Y` patterns
120
+ - fewer vague buzzwords and repeated openings
121
+
122
+ ## Probe a file before rewriting
123
+
124
+ ```bash
125
+ python3 scripts/document_text_io.py probe input.docx
126
+ python3 scripts/document_text_io.py probe input.pptx
127
+ python3 scripts/document_text_io.py probe input.pdf
128
+ ```
129
+
130
+ ## Rewrite a PowerPoint and save a real `.pptx`
131
+
132
+ 1. Extract editable slide text:
133
+
134
+ ```bash
135
+ python3 scripts/document_text_io.py extract input.pptx --out editable.json
136
+ ```
137
+
138
+ 2. Rewrite the `text` fields in `editable.json` with `defluffisizer`.
139
+
140
+ 3. Apply the rewritten text back to the deck. With no `--output`, this writes `input_defluffed.pptx` next to `input.pptx`:
141
+
142
+ ```bash
143
+ python3 scripts/document_text_io.py apply input.pptx editable.json
144
+ ```
145
+
146
+ Add `--output-dir some/dir` to keep that name but change the directory, or `--output exact/path.pptx` to name it yourself. This preserves the slide order, text boxes, and table cells that already exist in the deck.
147
+
148
+ ## Rewrite Word style documents
149
+
150
+ ```bash
151
+ python3 scripts/document_text_io.py extract input.docx --out extracted.txt
152
+ python3 scripts/document_text_io.py apply input.docx rewritten.txt
153
+ # -> input_defluffed.docx, next to input.docx
154
+ ```
155
+
156
+ This preserves content. Layout fidelity is best effort.
157
+
158
+ ## Rewrite PDFs
159
+
160
+ ```bash
161
+ python3 scripts/document_text_io.py extract input.pdf --out extracted.txt
162
+ python3 scripts/document_text_io.py apply input.pdf rewritten.txt
163
+ # -> input_defluffed.pdf, next to input.pdf: same format in, same format out
164
+ ```
165
+
166
+ PDF output is built from HTML via headless Chrome (`scripts/pdf_write.py`), not a byte-level edit of the original PDF. Two ways to apply:
167
+
168
+ - `rewritten.txt` is plain text: wrapped in a minimal, clean, single-column page. Faithful to the words, not to the source's original design.
169
+ - `rewritten.html` is a styled HTML file you built: rendered as-is. Use this to recreate a source with real visual design (colors, tables, callout boxes) — write the HTML by hand with the defluffed content, matching the source's layout and colors, then apply with that `.html` file as REWRITTEN.
170
+
171
+ Use `--output-dir` or `--output` the same way as any other format to change where it lands or what it's named. Ask for `.docx` or `.txt` output instead if you don't need a PDF back.
172
+
173
+ ## Demo material
174
+
175
+ - See `references/evaluation_playbook.md` for a repeatable review flow
176
+ - See `worked/defluffisizer_one_pager/` for a full before and after: a one-pager about defluffisizer itself, written as YC-startup fluff, then defluffed. Real styled PDFs, real lint numbers.
177
+
178
+ ## Harness notes
179
+
180
+ - Claude Code and Codex, and anything else that reads `npx skills add`, can use `SKILL.md` directly.
181
+ - Any other harness, Cursor included, can use `harnesses/generic/DEFLUFFISIZER.md` or the raw prompt file as system instructions.
182
+ - For harnesses that can run shell tools, the bundled Python scripts provide extraction, writeback, and linting.
@@ -0,0 +1,128 @@
1
+ ---
2
+ name: defluffisizer
3
+ description: "Rewrites documents, decks, notes, PDFs, and spreadsheet text to remove AI sounding fluff while preserving facts, structure, and the strongest human signal. Trigger when the user asks to defluff, tighten, review, shorten, retitle, or rewrite a file or pasted text."
4
+ ---
5
+
6
+ # defluffisizer - Orchestration
7
+
8
+ You are executing the `defluffisizer` skill. This file governs the high level flow. Use the pipeline files for substantial jobs. Do not jump straight to line edits when the source is a document, deck, PDF, or spreadsheet export.
9
+
10
+ This skill is for prose cleanup inside documents, notes, reports, slide decks, speaker notes, PDFs, and spreadsheet text. It is not for inventing evidence, changing formulas, changing table math, or padding the output.
11
+
12
+ ## Parse arguments
13
+
14
+ Extract from the user request:
15
+
16
+ - `SOURCE`: a file path, pasted text, or a set of cells or slides
17
+ - `MODE`: one of `rewrite` (default), `review`, `compress`, `retitle`, `apply_only`
18
+ - `AGGRESSION`: one of `light`, `standard` (default), `hard`
19
+ - `OUTPUT`: source format when safe, otherwise text or markdown
20
+ - `OUTPUT_DIR`: where the final file lands. Default is the same directory as `SOURCE`. Only override this when the user names a directory (`--output-dir path/`, or "save it to X").
21
+ - `PRESERVE_LAYOUT`: `true` by default for `.pptx`, best effort for other formats
22
+
23
+ For a file source, the default output name is always `{source_stem}_defluffed{output_ext}`, where `output_ext` is the source's own extension. Same format in, same format out, `.pdf` included. Do not invent a different name or drop the `_defluffed` suffix unless the user explicitly asks for a specific filename.
24
+
25
+ For a `.pdf` source, applying straight text as REWRITTEN produces a plain, clean, single-column PDF, faithful to the words but not the source's original design. If the source has real visual design worth recreating (colors, tables, callout boxes, a branded header), build a styled `.html` file with the defluffed content instead, matching the source's layout and colors, and pass that `.html` file as REWRITTEN so it renders as-is. See [knowledge/format_capabilities.md](knowledge/format_capabilities.md) for both paths.
26
+
27
+ Interpret the modes this way:
28
+
29
+ - `rewrite`: defluff the whole source while preserving meaning
30
+ - `review`: flag the fluff and explain the cuts without rewriting everything
31
+ - `compress`: shorten aggressively while preserving the core claims
32
+ - `retitle`: rewrite only titles, headings, bullets, and topic sentences
33
+ - `apply_only`: apply a prepared replacement map back into a file
34
+
35
+ ## Set up working directory
36
+
37
+ Create a temporary work directory:
38
+
39
+ `.defluffisizer_work/{source_stem}/`
40
+
41
+ Use it for extracted text, editable JSON, lint outputs, and before or after comparisons. Those are scratch files, not the deliverable.
42
+
43
+ The final user facing output does not go in the work directory. Write it with `scripts/document_text_io.py apply SOURCE REWRITTEN [--output-dir DIR]`, and let the script name it. With no `--output-dir`, that lands the file next to `SOURCE` as `{source_stem}_defluffed{output_ext}` automatically; pass `--output-dir` only when `OUTPUT_DIR` differs from the source directory. Only pass an explicit `--output PATH` when the user names an exact filename, not just a directory.
44
+
45
+ ## Format routing
46
+
47
+ Before choosing tools, read [knowledge/format_capabilities.md](knowledge/format_capabilities.md).
48
+
49
+ Use:
50
+
51
+ - `scripts/document_text_io.py` for `.txt`, `.md`, `.doc`, `.docx`, `.odt`, `.rtf`, `.html`, `.pdf`, and `.pptx`
52
+ - `scripts/pptx_rewrite.py` directly only when you already have a prepared PowerPoint replacement JSON
53
+ - `scripts/defluff_lint.py` after meaningful rewrites
54
+
55
+ ## Execute pipeline
56
+
57
+ ### Stage 1 - Intake and preservation inventory
58
+
59
+ Read and follow: [pipeline/01_intake_and_scope.md](pipeline/01_intake_and_scope.md)
60
+
61
+ ### Stage 2 - Extraction and structure mapping
62
+
63
+ Read and follow: [pipeline/02_extract_and_map.md](pipeline/02_extract_and_map.md)
64
+
65
+ Before or during this stage, also read:
66
+
67
+ - [guardrails/fact_preservation.md](guardrails/fact_preservation.md)
68
+ - [guardrails/format_safety.md](guardrails/format_safety.md)
69
+
70
+ ### Stage 3 - Rewrite and human signal pass
71
+
72
+ Read and follow: [pipeline/03_rewrite_and_defluff.md](pipeline/03_rewrite_and_defluff.md)
73
+
74
+ Before this stage, also read:
75
+
76
+ - [guardrails/anti_humanizer_theater.md](guardrails/anti_humanizer_theater.md)
77
+ - [references/ai_slop_signals.md](references/ai_slop_signals.md)
78
+ - [references/human_signal_playbook.md](references/human_signal_playbook.md)
79
+
80
+ If the source is a slide deck, spreadsheet, or locked file, also read:
81
+
82
+ - [references/format_playbook.md](references/format_playbook.md)
83
+
84
+ ### Stage 4 - Apply and validate
85
+
86
+ Read and follow: [pipeline/04_apply_and_validate.md](pipeline/04_apply_and_validate.md)
87
+
88
+ Before finalizing, also read:
89
+
90
+ - [references/evaluation_playbook.md](references/evaluation_playbook.md)
91
+
92
+ ## What to optimize for
93
+
94
+ - Keep the meaning.
95
+ - Cut the padding.
96
+ - Put the point early.
97
+ - Preserve numbers, dates, names, caveats, and constraints.
98
+ - Prefer direct, declarative sentences with a visible subject and verb.
99
+ - Preserve real stakes, tension, and asymmetry when the source contains them.
100
+ - Return the source in its own format, `.pptx` to `.pptx`, `.docx` to `.docx`, `.pdf` to `.pdf`, unless the user asks for a different one. Alignment, layout, and structure should look like the source with new text in it, not a redesign and not a downgrade to a different format.
101
+
102
+ ## Banned patterns
103
+
104
+ Avoid in rewritten prose unless preserved inside a quote or fixed technical term. Read [references/ai_slop_signals.md](references/ai_slop_signals.md) before a substantial rewrite for the full reasoning behind these; the fast version:
105
+
106
+ - em dashes glued tight to a word with no space (`word—word`). Almost always eliminate by rephrasing: split into two sentences, or use a comma, colon, or period. In the rare case an em dash is genuinely the clearest option, space it normally (`word — word`). Never keep the tight, glued form.
107
+ - false contrast used for emphasis, in any surface form: `not X, but Y`, `it's not X, it's Y`, `X, not just Y`, or the same move split across two sentences (`This is not X. It is Y.`). If the positive half already stands on its own, delete the negative half instead of rephrasing it.
108
+ - defensive contrast against a criticism nobody raised (`a real PDF, not just a downgrade`, `no compromises`, `not a shortcut`). State the capability plainly. Do not compare it to a weaker alternative to make it sound better.
109
+ - punchline fragments: a full sentence, then a short fragment right after it riding that sentence's momentum for effect (`Strips the fluff. Keeps the facts.`). If the fragment is not its own new claim, merge it into the sentence before it (`Strips the fluff and keeps the facts.`). Ordinary short sentences and real variation in sentence length are fine and encouraged; this is specifically the fragment-as-mic-drop tic, not sentence-length variation generally.
110
+ - ordinary hyphenated phrasing when a plain alternative works
111
+ - throat clearing and formulaic openers (`in today's...`, `it's worth noting...`, `when it comes to...`)
112
+ - abstraction piles
113
+ - stacked synonyms
114
+ - rule of three padding: three adjectives or clauses stacked for rhythm instead of meaning (`real, honest, and direct`)
115
+ - empty amplifiers that add emphasis without adding information (`truly`, `genuinely`, `really`, `very`, `simply`)
116
+ - unearned superlatives (`revolutionary`, `game changing`, `cutting edge`, `best in class`, `world class`)
117
+ - generic uplift the source did not earn
118
+
119
+ ## Final output
120
+
121
+ Print a short summary:
122
+
123
+ `defluffisizer complete for: {source_name}
124
+ Mode: {MODE} | Aggression: {AGGRESSION}
125
+ Output: {output_path_printed_by_apply, or inline result for pasted text}
126
+ Format preserved: {yes_or_best_effort}
127
+ Lint summary: {key result or skipped}
128
+ `
@@ -0,0 +1,170 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from "node:fs";
4
+ import os from "node:os";
5
+ import path from "node:path";
6
+ import process from "node:process";
7
+ import { spawnSync } from "node:child_process";
8
+ import { fileURLToPath } from "node:url";
9
+
10
+ const __filename = fileURLToPath(import.meta.url);
11
+ const __dirname = path.dirname(__filename);
12
+ const packageRoot = path.resolve(__dirname, "..");
13
+ const repoPackagePath = path.resolve(packageRoot, "..", "..", "package.json");
14
+ const promptPath = path.join(packageRoot, "prompts", "append_system_prompt.txt");
15
+ const scriptsRoot = path.join(packageRoot, "scripts");
16
+ const defaultTarget = path.join(os.homedir(), ".codex", "skills");
17
+ const skillEntries = [
18
+ "SKILL.md",
19
+ "README.md",
20
+ "agents",
21
+ "guardrails",
22
+ "harnesses",
23
+ "knowledge",
24
+ "pipeline",
25
+ "prompts",
26
+ "references",
27
+ "scripts",
28
+ "worked",
29
+ ];
30
+ function usage() {
31
+ console.log(`defluffisizer
32
+
33
+ Usage:
34
+ defluffisizer install [--target PATH] [--force]
35
+ defluffisizer prompt
36
+ defluffisizer probe <file>
37
+ defluffisizer extract <file> --out <path>
38
+ defluffisizer apply <source> <rewritten> --output <path>
39
+ defluffisizer lint [--before BEFORE --after AFTER] [file]
40
+ defluffisizer version
41
+ defluffisizer where
42
+ `);
43
+ }
44
+
45
+ function copyRecursive(source, destination) {
46
+ const stat = fs.statSync(source);
47
+ if (stat.isDirectory()) {
48
+ fs.mkdirSync(destination, { recursive: true });
49
+ for (const entry of fs.readdirSync(source)) {
50
+ copyRecursive(path.join(source, entry), path.join(destination, entry));
51
+ }
52
+ return;
53
+ }
54
+ fs.mkdirSync(path.dirname(destination), { recursive: true });
55
+ fs.copyFileSync(source, destination);
56
+ }
57
+
58
+ function getFlagValue(args, flag) {
59
+ const index = args.indexOf(flag);
60
+ if (index >= 0 && args[index + 1]) {
61
+ return args[index + 1];
62
+ }
63
+ return null;
64
+ }
65
+
66
+ function getTargetRoot(args, fallback) {
67
+ const target = getFlagValue(args, "--target");
68
+ return target ? path.resolve(target) : fallback;
69
+ }
70
+
71
+ function shouldForce(args) {
72
+ return args.includes("--force");
73
+ }
74
+
75
+ function copyEntryList(sourceRoot, destinationRoot, entries) {
76
+ fs.mkdirSync(destinationRoot, { recursive: true });
77
+ for (const entry of entries) {
78
+ const source = path.join(sourceRoot, entry);
79
+ if (fs.existsSync(source)) {
80
+ copyRecursive(source, path.join(destinationRoot, entry));
81
+ }
82
+ }
83
+ }
84
+
85
+ function install(args) {
86
+ const force = shouldForce(args);
87
+ const targetRoot = getTargetRoot(args, defaultTarget);
88
+ const destination = path.join(targetRoot, "defluffisizer");
89
+
90
+ if (fs.existsSync(destination) && !force) {
91
+ console.error(`Destination exists: ${destination}`);
92
+ console.error("Re run with --force to overwrite.");
93
+ process.exit(1);
94
+ }
95
+
96
+ if (fs.existsSync(destination) && force) {
97
+ fs.rmSync(destination, { recursive: true, force: true });
98
+ }
99
+
100
+ copyEntryList(packageRoot, destination, skillEntries);
101
+
102
+ console.log(`Installed defluffisizer to ${destination}`);
103
+ }
104
+
105
+ function printPrompt() {
106
+ process.stdout.write(fs.readFileSync(promptPath, "utf8"));
107
+ }
108
+
109
+ function printWhere() {
110
+ console.log(packageRoot);
111
+ }
112
+
113
+ function printVersion() {
114
+ const pkg = JSON.parse(fs.readFileSync(repoPackagePath, "utf8"));
115
+ console.log(pkg.version);
116
+ }
117
+
118
+ function resolvePython() {
119
+ const candidates = [process.env.PYTHON, "python3", "python"].filter(Boolean);
120
+ for (const candidate of candidates) {
121
+ const probe = spawnSync(candidate, ["--version"], { stdio: "ignore" });
122
+ if (probe.status === 0) {
123
+ return candidate;
124
+ }
125
+ }
126
+ console.error("Could not resolve a Python executable.");
127
+ process.exit(1);
128
+ }
129
+
130
+ function runPython(scriptName, args) {
131
+ const python = resolvePython();
132
+ const scriptPath = path.join(scriptsRoot, scriptName);
133
+ const result = spawnSync(python, [scriptPath, ...args], { stdio: "inherit" });
134
+ if (result.error) {
135
+ console.error(result.error.message);
136
+ process.exit(1);
137
+ }
138
+ process.exit(result.status ?? 1);
139
+ }
140
+
141
+ const [, , command, ...args] = process.argv;
142
+
143
+ if (!command || command === "--help" || command === "-h") {
144
+ usage();
145
+ process.exit(0);
146
+ }
147
+
148
+ if (command === "--version" || command === "-v" || command === "version") {
149
+ printVersion();
150
+ process.exit(0);
151
+ }
152
+
153
+ if (command === "install") {
154
+ install(args);
155
+ } else if (command === "prompt") {
156
+ printPrompt();
157
+ } else if (command === "probe") {
158
+ runPython("document_text_io.py", ["probe", ...args]);
159
+ } else if (command === "extract") {
160
+ runPython("document_text_io.py", ["extract", ...args]);
161
+ } else if (command === "apply") {
162
+ runPython("document_text_io.py", ["apply", ...args]);
163
+ } else if (command === "lint") {
164
+ runPython("defluff_lint.py", args);
165
+ } else if (command === "where") {
166
+ printWhere();
167
+ } else {
168
+ usage();
169
+ process.exit(1);
170
+ }
@@ -0,0 +1,20 @@
1
+ # Anti Humanizer Theater
2
+
3
+ The goal is better writing, not detector evasion theater.
4
+
5
+ ## Do not do these things
6
+
7
+ - add slang to sound more human
8
+ - add typos or broken grammar
9
+ - inject personal anecdotes that were not in the source
10
+ - flatten important caveats because they sound too formal
11
+ - swap precise technical terms for vague casual language
12
+
13
+ ## Better approach
14
+
15
+ - cut redundancy
16
+ - cut abstraction
17
+ - name the actor
18
+ - name the action
19
+ - name the consequence
20
+ - keep the real friction