npx claudepluginhub choxos/rpkgagent --plugin r-package-developmentThis skill uses the workspace's default tool permissions.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Delivers DB-free sandbox API regression tests for Next.js/Vitest to catch AI blind spots in self-reviewed code changes like API routes and backend logic.
This skill covers the complete CRAN submission process, from pre-submission preparation through to acceptance and post-release tasks. CRAN (Comprehensive R Archive Network) is the primary repository for R packages and has strict quality requirements.
@returns and @examples documentation\donttest{} sparingly)Every exported function must have:
#' Function Title
#'
#' @description
#' Detailed description of what the function does.
#'
#' @param x Description of parameter x
#' @param y Description of parameter y
#'
#' @returns A data.frame with columns:
#' \item{col1}{Description of column 1}
#' \item{col2}{Description of column 2}
#'
#' @examples
#' # Basic usage
#' result <- my_function(x = 1, y = 2)
#' print(result)
#'
#' # Advanced usage
#' result2 <- my_function(x = 1:10, y = 20)
#'
#' @export
my_function <- function(x, y) {
# implementation
}
Critical: Use @returns (not @return) for consistency with roxygen2 7.0+.
Package: packagename
Title: A Package That Does Amazing Things # Title case, < 65 chars, no period
Version: 0.1.0 # Must be > current CRAN version
Authors@R: c(
person("First", "Last", email = "email@example.com",
role = c("aut", "cre"),
comment = c(ORCID = "0000-0000-0000-0000")),
person("Another", "Author", role = "aut"),
person("Company Name", role = "cph") # Copyright holder
)
Description: Provides tools for amazing analysis. This package implements
novel algorithms and provides intuitive interfaces. Functions include
data processing, visualization, and reporting capabilities.
License: MIT + file LICENSE
Encoding: UTF-8
LazyData: true
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.3.0
URL: https://username.github.io/packagename/, https://github.com/username/packagename
BugReports: https://github.com/username/packagename/issues
Suggests:
testthat (>= 3.0.0),
knitr,
rmarkdown
VignetteBuilder: knitr
Config/testthat/edition: 3
Title field rules:
Description field rules:
For new submissions:
Version: 0.1.0
For updates (must be > CRAN version):
# If CRAN has 0.1.0, use:
Version: 0.1.1 # Bug fixes
Version: 0.2.0 # New features
Version: 1.0.0 # Major release
Development versions (not for CRAN):
Version: 0.1.0.9000 # Development version after 0.1.0
# Standard check
devtools::check()
# Check with remote checking (stricter)
devtools::check(remote = TRUE, manual = TRUE)
# Check with --as-cran flag
devtools::check(args = c('--as-cran'))
# Check on Windows builder (CRAN's Windows server)
devtools::check_win_devel() # R-devel
devtools::check_win_release() # R-release
devtools::check_win_oldrelease() # R-oldrelease
You'll receive an email with results in ~30 minutes.
# Install rhub
install.packages("rhub")
# Validate email first time
rhub::validate_email()
# Check on multiple platforms
rhub::check_for_cran()
# Specific platforms
rhub::check(platform = "windows-x86_64-devel")
rhub::check(platform = "ubuntu-gcc-release")
rhub::check(platform = "macos-highsierra-release-cran")
rhub::check(platform = "solaris-x86-patched")
# List available platforms
rhub::platforms()
Note: R-hub can be unreliable. GitHub Actions with r-lib/actions is often more reliable.
Most reliable multi-platform testing:
# Set up GitHub Actions
usethis::use_github_action("check-standard")
Tests on:
# Check all URLs in documentation and vignettes
urlchecker::url_check()
# Fix or explain any broken URLs
Common issues:
https://doi.org/ not http://dx.doi.org/Create cran-comments.md in package root:
## Test environments
* local R installation, R 4.4.0
* ubuntu 22.04 (on GitHub Actions), R-devel, R-release, R-oldrel-1
* windows-latest (on GitHub Actions), R-release
* macos-latest (on GitHub Actions), R-release
* win-builder (devel and release)
## R CMD check results
0 errors | 0 warnings | 1 note
* This is a new release.
## Downstream dependencies
There are currently no downstream dependencies for this package.
## Test environments
* local R installation, R 4.4.0
* ubuntu 22.04 (on GitHub Actions), R-devel, R-release, R-oldrel-1
* windows-latest (on GitHub Actions), R-release
* macos-latest (on GitHub Actions), R-release
## R CMD check results
0 errors | 0 warnings | 0 notes
## What's changed
This is a minor release that fixes bugs and adds new features:
* Fixed issue with X (#123)
* Added new function Y
* Improved documentation for Z
## Downstream dependencies
I have run R CMD check on downstream dependencies of my package.
All packages passed.
## R CMD check results
0 errors | 0 warnings | 1 note
* Checking CRAN incoming feasibility ... NOTE
Maintainer: 'First Last <email@example.com>'
New submission
Possibly misspelled words in DESCRIPTION:
MCMC (3:49)
PyMC (9:31)
These are not misspelled:
* MCMC is a standard acronym for Markov Chain Monte Carlo
* PyMC is the name of a Python library
# 1. Final checks
devtools::check()
devtools::check_win_devel()
rhub::check_for_cran()
urlchecker::url_check()
# 2. Build the package
devtools::build()
# 3. Submit to CRAN
devtools::submit_cran()
# This will:
# - Build the package
# - Run R CMD check
# - Ask for confirmation
# - Submit to CRAN via web form
If submit_cran() doesn't work:
devtools::build()You'll receive an email asking to confirm submission:
Typical timeline: 1-2 weeks, but can be longer during busy periods.
Problem:
checking R code for possible problems ... NOTE
my_function: no visible binding for global variable 'x'
my_function: no visible binding for global variable 'y'
Cause: Using NSE (non-standard evaluation) with dplyr, data.table, etc.
Solution:
# In R/globals.R
utils::globalVariables(c("x", "y", "z"))
# Or use .data pronoun
library(dplyr)
my_function <- function(df) {
df %>%
mutate(z = .data$x + .data$y)
}
Problem:
checking dependencies in R code ... NOTE
Namespace in Imports field not imported from: 'package'
Solution: Remove from DESCRIPTION or use somewhere:
#' @importFrom package function
Problem:
checking R files for non-ASCII characters ... NOTE
Solution: Use Unicode escapes:
# Bad
"Müller"
# Good
"M\u00fcller"
Problem:
checking examples ... ERROR
Solution: Wrap problematic examples:
#' @examples
#' # Basic example (always runs)
#' result <- my_function(x = 1)
#'
#' \donttest{
#' # Slow example (skipped on CRAN)
#' slow_result <- slow_function(x = 1:1000000)
#' }
#'
#' \dontrun{
#' # Requires authentication (never runs)
#' api_result <- call_api(key = "your-key")
#' }
Rules:
\donttest{}: Runs locally and on CI, skipped on CRAN (for slow examples)\dontrun{}: Never runs automatically (for examples needing setup)Problem:
checking dependencies in R code ... WARNING
'::' or ':::' imports not declared from:
'package'
Solution: Add to DESCRIPTION Imports and use:
#' @importFrom package function
Or declare in NAMESPACE:
importFrom(package, function)
Problem:
checking PDF version of manual ... WARNING
Solution: Fix .Rd formatting issues or use:
# In GitHub Actions
build_args: 'c("--no-manual")'
Problem:
checking re-building of vignette outputs ... WARNING
Solution: Ensure vignettes build:
devtools::build_vignettes()
# Check for missing packages in Suggests
Problem:
checking file modes ... NOTE
Solution: Fix permissions:
chmod 644 R/*.R
chmod 644 man/*.Rd
chmod 755 configure
Problem:
checking installed package size ... NOTE
installed size is X Mb
sub-directories of 1Mb or more:
data Y Mb
Solution:
tools::resaveRdaFiles("data")LazyData: true in DESCRIPTIONProblem: Package writes to home directory or modifies environment
Solution: Use temporary directories:
# Bad
write.csv(data, "~/mypackage/output.csv")
# Good
tmpdir <- tempdir()
write.csv(data, file.path(tmpdir, "output.csv"))
# For configuration
config_dir <- tools::R_user_dir("mypackage", which = "config")
if (!dir.exists(config_dir)) {
dir.create(config_dir, recursive = TRUE)
}
11. Suggested packages not declared:
# Conditional usage
if (requireNamespace("ggplot2", quietly = TRUE)) {
# Use ggplot2
} else {
message("Install ggplot2 for better plots")
}
12. Internet resources without checks:
# Check connectivity
check_connection <- function(url) {
tryCatch({
httr::GET(url, httr::timeout(5))
TRUE
}, error = function(e) {
message("Cannot connect to ", url)
FALSE
})
}
13. Testing failures:
# Skip tests on CRAN if they require internet/auth
testthat::skip_on_cran()
testthat::skip_if_offline()
14. Long-running tests:
# In tests/testthat.R
Sys.setenv("NOT_CRAN" = "true")
# In test files
testthat::skip_on_cran() # Skip slow tests
15. Missing LICENSE file:
# For MIT license
usethis::use_mit_license()
# Creates LICENSE and LICENSE.md
16. Undeclared S3 methods:
#' @export
print.myclass <- function(x, ...) {
# implementation
}
# In NAMESPACE (auto-generated by roxygen2)
S3method(print, myclass)
17. Examples too long:
\donttest{}18. Rd cross-references broken:
#' @seealso \code{\link{other_function}}
#' @seealso \code{\link[otherpackage]{their_function}}
19. Non-standard installation:
configure script for system dependencies20. Archived dependencies:
21. Data documentation missing:
#' Dataset Title
#'
#' @description Description of dataset
#'
#' @format A data frame with 100 rows and 5 variables:
#' \describe{
#' \item{var1}{Description of var1}
#' \item{var2}{Description of var2}
#' }
#' @source \url{https://example.com/data}
"dataset_name"
22. NAMESPACE conflicts:
# Don't export everything
#' @keywords internal
internal_function <- function() {}
23. Windows path issues:
# Use file.path() not paste
file.path("dir", "file.txt") # Good
# Not: paste("dir", "file.txt", sep = "/") # Bad
24. Encoding issues: Add to DESCRIPTION:
Encoding: UTF-8
25. Undeclared attachments:
# Don't use library() in package code
# Use :: or importFrom instead
dplyr::filter() # Good
# Not: library(dplyr); filter() # Bad
26. Examples with \dontrun only:
\donttest{} instead of \dontrun{} when possible27. Biased package names:
28. Missing return values:
#' @returns A numeric vector of length n
#' @returns NULL (invisibly) if no output
29. Improper TRUE/FALSE:
# Use TRUE/FALSE, not T/F
if (condition == TRUE) # Good
# Not: if (condition == T) # Bad
30. Unconventional directory structure:
31-40: Platform-specific code, parallel processing issues, memory leaks, C/C++ code problems, Fortran code issues, Java dependencies, system command calls, graphic device problems, locale-specific code, timezone issues
41-50: Partial argument matching, 1:length() issues, sapply() problems, dependency version constraints, circular dependencies, namespace pollution, documentation warnings, alias issues, keyword problems, cross-reference errors
If rejected, you'll get an email with issues. Fix them and resubmit:
## Resubmission
This is a resubmission. In this version I have:
* Fixed the DESCRIPTION title to be in title case
* Added \value sections to all exported functions
* Ensured all examples run without errors
* Fixed the NOTE about global variables by using utils::globalVariables()
## Test environments
...
Important:
After rejection, bump patch version:
# First submission
Version: 0.1.0
# After rejection
Version: 0.1.0 # Keep same version if resubmitting same release
# Or bump if making significant changes
Version: 0.1.1
If your package has downstream dependencies (packages that depend on yours):
# Install revdepcheck
install.packages("revdepcheck")
# Check reverse dependencies
revdepcheck::revdep_check(num_workers = 4)
# View results
revdepcheck::revdep_report()
# If issues found, contact maintainers
# 1. Create GitHub release
usethis::use_github_release()
# 2. Bump to development version
usethis::use_dev_version()
# This changes:
# Version: 0.1.0 -> Version: 0.1.0.9000
Check CRAN check results daily:
https://cran.r-project.org/web/checks/check_results_PACKAGENAME.html
Fix any issues that arise on CRAN's servers.
Problem: Package has warnings but submitter thinks they're acceptable
Fix: CRAN will auto-reject. Fix ALL warnings before submission.
Problem: Package works on Mac/Linux but fails on Windows
Fix: Use check_win_devel() and GitHub Actions before submission.
Problem: Examples assume files/data/authentication exist
Fix: Examples must be self-contained or use \dontrun{}.
Problem: Wait too long to respond to CRAN
Fix: Respond within 2 weeks or submission is archived.
Problem: Trying to argue that a NOTE is acceptable
Fix: Either fix it or provide a clear, technical explanation in cran-comments.md.
Problem: Missing @returns or @examples
Fix: Every exported function needs both.
Problem: Trying to submit 0.1.0 when CRAN has 0.1.0
Fix: Bump version to 0.1.1 or higher.
Problem: Package is 10+ MB
Fix: Compress data, use external data, or justify in cran-comments.md.
Problem: Importing 20+ packages
Fix: Consider if all are necessary. Each import is a dependency burden.
Problem: Violating policies unknowingly
Fix: Read https://cran.r-project.org/web/packages/policies.html
devtools::check() shows 0 errors, 0 warnings, 0 notes (or explained)check_win_devel() passesrhub::check_for_cran() or GitHub Actions passes@returns and @examplesurlchecker::url_check() passesGood luck with your CRAN submission!