Skip to main content

manuscript-guard

CI Python 3.10+ Licence: MIT Status: alpha

Make every number in a scientific manuscript traceable to its source.

A number in a paper comes from one of three places: your results, the literature, or a convention of scientific writing. manuscript-guard holds a manuscript to that. Numbers from your analysis are bindings into a results file that your code writes, numbers from the literature are bindings into a ledger backed by stored sources, and anything else has to be justified. Change the analysis, run it again and rebuild, and every bound number in the manuscript and the supplement follows. A number with no source is a finding of the check, not something left for a reviewer to notice.

The analysis writes results; the manuscript binds to them and to a literature ledger; check runs fourteen gates against the journal's rules and a reporting checklist; build writes the .docx; import brings a co-author's Word edits back to the manuscript.

It is a command line tool written in Python, for a manuscript written in Markdown and built to a Word document. The checks are deterministic code: they run offline and in CI and give the same answer every time. No gate asks a model anything. Two of them read a recorded review, of each figure and of the manuscript, which a person or a model may have written: the record is what the gate reads, and a person answers its major findings (principles). Skills and hooks for Claude Code, Codex and other agent tools are optional, and help with the parts that need judgement.

What it catches

Each finding names the stage from which it fails the run. Before that stage it is printed and counted, and the run passes: a new project starts at design, where the manuscript can wait (stages).

What went wrong What check names Fails from
A number was typed into the text where a result should be bound the number, with its line and column drafting
A results file was edited by hand the file, which no longer matches what the analysis wrote analysis
The script that wrote a results file, or an input it declared, changed afterwards which of them, and the script to run again analysis
A value taken from a paper is not in the sentence quoted as evidence for it the value and the quote; the quote itself has to be in the stored source drafting
A number was typed into text that a figure draws the line of the figure's script drafting
The analysis changed after the Methods were last read against it the files that changed internal-review
A reporting checklist item (STROBE, CONSORT, PRISMA and others) is not addressed each item still open internal-review
The journal's word limit, a required section or a required statement is missed which one internal-review
A reply to a reviewer claims a revision that was not made the point submission
A number sits in TeX that Word would silently drop the piece of TeX and its line, where pandoc is installed; build refuses it too drafting

check knows that a results file is out of date from digests: of the script that wrote it, and of the inputs that script declared. It does not follow imports, so a change in a helper module fails the run only where the script lists that module among its inputs. Left unlisted, a source file under analysis/ that is newer than the results gets a warning, and the run passes. manuscript-guard verify asks the other question. It runs the analysis again into a scratch copy and compares every value, which takes as long as the analysis does, and is what catches a result that changed while its file did not.

This is the finding for the first of those, on the worked example, after one binding in the abstract was replaced by the number it stood for. The line that opens the output and the warnings that follow the finding are left out:

manuscript-guard check prints: FAIL G2 manuscript/main.md:11:17, '4,000' is not bound to any source, with the line it is on and a hint to bind it with a results or literature key.

And for the second, after one value in a results file was changed by hand. ... stands for a line left out, and three more findings follow from the same edit:

  [FAIL] G1 results/01_disproportionality.json
         01_disproportionality.json has been modified since the analysis wrote it
         ...
         hint: results are machine-written; change the analysis and re-run it rather than editing this file

How it works

The manuscript source is Markdown. Numbers appear in it as bindings:

The database contained {{results.cohort.n_reports}} reports, of which
{{results.cohort.n_drug_reports}} named example-drug. The reporting odds ratio was
{{results.ror.point}} (95% CI {{results.ror.ci_low}} to {{results.ror.ci_high}}).

Your analysis publishes those values through an emitter, which records where they came from. There is one for Python and one for R, and anything that can write JSON can take part:

from manuscript_guard.emit import Emitter

em = Emitter(__file__, inputs=["data/reports.csv"])
em.value("cohort.n_reports", 4000)
em.value("ror.point", 3.4211, digits=2)
em.write()

Then two commands do most of the work:

manuscript-guard check     # every gate, against the source
manuscript-guard build     # the .docx, with live Zotero citations

check reads the source, where a binding is still visible, and not the rendered text, where every number looks alike. The rule is short: in manuscript source, a bare number is a defect unless it is a recognised convention (a 95% confidence interval) or a pointer (Table 1). The check also runs the other way: a value the analysis declares as quoted, which nothing quotes, fails too.

