HiroHyun
中文
← All projects

grounded-copy

A style gate for marketing copy: every claim must state what a thing is or does. A zero-dependency Python linter enforces it across nine languages.

Python · Agent skill · CI · Jul 2026 Source ↗

grounded-copy is a style gate for marketing and web copy. It enforces one rule: every value proposition states what the subject is or does — a feature, a number, a mechanism. The contrast move — phrases like “not just X”, “unlike others”, “say goodbye to” — fails the check in each disguise it wears, together with hype vocabulary and vague attribution such as “experts agree”. A deterministic Python linter backs the rule and holds the writing task until the copy complies.

The rewrite it asks for

The effect shows in the before-and-after pairs. “Experts agree Acme leads the market” becomes “Acme holds 34% of the segment, per Gartner’s 2025 market report.” “Say goodbye to hidden fees” becomes “The listed price is the complete price; the invoice adds nothing.” Same information, carried by specifics. The rule sends the writer back to name the feature, cite the number, or describe the mechanism the vaguer line was gesturing at.

Three layers

The gate works in three layers, each catching what the one before it misses. SKILL.md teaches an AI agent the banned move and its ten disguises, with closures aimed at the ways an agent rationalizes around a style rule: contrast split across two sentences, an invented testimonial, the claim that “the banned string doesn’t appear”. scripts/copy_lint.py is a zero-dependency Python 3 linter carrying more than fifty enumerated patterns; exit code 1 blocks the task, and the skill forbids editing the linter to get past it. Hooks and CI apply the gate on every file write and every pull request, the human ones included.

Nine languages

The linter catches the same move in English, Chinese, Russian, Spanish, Arabic, French, German, Japanese, and Korean. 不仅仅是, не просто, no es solo, ليس مجرد, pas seulement, mehr als nur, 単なる〜ではない, and 단순한 ~이 아닙니다 all carry “not just”, and all fail. Words with everyday factual uses — Japanese だけでなく, Korean 뿐만 아니라 — lint as warnings and pass through a deletion test that checks whether the sentence still stands once the phrase is cut. That coverage reaches locale files: a translation that reintroduces the contrast move fails CI even when the English source passed clean.

Install and enforce

The Skills CLI sets it up in one command — npx skills@latest add HiroHyun/grounded-copy — which reads the root SKILL.md, detects the agents on the machine, and places the skill in their skill directories. The linter also runs on its own: python3 scripts/copy_lint.py draft.md locales/en.json, or piped in through --stdin, with exit 0 to pass and 1 to rewrite. Copy-paste blocks in references/setup.md wire the gate into Claude Code hooks, AGENTS.md, GitHub Actions, and CODEOWNERS. Each new pattern in the catalog needs a real-world sighting, a failing line in the test corpus, and a counterexample check that keeps legitimate copy passing. grounded-copy ships under the MIT license.