@roughen/cli
v0.3.0
Published
Lint prose and page copy locally with Roughen, and print revision briefs.
Downloads
194
Readme
@roughen/cli
Lint prose files, page copy or stdin locally with Roughen, plan a whole site's copy pass, and verify the rewrite. No uploads, model calls, or telemetry.
roughen ./content --json
roughen ./content --fix
roughen ./src --copy --brief
roughen --stdin --format md --brief
roughen site . --out ../copy-pass
roughen verify --gitSafe fixes are the default; --fix --careful also applies explicitly careful edits. Manual findings never auto-apply. --brief prints a revision brief instead of individual findings: what to rewrite, why, and what must not change. Hand it to a writer or a model.
Page copy
Named .tsx, .jsx, .ts and .js files are read as page copy. That means JSX text, copy attributes such as alt, and copy-named properties such as description, answer, detail and rows. It also covers FAQ { q, a } pairs, conditional JSX branches, string concatenations, arrays mapped into JSX, and any property whose value reads as prose. In directories, source files are included only with --copy. Fixes are never written to source files. Parsing uses @babel/parser, the CLI's only dependency beyond Roughen.
Every copy string has a role, listed with its line and key under copy.strings in --json:
- body: paragraphs and descriptions. Every rule applies.
- short: headings, labels, buttons, alt text. Too short for density rules, but still editable.
- protected: leave exactly as written. H1s,
title/metaTitle/headline, FAQ questions,keywords, schema names, and verbatim words: quotes, testimonials, reviews, citations, and data modules named for them.
Each finding carries the role of the string it sits in. The brief covers only what an editor may rewrite, and names any findings inside protected strings for the owner.
Config
Config resolves upward from each file via roughen.config.js, .mjs, or .cjs:
export default {
extends: ['marketing'], // register: 'marketing' — list saturation against human marketing pages
voice: {
bannedCharacters: ['—'], // every occurrence is an error, however rare
bannedPatterns: [{ pattern: '\\bgenuinely\\b', flags: 'i' }],
banned: [{ term: 'utilize', use: 'use' }],
required: ['Upforge'],
},
copy: {
body: ['soWhat'], // project keys that hold copy
protected: ['serviceLabel'], // project keys to leave alone
ignore: ['internalNote'],
protectedFiles: ['lib/data/citations.js'],
},
exclude: ['docs/**'],
};roughen site <dir>
Use this on a Next.js app-router project. It follows static, dynamic and template-literal imports from every route file (page, layout, template, not-found, error, loading), resolving tsconfig/jsconfig paths, and reports:
- copy words and findings per route and per file;
- copy no route ships;
- prose in places the reader skips, such as call arguments and unknown variables, so you can add a key to
copy.body; - a work plan: groups of files by route area, around
--group-wordseditable words each (default 6,000). Files more than one area ships get their ownsharedgroups. No file appears in two groups, so editors can work in parallel.
--json includes each file's revision brief. --out <dir> writes PLAN.md, plan.json and briefs/<group>.md to a new directory outside the site. Nothing else is written.
roughen verify
roughen verify --git [<ref>] [<path> ...] compares every changed file with its version at <ref>, which defaults to HEAD. roughen verify --before a.md --after b.md compares two files. For component copy it pairs strings through the AST with every string blanked, then fails on:
- a code change (reported at its line), an edited import path or non-copy string, or a file that no longer parses;
- an edited protected string;
- a number, link or quotation lost, or a number or link added;
- a new banned character;
- rewritten copy more than 15% longer or shorter (with ten words of slack), or flagged habits that grew.
It warns on strings outside ±15%, changed headings and new em dashes. Prose files get core's judgeRevision whole. New, deleted and untracked files are listed, not judged. Verify is read-only.
Exit codes and output
Exit codes: 0 for no errors, 1 for lint or verify errors, 2 for invalid input/configuration. JSON output is { version, results } for lint, the plan for site, and { version, files, errors, warnings, ok } for verify. Findings after fixing point into the fixed text. Directory traversal skips symlinks and build/dependency folders. MIT.