build writes the .docx from the Markdown every time, so the document is never edited and nothing is carried across by hand. With Zotero open it writes live Zotero citation fields that Word's plugin adopts. Without it, --offline formats the citations from a committed references.bib, which is what CI and a co-author without your library get.

What is checked

Gate Checks
G1 results are not older than the code or data that produced them
G2 every number is classified, and every declared value is quoted
G3 numbers in a figure's output and in its source trace back to results
G4 word counts, required sections and required statements match the target journal
G5 every reporting-checklist item is addressed, or excluded with a reason
G6 model artefacts, AI phrasing, and unsupported appeals to authority
G7 citations resolve and are pinned; every literature quote is in its source, and every value in its quote
G8 one quantity is not emitted twice under two names
G9 the analysis has not changed since the Methods were last read against it
G10 every figure has a current review by someone who looked at it
G11 a recorded panel has reviewed the manuscript, and its major findings are answered
G12 there was an analysis plan, and its sections say something
G13 every reviewer point is answered, and every claimed revision really happened
G14 an abbreviation is defined once, before it is used, the manuscript keeps to the terms its author declared, and it is spelt in one English (warnings only)

A finding also carries one of two labels that are no gate of their own: G0, for a file of the project that cannot be used as it stands, and BUILD, for what the build would refuse or warn of.

You do not have to satisfy every gate on the first day. Each finding declares the stage at which it starts to matter, from design to submission, and until then it is printed and counted without failing the run: see stages. What each gate guarantees and why it is built that way is in principles.

Install

Python 3.10 or later:

pip install manuscript-guard
manuscript-guard --version

To build a .docx you also need pandoc. Zotero, R, and pdftotext or pypdf for reading PDFs, are needed only for particular things, and the tool says which when you reach it. Installing and upgrading has the table of optional tools, the upgrade commands, how to install from the repository, and the R emitter.

Quick start

Start a paper:

manuscript-guard init my-paper

That writes a project with a paper.yaml, an analysis plan to fill in, a manuscript and an AGENTS.md that gives any agent working there the rules on one page.

Or run the worked example first. example/ is a synthetic pharmacovigilance study that exercises every gate but G13, having no revision round. It is in the repository and not in the installed package, so it needs a clone, a Python that has manuscript_guard installed, and matplotlib for its figure:

git clone https://github.com/BasileChretien/manuscript-guard
cp -r manuscript-guard/example my-example && cd my-example
python analysis/00_simulate.py && python analysis/01_disproportionality.py && python figures/forest.py
manuscript-guard check
manuscript-guard build --offline     # writes build/manuscript.docx and build/supplementary.docx

Then type a number over one of the bindings in manuscript/main.md and run check again. A different matplotlib version draws a slightly different figure, and check then lists the figure's recorded review as stale; that is INFO until the internal-review stage.

When a finding surprises you, manuscript-guard explain manuscript/main.md prints every number in the file and the rule that classified it.

Commands

Command What it does
init scaffold a new manuscript project
check run every gate; --submission holds the manuscript to submission standards
bind show every unbound number and how to give it a source
explain show how each number in a file was classified
verify re-run the analysis and check it still produces the recorded results
build produce the .docx; --annotated colours every number by what backs it
render substitute the bindings and stop there
stages what each stage means and what binds at it
journal list journal profiles, or start one from the annotated template
fetch download a reporting guideline's own checklist document
transcribe build checklist profiles from those documents
checklist write the completion file for a checklist
sync-bib rewrite references.bib from Zotero
methods check or record that the Methods were read against the code
review show where the review panel stands; --run has it read by the models you list
import bring a co-author's Word edits back into the manuscript source
respond open a revision round, or write the point-by-point response
submit assemble the submission pack
audit check the numbers of a paper that was not written this way against existing outputs
install-skills copy the skills to a folder an agent tool reads

Each takes --help. verify is a separate command because it executes your analysis, which a gate never does, and because it takes as long as the analysis does.

Agent tools

The pip package is the whole guarantee and needs nothing else. An agent tool adds two things: skills, for the parts that need judgement, and hooks, which catch a mistake at the moment it is made. Agent tools says what each tool enforces and what it does not.

The Claude Code plugin

This repository is its own plugin marketplace:

claude plugin marketplace add BasileChretien/manuscript-guard
claude plugin install manuscript-guard@manuscript-guard

Fourteen skills. Start with project-setup; most of the others name the finding codes that should send you to them.

