jsslintr: check JSS manuscript style from R (and everywhere else)

2026-08-23 · Manuel Koller · source

If you have ever submitted to the Journal of Statistical Software, you know the drill: the science is done, the package works, and then a revision round arrives about \pkg{} markup, capitalization in section titles, citation macros, and a doi field missing from half the bibliography. None of it improves the paper; all of it costs a round trip.

jsslintr, now on CRAN, checks a JSS-format manuscript (.tex, .Rnw, or .Rmd plus its .bib) against 62 deterministic rules derived from the journal's published style guide — before an editor ever sees it:

install.packages("jsslintr")
library(jsslintr)
jsslint("paper.Rnw")      # report violations with positions + fixes
jssfix("paper.Rnw")       # apply the auto-fixable subset

The same engine — one Rust core — also ships as a command-line tool (cargo install jsslint-cli), Python packages (pip install jss-style-checker or jsslint), an npm/WASM module, a VS Code extension, a GitHub Action for CI on package vignettes, and a browser app that runs entirely client-side — your manuscript never leaves your machine. All channels produce byte-identical output; that parity is enforced in CI.

The interesting part: the accuracy is measured

A linter's real cost is false positives. Instead of hoping the rules are right, the project maintains a pinned evaluation corpus of 254 real JSS-format manuscripts (mostly CRAN vignettes of published JSS papers) and measures every rule against it: precision is currently 97.2% over 20,060 adjudicated violation instances, recall 80.7% against a hand-annotated ground-truth corpus, and the README badges regenerate from the evaluation database on every push. Rules that could not reach 90% precision were narrowed or publicly retired.

Honesty note, since it is unusual: the code, tests, and evaluation tooling were written by large language models under human direction — the human role was setting requirements, adjudicating evaluation labels, and verifying measured behavior rather than reviewing lines of code. The measurement apparatus above (plus byte-parity between two independently implemented engines) is what makes that workable, and every process artifact is in the public repository. A full write-up of the methodology and the empirical results is linked from the README.

For reviewers and editors, too

Reviewer mode aggregates the findings into a per-category PASS/FAIL compliance summary:

jss-lint --mode reviewer paper.tex

so questions of form can be separated from questions of content in one glance.

jsslintr and jss-lint are an independent, third-party project — not affiliated with, endorsed by, or connected to the Journal of Statistical Software, its editors, or its publisher.

Bug reports — especially false positives, which feed directly into the precision measurement — are very welcome on GitHub.