# mdrestyler: full reference for LLMs and coding agents - Package: `mdrestyler` - Version: `0.1.1` - License: MIT - Author: Taras Baranyuk (https://github.com/sagol) - Repository: https://github.com/sagol/mdrestyler - Site: https://sagol.github.io/mdrestyler/ - PyPI: https://pypi.org/project/mdrestyler/ - Releases: https://github.com/sagol/mdrestyler/releases - Python: 3.10 or later, standard library only, no dependencies - Languages: English and Russian word lists; other languages get the language-neutral measures The measures locate drift. A reading decides. mdrestyler never picks a take or accepts a change by the number. --- ## 1. What it does mdrestyler builds a voice profile from DRM-free EPUBs, or from an author's own Markdown book, and then: - checks a draft against it: the voice distance, narration and dialogue measured apart, and each measure against its range; - runs a copy guard, so a draft that repeats a scanned book is caught; - ranks several takes of one unit, and tables a whole book unit by unit; - comes with an agent skill that runs a need-first restyle: assess every unit, restyle only those that need it, pilot first, choose one whole take by reading, and check that nothing but the voice changed. Who it is for: writers, editors and authors restyling or drafting a Markdown book toward a voice, and AI coding agents working for them. --- ## 2. Install ### PyPI ```bash pip install mdrestyler mdrestyler --version mdrestyler --help ``` The wheel is also attached to each release: https://github.com/sagol/mdrestyler/releases ### Agent skill, nothing installed Copy `skills/mdrestyler/` into the agent's skills folder. From inside that folder the command is `python3 scripts/mdrestyler.py COMMAND`; it is the same command as the installed `mdrestyler COMMAND`. ```bash git clone --branch v0.1.1 https://github.com/sagol/mdrestyler.git cd mdrestyler python3 skills/mdrestyler/scripts/mdrestyler.py --help python3 skills/mdrestyler/scripts/mdrestyler.py verify ``` `verify` checks the skill folder against its manifest. `--version` prints the version, the source commit and the manifest's digest, which is what products built on mdrestyler pin. ### GitHub Action ```yaml - uses: sagol/mdrestyler@v0.1.1 with: command: check args: --profile voice chapters/01.md --strict ``` | Input | Default | Meaning | |---|---|---| | `command` | `check` | The mdrestyler command to run, such as check, rank, book, verify or profile. | | `args` | empty | The command's arguments as one string, split like a shell would. | | `working-directory` | `.` | The folder to run in; paths in args are relative to it. | It is a composite action that runs the skill folder's `scripts/mdrestyler.py` with the runner's `python3` (or `python`) and exits with the command's status, so a copy-guard hit (exit 1) fails the job. A book table in CI: ```yaml - uses: sagol/mdrestyler@v0.1.1 with: command: book args: manuscript --profile voice --list units.txt --within p90 ``` --- ## 3. Commands | Command | Does | |---|---| | `scan` | builds a profile, one per language, from `--own` and `--reference` EPUBs or `--own-book BOOK --eligibility FILE` | | `check` | measures drafts against `--profile FOLDER` and runs the copy guard; `--accepted BASE` for a revision of one unit; exit 1 on a shared run | | `rank` | orders two or more takes of one unit | | `book` | checks every unit a `--list` file names, one row each, with a restyle reading against `--within` | | `install` | installs a profile into a profile folder, keeping the earlier one under `history/` | | `profile validate` | reports a profile folder's status, or why it is not valid | | `verify` | checks the skill folder against its manifest; `--expect DIGEST` checks the digest too | ### 3.1 `mdrestyler scan` Syntax: `mdrestyler scan [--own EPUB] [--reference EPUB] [--own-book BOOK] [--eligibility FILE] --out OUT --work WORK [--min-words N] [--replace] [--max-expanded-mb N]` | Flag | Meaning | |---|---| | `--own EPUB` | a book by the author (may be quoted in the profile); repeatable | | `--reference EPUB` | a book by another writer (measured and described, never quoted); repeatable | | `--own-book BOOK` | the author's own Markdown book folder, read from its units (needs `--eligibility`) | | `--eligibility FILE` | the author's confirmation of the book's original units and passages | | `--out OUT` | required: folder for the profile files | | `--work WORK` | required: folder outside the book for the sample passages | | `--min-words N` | fewest words in a language to build its profile (default 3000) | | `--replace` | replace a profile already in `--out`, moving its files to `history/` first | | `--max-expanded-mb N` | expanded EPUB text the scan may read across all its books (default 64) | Give at least one book with `--own`, `--own-book` or `--reference`. `--own-book` and `--eligibility` go together. For each language with enough text it writes `author-profile..json`, `copy-guard..json` and a draft `AUTHOR_PROFILE..md` into `--out`, and `samples..md` into `--work`. Delete the samples once the profile is written. It prints a JSON report with `profiles` and `skipped`. Exit status: `0` built; `1` refused (DRM, a size limit, an existing profile, a folder inside a book, a destination that is a symbolic link, the same book given twice) or no language had enough text; `2` on errors, such as a damaged archive, an input that is not a regular file, or a language tag that names no language. ```bash mdrestyler scan --own mine.epub --reference theirs.epub --out profile --work work mdrestyler scan --own-book my-book --eligibility eligibility.json --out profile --work work ``` ### 3.2 `mdrestyler check` Syntax: `mdrestyler check --profile FOLDER CANDIDATE.md [MORE.md ...] [--lang LANG] [--json] [--strict] [--accepted BASE]` | Flag | Meaning | |---|---| | `--profile PROFILE` | the profile folder, or an `author-profile..json` file | | `--lang LANG` | profile language (default: from the draft's script) | | `--json` | print the report as JSON | | `--strict` | exit 1 when a measure is outside its range and not marked weak, or could not be compared with a profile scanned by another measure method | | `--accepted ACCEPTED` | a revision's own accepted base: the unit's exact accepted text before the revision | | `--rank` | check each file alone as a take of the same unit and order the takes (what `rank` runs) | | `--book BOOK` | check every unit in the book's reading order (what `book` runs) | | `--list LIST` | with `--book`: a file naming the units in reading order, one path per line, relative to the book | | `--within WITHIN` | with `--book`: `p50`, `p90` (default), `max` of the narration calibration, or a number | Without `--lang`, the language is the one profile in the folder whose recorded scripts (Latin, Cyrillic) include the draft's; when several profiles do, pass `--lang`. Exit status: `0` measured; `1` when the copy guard finds a run (or, with `--strict`, a measure is outside and not marked weak, or the profile was scanned by another measure method, so a target could not be compared); `2` on errors, including a profile or guard that is not valid. ```bash mdrestyler check --profile my-book/voice chapter-01.md mdrestyler check --profile my-book/voice chapter-01.md chapter-02.md --lang en --json --strict mdrestyler check --profile my-book/voice revised.md --accepted base.md ``` ### 3.3 `mdrestyler rank` Syntax: `mdrestyler rank --profile FOLDER TAKE1.md TAKE2.md [TAKE3.md ...] [--lang LANG] [--json]` Each file is one take of the same unit, checked alone. Takes with a copy-guard run come last, then the order follows the narration distance, the voice distance and the number of measures outside. The order informs a reading and chooses nothing. `rank` needs two takes or more and no `--accepted`; check a single take with `check`. Exit status: `0` when the ranking is printed (a ranking informs; the per-candidate checks gate); `2` on errors. ```bash mdrestyler rank --profile my-book/voice take-1.md take-2.md take-3.md ``` ### 3.4 `mdrestyler book` Syntax: `mdrestyler book BOOK --profile FOLDER --list UNITS [--within p90] [--lang LANG] [--json]` The list names the units in reading order, one path per line relative to the book; blank lines and `#` lines are skipped. A unit outside the book, missing, named twice or not Markdown stops the table. Each unit gets one row: voice, narration and dialogue distances, where they fall among the source chapters, measures outside and copy-guard runs. A unit with no prose, such as a part title, is listed as not measured. The last column reads each unit's narration distance against a threshold: the narration calibration's 90th percentile, or `--within p50`, `max` or a number. *Beyond* means the unit's narration lies farther from the profile than the sources' own chapters mostly do, so read it first. *Within* means nearer. *By reading* means too little narration to measure, or no narration calibration. The column orders a reading; it decides nothing. The JSON keeps the selector and the exact value. Exit status: `0` when the table is printed; `2` when the table stops (a bad unit list or an invalid profile, for example). ```bash mdrestyler book my-book --profile my-book/voice --list units.txt --within p90 mdrestyler book my-book --profile my-book/voice --list units.txt --within p90 --json ``` ### 3.5 `mdrestyler install` Syntax: `mdrestyler install FOLDER [SOURCE] --lang LANG [--replace]` | Argument | Meaning | |---|---| | `FOLDER` | the profile folder to install into | | `SOURCE` | a folder a scan wrote, or another profile folder (default: the shipped default for `--lang`) | | `--lang LANG` | required: profile language, such as `en` or `ru` | | `--replace` | replace an installed profile other than the unedited default, keeping its files under `history/` | Installs `AUTHOR_PROFILE..md`, `author-profile..json` and, when present, `copy-guard..json`. The shipped default, unedited, is replaced freely. Anything else already installed is replaced only with `--replace`, and its files move to `FOLDER/history/