A prose style gate for every stretch of text a person reads.
Read this in other languages: English · 简体中文
Install · Profiles · What it does · Before and after · Nine languages · Documentation
grounded-copy covers chat replies, documentation, plans, reports, commit
bodies, pull request descriptions, code comments, and product copy. It requires
every claim to name a feature, number, or mechanism. A Python linter detects
documented contrast patterns, hype vocabulary, and vague attribution.
Install
One command installs the Claude Code and Codex plugins when their CLIs are available, then installs the portable skill for 17+ agents through the Skills CLI.
# macOS · Linux · WSL · Git Bash
curl -fsSL https://raw.githubusercontent.com/HiroHyun/grounded-copy/main/install.sh | sh
# Windows · PowerShell
irm https://raw.githubusercontent.com/HiroHyun/grounded-copy/main/install.ps1 | iex
The launchers require Python 3 and Node. They print each host command before
running it. A checkout exposes the full flags: sh install.sh --dry-run,
python3 install.py --skills-only, and python3 install.py --uninstall.
Per-host alternatives
| Host | Command |
|---|---|
| Portable skill, 17+ agents | npx skills add HiroHyun/grounded-copy --skill grounded-copy --yes |
| Claude Code plugin | claude plugin marketplace add HiroHyun/grounded-copyclaude plugin install grounded-copy@hirohyun-plugins -s user |
| Codex plugin | codex plugin marketplace add HiroHyun/grounded-copycodex plugin add grounded-copy@hirohyun-plugins |
| Linter from a checkout | python3 skills/grounded-copy/scripts/copy_lint.py draft.md |
The portable command copies the canonical skill directory: SKILL.md, both
references, the linter, and both test corpora. The Claude Code and Codex
plugins add lifecycle hooks, three stored profiles, and a profile controller.
| Capability | Portable, 17+ agents | Plugin, Claude Code and Codex |
|---|---|---|
| Rules, catalog, nine locales, linter, and corpora | yes | yes |
SessionStart policy, repeated after compaction | yes | |
UserPromptSubmit turn reminder | yes | |
chat, copy, and off profiles with a stored preference | yes | |
| Profile controller and governing directive | yes |
Agents evaluate the skill description on each turn. Plugin hooks run on their registered session events, so Claude Code and Codex receive the stored profile at session start, after compaction, and on each prompt.
When the universal install and Claude plugin share a machine, Claude Code may
list grounded-copy@skills-dir as Not loaded because the plugin owns the
active skill name. The plugin supplies the skill and hooks.
The Codex cache also carries the linter, under a directory named for the installed version:
python3 ~/.codex/plugins/cache/hirohyun-plugins/grounded-copy/<version>/skills/grounded-copy/scripts/copy_lint.py draft.md
codex plugin list prints the number that goes in <version>.
Pick your profile
Three profiles. Switch with /grounded-copy:grounded chat|copy|off in Claude
Code and $grounded-profile chat|copy|off|status in Codex. The choice records
at <config-dir>/grounded-copy/profile and holds across restarts until another
set replaces it.
| Profile | What SessionStart injects | Bytes | Turn reminder |
|---|---|---|---|
chat (default) | the intro and its grounded example, the banned move with its seven shapes, positive forms, scope and precedence, sourcing | 3,679 | one line naming chat |
copy | the same, plus the marketing register and two loophole closures | 5,140 | one line naming copy |
off | nothing | 0 | nothing |
[!IMPORTANT] Set
offbefore working on supplied text. The rules govern prose you compose. Pointed at text that carries a contrast of its own — a translation of a supplied source, a quoted passage, a legal or regulatory clause, a billing statement — the model can delete that contrast and change what the text says. Translation is the common case: the source sentence carries a contrast the author chose, and a profile left on produces a target sentence that drops it. Setofffor that work.
[!TIP] A phrase the linter reports by design. Any
-ingnoun afterwithoutreads as a gerund, so "without warning" and "without training" reportwithout-gerund. Copy that needs one of them is written withoff.
What it does
- Rule:
SKILL.mddefines seven contrast shapes, positive constraint terms, sourcing rules, and a concrete rewrite method. - Linter:
copy_lint.pyuses the Python 3 standard library and returns exit code 0 for a clean file, 1 for findings, and 2 for usage or I/O errors. - Session policy: Claude Code and Codex plugins inject the selected policy at session start and a compact reminder on each prompt.
- CI gate: the workflow requires the bad corpus to return 1 and the good corpus to return 0 on Ubuntu and Windows.
Two layers do the work. The hooks put the rules in the model's context at
session start, after each compaction, and on each prompt, and the model follows
them at the rate a model follows any instruction. copy_lint.py returns exit
code 1 on findings, which holds for whatever you point it at: a draft, a diff,
a CI path.
Before and after
Each left cell quotes a blocked pattern, and the rule column names the id
copy_lint.py prints for it. The catalog carries a rewrite for every
documented shape.
| Blocked draft | Grounded rewrite | Rule |
|---|---|---|
| "It's not a website. It's your storefront." | "The site takes orders, processes payments in 135 currencies, and prints shipping labels." | opener-it-is-not |
| "Acme is a partner, not a vendor." | "Acme assigns each client a strategist who joins quarterly planning." | comma-not-appositive |
| "We ship every Friday rather than hoarding features." | "We ship every Friday." | rather-than |
| "Acme answers tickets instead of queuing them." | "Acme replies to every ticket within four business hours." | instead-of |
| "More than just a project tracker." | "Acme links every task to its pull request and posts a daily digest to Slack." | more-than-just |
| "Experts agree Acme leads the market." | "Acme holds 34% of the segment, per Gartner’s 2025 market report." | vague-experts |
See the full pattern catalog.
Nine languages
The linter covers nine languages at three documented depths.
| Tier | Languages | What the regexes match |
|---|---|---|
| Full | English | 57 rules, with one or more rules for each shape |
| Structural | Chinese, Japanese, Korean | a bounded gap between negation and assertion, plus enumerated triggers |
| Enumerated | Russian, Spanish, Arabic, French, German | trigger lists of 6 to 18 phrases across minimizing, era-ending, transcendence, and rhetorical-bait families |
The target-language trigger lists form a floor, and the catalog's translator rule carries the rest: translate the grounded source, keep its concrete facts, and hold the contrast out of the target sentence. Japanese だけでなく and Korean 뿐만 아니라, 더 이상, and 혁신적 each also carry a plain coordinating sense, and the regex reports those uses too.
Documentation
- Setup and wiring covers install layout, profiles, hook lifecycle, context cost, CI, and rollback.
- Pattern catalog lists every documented trigger family and its rewrites.
- Contributing covers patterns, languages, and test corpora.
- MIT License covers use and redistribution.