Skill For
project-setup starting a paper project, and the daily loop from analysis to .docx
results-binding publishing values from the analysis, and turning a red number into a bound one
analysis-plan writing the plan before the analysis, and recording deviations from it
manuscript-writing prose that reads as written
methods-writer Methods that describe the code that was actually run
literature-verify a number from a paper, with its verbatim quote and stored source
figure-review looking at a rendered figure and recording what was seen
journal-profile choosing a journal with the author, and encoding its rules
reporting-checklist STROBE, CONSORT, PRISMA and the rest, retrieved rather than remembered
review-panel an internal review panel, recorded and answered
word-roundtrip a co-author's Word edits, back into the source
reviewer-response the point-by-point response to a journal, checked against the revision
submission-pack everything the journal asks for, and the covering letter
paper-audit a paper that was not written with this toolkit

Four hooks: one line on the project's state when a session starts, a refusal to edit files that are machine-written, a note on the numbers just saved in a manuscript file, and the submission check before a command that looks like a submission.

Codex

Codex installs the same plugin, with the same skills and hooks:

codex plugin marketplace add BasileChretien/manuscript-guard
codex plugin add manuscript-guard@manuscript-guard

By Codex's documentation, it runs a hook only after you have trusted it, under /hooks.

Gemini CLI, Mistral Vibe, Kimi Code CLI and other tools

By their own documentation these read skills from a folder, and one command copies the fourteen there:

manuscript-guard install-skills              # for you, in every project: ~/.agents/skills
manuscript-guard install-skills --project    # for one paper: .agents/skills in that project

There are no hooks under these tools. check, build and submit hold as they do everywhere.

Skills Hooks
Claude Code plugin four
Codex plugin four, once you have trusted them
Gemini CLI, Mistral Vibe, Kimi Code CLI copy none

More

Installing and upgrading upgrades, optional tools, the R emitter
Stages which findings bind when, from the analysis plan to submission
Principles what the check guarantees, and why it is built this way
Agent tools Claude Code, Codex and the others: installing, updating, what each enforces
A review panel read by several models internal review by people, an agent, or models from several providers
Auditing a paper you already wrote one command for a manuscript with no bindings, and how little a match means
DESIGN.md the architecture, the reasons for its decisions, and the known gaps
ATTRIBUTION.md the reporting guidelines' licences, and the one data file derived from another work

Status

Alpha. Its author has written one real manuscript with it, and the gates still change from week to week: interfaces, file formats and what a gate reports can change without a migration path. Every round of review so far has found something the round before had opened up.

A passing check means that no finding due at the project's stage is open. At submission that is what the tables above describe; at an earlier stage the findings not yet due are printed and counted, and the run still passes. Neither is evidence that a paper is right. What the toolkit cannot see is listed under "Known gaps" in DESIGN.md, because a gate whose limits are undocumented gets trusted beyond them.

The most useful contribution now is a case where a gate is wrong, in either direction: CONTRIBUTING.md says how.

Citing

If you use manuscript-guard for a paper, the "Cite this repository" button on GitHub gives the reference, from CITATION.cff.

Licence

MIT.

Metadata

Release files for manuscript-guard 0.2.432

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for manuscript-guard 0.2.432
File Size Uploaded
manuscript_guard-0.2.432.tar.gz 1.7 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for manuscript-guard 0.2.432
File Interpreter ABI Platform
manuscript_guard-0.2.432-py3-none-any.whl Python 3 none any Details

Total release size: 2.4 MB

Release files / manuscript_guard-0.2.432.tar.gz

Download URL manuscript_guard-0.2.432.tar.gz
Size 1.7 MB
Tags Source
SHA-256 checksum
How to use checksums
d80fdaef788ce9f0166b35eba24655b69037b36dad3dcf21bb8c8a94285d2503
BLAKE2b-256 checksum
How to use checksums
180898104901910d4163b0500f63d5d9be892ab1b467fdbaeff31424de336b01
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.

Transparency log

Release files / manuscript_guard-0.2.432-py3-none-any.whl

Download URL manuscript_guard-0.2.432-py3-none-any.whl
Size 733.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
574c08fa36b0d7eaccab81ea4629a954b36a47b9ad4203e545a7ef84e6397531
BLAKE2b-256 checksum
How to use checksums
acf09e1c12c8518861a858947a0e9ce1d3bd86a4c419d1645159c7b27d2df1b3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.432 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page