checktor v0.1.0 Released - A Package Doctor for CRAN Submission Checks

checktor runs extra-CRAN diagnostic checks on R packages — catching the T/F literals, hardcoded seeds, DESCRIPTION formatting, missing tags, and policy snags that R CMD check leaves for a human reviewer to find.
software-releases
r-package
Author

James Balamuta

Published

June 24, 2026

The checktor package (GitHub, documentation) runs the extra checks that stand between a clean R CMD check and a clean CRAN submission. These are the requirements CRAN reviewers enforce by hand but the standard tooling never flags: T/F used in place of TRUE/FALSE, hardcoded set.seed() calls, a Description: field that opens with “This package”, a missing \value{} tag, a tarball bloated past the size limit, an http:// URL that should be https://. None of these stop R CMD check. All of them can stop a submission.

Anyone who has submitted to CRAN knows the rhythm: devtools::check() comes back with zero errors, zero warnings, zero notes, you submit with a clear conscience, and a day later an email arrives explaining that your title needs to be in title case and your one exported helper is missing an @return tag. The rules are real, but they live scattered across the CRAN Repository Policy, the R Packages book, and a long memory of past reviewer feedback. checktor gathers that folklore into a single function you can run before you hit submit.

I leaned into the medical metaphor a little, because it made the API read the way the work feels. You run a checktor() examination, get a diagnosis, ask for a prescribe()-d set of treatments, and generate a health_report() to keep on file. The package is, quite literally, a doctor for your package.

A checkup

The headline function, checktor(), examines a package directory and reports back across five categories — code patterns, the DESCRIPTION file, documentation, general structure, and CRAN policy:

library(checktor)

# Examine the package in the current working directory
results <- checktor()

The printed diagnosis is a summary you can read at a glance:

── Package Doctor - Diagnosis Summary ──────────────────────────────
Patient: '.'
Doctor version: 0.1.0

CODE ISSUES: 1 failing check
DESCRIPTION ISSUES: HEALTHY
DOCUMENTATION ISSUES: HEALTHY
GENERAL ISSUES: 1 failing check
POLICY ISSUES: HEALTHY

! Overall health: NEEDS ATTENTION (2 issues)

When you want more than a verdict, prescribe() turns each finding into a concrete remedy, and health_report() writes the whole thing out as Markdown, HTML, or plain text for a paper trail:

# Treatment recommendations for everything that turned up
prescribe(results)

# A report you can save alongside cran-comments.md
cat(health_report(results, format = "markdown"), sep = "\n")

For continuous integration, checkup() collapses the diagnosis down to a single TRUE/FALSE so a failing check can fail a build:

# Stop CI if checktor finds anything worth fixing
if (!checkup()) stop("checktor found issues")

Looking at code, not text

The part of checktor I am most pleased with is how it reads your sources. Earlier generations of this kind of tool lean on regular expressions, which means they cannot tell a real set.seed(42) from the string "set.seed(42)" in a help topic, or a T flag from a T inside a column name. checktor parses each R/*.R file into its abstract syntax tree via xmlparsedata and xml2, then runs XPath queries against the tree. A pattern written inside a string literal or a comment is a different kind of node than a function call, so it simply never matches. The same care extends to the rest of the package: DESCRIPTION is read with read.dcf() rather than line by line, so multi-line Title: and Description: fields are fully visible, and .Rd files are walked with tools::parse_Rd() so structured content like \value{} and \examples{\dontrun{...}} is inspected by tag rather than grepped.

checktor is meant to sit alongside R CMD check and lintr, not to replace either of them. Run all three before a submission and you have covered the automated rules, the style conventions, and the human-enforced CRAN requirements in one pass. For a tour of every diagnostic and how to author your own, see the Getting Started and Writing Your Own Checks articles in the package documentation.

Installation

checktor is available now from GitHub, with a CRAN submission on the way:

# install.packages("remotes")
remotes::install_github("coatless-rpkg/checktor")

For details, see the checktor news file entry below:

checktor news file entry for version 0.1.0

Features

  • Added checktor() as the top-level orchestrator, running five categories of diagnostics (code, DESCRIPTION, documentation, general, CRAN policy) against an R package directory.
  • Added the checkup() boolean wrapper for CI use, prescribe() for treatment recommendations, and health_report() for Markdown / HTML / text reports.
  • All code-side diagnostics run XPath queries against the parsed abstract syntax tree via xmlparsedata and xml2. Documentation-side checks walk .Rd files via tools::parse_Rd(). The DESCRIPTION file is parsed with base::read.dcf().

GitHub Repository