关于 r-cran-extrachecks
帮助 R 包开发者为 CRAN 提交做准备,系统检查常规检查工具可能遗漏的审查要求。它按清单审阅文档、元数据、示例和链接,并在获准后实施修正。
主要功能
- 01按 CRAN 清单逐项检查
- 02审阅 DESCRIPTION 和文档要求
- 03检查 README、链接及打包文件
- 04提出修复并经批准后修改
- 05核验修改结果
适用场景
- 01准备 R 包首次提交 CRAN
- 02处理 CRAN 重新提交前的审查要求
- 03检查导出函数的返回值和示例文档
- 04排查 URL、版权或许可问题
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ posit-dev/ skills --skill r-cran-extrachecks安装后在 Claude Code 中输入/r-cran-extrachecks确认已加载。
详细介绍
CRAN 额外检查
帮助 R 包开发者为提交到 CRAN 做好准备,系统地检查 CRAN 审核人员会执行、但 devtools::check() 不会发现的常见临时要求。
工作流程
- 初步评估:询问用户这是首次提交还是重新提交
- 执行标准检查清单:逐项进行检查(见下文)
- 找出问题:检查文件时记录具体问题
- 提出修复方案:针对发现的每个问题提出具体修改建议
- 实施修改:仅在用户批准后编辑
- 验证:确认所有修改均已完成
CRAN 标准准备检查清单
按顺序系统地检查以下项目:
- 创建 NEWS.md:如果文件尚不存在,运行
usethis::use_news_md() - 创建 cran-comments.md:如果文件尚不存在,运行
usethis::use_cran_comments() - 检查 README:
- 确保其中包含在包被 CRAN 接纳后仍有效的安装说明(通常为
install.packages("pkgname"))。 - 检查其中是否包含相对链接。这类链接在 GitHub 上有效,但会被 CRAN 标记。请使用指向包文档的完整 URL,或删除这些链接。
- README 是否清楚说明了包的用途和功能?
- 重要:如果 README.Rmd 存在,只编辑 README.Rmd(README.md 会被覆盖),然后运行
devtools::build_readme()重新生成 README.md
- 确保其中包含在包被 CRAN 接纳后仍有效的安装说明(通常为
- 校对 DESCRIPTION:仔细检查
Title:和Description:字段(详见下方指南) - 检查函数文档:确认所有导出的函数都有
@return和@examples(详见下方指南)。请注意,S3 方法若仅使用#' @export编写文档,则属于豁免情况:这类方法不会生成.Rd文件,因此不要求包含这两个标签 - 核实版权持有者:检查
Authors@R:是否包含带有[cph]角色的版权持有者 - 检查捆绑文件的许可:检查任何包含的第三方文件的许可情况
- 运行 URL 检查:使用
urlchecker::url_check()并修复发现的问题
CRAN 详细检查
文档要求
返回值文档(严格执行)
CRAN 现在严格要求为所有导出的函数编写 @return 文档。使用 roxygen2 标签 @return 说明函数返回的内容。
- 即使函数标记了
@keywords internal,也必须编写 - 即使函数不返回任何内容,也必须编写——可注明
@return None或类似内容 - 每个导出的函数都必须包含此文档
这些规则仅适用于带有 .Rd 文件的函数。只有当代码块包含文档内容(标题或描述)时,roxygen2 才会创建 .Rd 文件。仅包含 #' @export 的代码块会将函数添加到 NAMESPACE,但不会生成 .Rd 文件,因此 CRAN 的文档检查无内容可检查。这是 S3 方法的惯用模式:
#' @export
print.my_class <- function(x, ...) {
cat("my_class object\n")
invisible(x)
}
此类方法无需编写 @return 或 @examples,且 R CMD check 不会将其标记为缺少文档(注册的 S3 方法不在未记录对象检查范围内)。
- 仅当代码块中只有
@export(或@exportS3Method)时,才适用此豁免。添加标题、@param、@rdname、@describeIn或任何其他文档内容后,roxygen2 就会生成.Rd文件,函数必须满足所有文档规则,包括@return。 - 不要将这些方法与 S3 泛型本身混淆(例如,
my_print <- function(x, ...) UseMethod("my_print"))。新导出的泛型是需要编写文档的普通导出函数,因此仍需包含@return和@examples。 - 通过
@rdname或@describeIn与泛型共用页面的方法遵循与泛型相同的规则:合并后的.Rd只需包含一次所需标签,无需为每个方法重复添加。
示例:
# Missing @return - WILL BE REJECTED
#' Calculate sum
#' @export
my_sum <- function(x, y) {
x + y
}
# Correct - includes @return
#' Calculate sum
#' @param x First number
#' @param y Second number
#' @return A numeric value
#' @export
my_sum <- function(x, y) {
x + y
}
# For functions with no return value
#' Print message
#' @param msg Message to print
#' @return None, called for side effects
#' @export
print_msg <- function(msg) {
cat(msg, "\n")
}
导出函数的示例
如果导出函数有实际意义的返回值,几乎肯定需要 @examples 部分。使用 roxygen2 标签 @examples。
- 即使函数标记了
@keywords internal,也必须编写 - 纯粹用于产生副作用的函数(例如创建目录)可以例外
- 示例必须可执行
- 仅使用
@export的 roxygen 代码块中的 S3 方法没有.Rd文件,因此无需示例(见上文)
带有示例的未导出函数
如果为未导出的函数编写 roxygen 示例,必须执行以下任一操作:
- 使用
:::记法调用:pkg:::my_fun() - 使用
@noRd标签来禁止创建.Rd文件
谨慎使用 \dontrun{}
只有在示例确实无法执行时(例如缺少其他软件、API 密钥等),才应使用 \dontrun{}。
- 如果要展示错误,请改用
try()包装调用 - 考虑使用自定义谓词(例如
googlesheets4::sheets_has_token()),并配合if ()代码块 - 有时可使用
interactive()作为条件 - 较长的示例(> 5 秒)可使用
\donttest{}
切勿在示例中注释掉代码
# BAD - Will be rejected
#' @examples
#' # my_function(x) # Don't do this!
CRAN 的指导原则:“示例/代码中的代码行不应被注释掉。理想情况下,应寻找可定期执行和检查的简单示例。”
使用建议包保护示例
对于需要建议包的整个示例部分,请使用 @examplesIf:
#' @examplesIf rlang::is_installed("dplyr")
#' library(dplyr)
#' my_data %>% my_function()
对于示例中的单个代码块:
#' @examples
#' if (rlang::is_installed("dplyr")) {
#' library(dplyr)
#' my_data %>% my_function()
#' }
DESCRIPTION 标题字段
CRAN 对 Title 字段有严格要求:
使用标题式大小写
除 ‘a’、‘the’ 等冠词外,所有单词首字母均大写。可使用 tools::toTitleCase() 辅助格式化。
避免冗余
常见的易触发警告的短语:
- “A Toolkit for” → 删除
- “Tools for” → 删除
- “for R” → 删除
示例:
# BAD
Title: A Toolkit for the Construction of Modeling Packages for R
# GOOD
Title: Construct Modeling Packages
# BAD
Title: Command Argument Parsing for R
# GOOD
Title: Command Argument Parsing
为软件/包名称加引号
所有软件和 R 包名称都要用单引号括起来:
# GOOD
Title: Interface to 'Tiingo' Stock Price API
长度限制
标题应少于 65 个字符。
DESCRIPTION 字段
切勿以禁止使用的短语开头
CRAN 会拒绝以下开头的描述:
- "This package"
- 包名称
- "Functions for"
# BAD
Description: This package provides functions for rendering slides.
Description: Functions for rendering slides to different formats.
# GOOD
Description: Render slides to different formats including HTML and PDF.
扩写为 3–4 个句子
单句描述不够充分。请更全面地说明:
- 软件包的功能
- 它可能有用的原因
- 它有助于解决的问题类型
# BAD (too short)
Description: Render slides to different formats.
# GOOD
Description: Render slides to different formats including HTML and PDF.
Supports custom themes and progressive disclosure patterns. Integrates
with 'reveal.js' for interactive presentations. Designed for technical
presentations and teaching materials.
软件名称加引号,函数名称不加
# BAD
Description: Uses 'case_when()' to process data.
# GOOD
Description: Uses case_when() to process data with 'dplyr'.
软件、软件包和 API 名称使用单引号(包括 'R')。函数名称不加引号。
展开所有首字母缩略词
所有首字母缩略词在首次出现时都必须完整展开:
# BAD
Description: Implements X-SAMPA processing.
# GOOD
Description: Implements Extended Speech Assessment Methods Phonetic
Alphabet (X-SAMPA) processing.
出版物标题才使用双引号
双引号仅用于出版物标题,不用于短语或强调:
# BAD
Description: Handles dates like "the first Monday of December".
# GOOD
Description: Handles dates like the first Monday of December.
URL 和链接验证
所有 URL 都必须使用 HTTPS
CRAN 要求所有 URL 使用 https:// 协议。HTTP 链接会被拒绝。
# BAD
URL: http://paleobiodb.org/
# GOOD
URL: https://paleobiodb.org/
不得使用会重定向的 URL
CRAN 会拒绝重定向到其他位置的 URL。拒绝示例:
Found the following (possibly) invalid URLs:
URL: https://h3geo.org/docs/core-library/coordsystems#faceijk-coordinates
(moved to https://h3geo.org/docs/core-library/coordsystems/)
使用 urlchecker 软件包
# Find redirecting URLs
urlchecker::url_check()
# Automatically update to final destinations
urlchecker::url_update()
忽略发布后才会生效的 URL
有些 URL 目前无法访问,但软件包发布到 CRAN 后便会生效。此类 URL 不应更改:
- CRAN 徽章 URL(例如,
https://cran.r-project.org/package=pkgname) - CRAN 状态徽章(例如,
https://www.r-pkg.org/badges/version/pkgname) - CRAN 检查结果(例如,
https://cranchecks.info/badges/pkgname) - 发布后才会部署到 r-universe 或 pkgdown 网站上的软件包文档 URL
如果 urlchecker::url_check() 标记了这些 URL,请保持原样。这些预期 URL 会在软件包发布到 CRAN 后生效。
检查无效的文件 URI
README 中的相对链接必须在软件包构建后仍然有效。常见问题:
Found the following (possibly) invalid file URI:
URI: CODE_OF_CONDUCT.md
From: README.md
这是因为文件位于 .Rbuildignore 中。解决方案:
- 从
.Rbuildignore中移除该文件 - 使用
usethis::use_code_of_conduct(),它生成的章节不含相对链接
管理要求
版权所有者角色
始终在 Authors 字段中添加 [cph] 角色,即使你是唯一作者:
# Required
Authors@R: person("John", "Doe", role = c("aut", "cre", "cph"))
由 Posit 支持的软件包
对于属于 Posit 相关 GitHub 组织(posit-dev、rstudio、r-lib、tidyverse、tidymodels)的软件包,或由使用 @posit.co 邮箱地址的人维护的软件包,请将 Posit Software, PBC 列为版权所有者和资助方:
Authors@R: c(
person("Jane", "Doe", role = c("aut", "cre"),
email = "[email protected]"),
person("Posit Software, PBC", role = c("cph", "fnd"),
comment = c(ROR = "03wc8by49"))
)
LICENSE 年份
将 LICENSE 年份更新为当前提交年份:
# If LICENSE shows 2024 but submitting in 2026
# Update: 2024 → 2026
方法参考文献
CRAN 可能会询问:
如果有介绍软件包中所用方法的参考文献,请将其添加到 description 字段中……
如果没有参考文献,请回复邮件说明这一点。可以考虑在 cran-comments.md 中预先添加说明:
## Method References
There are no published references describing the methods in this package.
The package implements original functionality for [brief description].
需要检查的关键文件
按以下顺序系统地检查这些文件:
- DESCRIPTION:标题、描述、Authors@R、URL、许可证年份
- R/*.R:函数文档(
@return、@examples、@examplesIf、@noRd) - README.Rmd(如果存在):编辑此文件(而非 README.md),然后运行
devtools::build_readme() - README.md:检查安装说明、相对链接和 URL。仅在 README.Rmd 不存在时直接编辑
- cran-comments.md:给审核人员的预先说明
- NEWS.md:本次发布的版本说明
- .Rbuildignore:README 中引用的文件
常见修复模式
DESCRIPTION 标题:
# Before
Title: A Toolkit for the Construction of Modeling Packages for R
# After
Title: Construct Modeling Packages
DESCRIPTION 描述:
# Before
Description: This package provides functions for rendering slides.
# After
Description: Render slides to different formats including HTML and PDF.
Supports custom themes and progressive disclosure. Integrates with
'reveal.js' for interactive presentations.
函数文档:
# Before - Missing @return
#' Calculate total
#' @param x Values
#' @export
calc_total <- function(x) sum(x)
# After - Complete documentation
#' Calculate total
#' @param x Numeric values to sum
#' @return A numeric value representing the sum
#' @examples
#' calc_total(1:10)
#' @export
calc_total <- function(x) sum(x)
实用工具
tools::toTitleCase()- 使用规范的大小写格式化标题urlchecker::url_check()- 查找有问题的 URLurlchecker::url_update()- 修正会重定向的 URLusethis::use_news_md()- 创建 NEWS.mdusethis::use_cran_comments()- 创建 cran-comments.mddevtools::build_readme()- 从 README.Rmd 重新生成 README.mdusethis::use_code_of_conduct()- 添加不含相对链接的行为准则usethis::use_build_ignore()- 在 R 包构建中忽略文件usethis::use_package()- 向 DESCRIPTION 添加包依赖项usethis::use_tidy_description()- 整理 DESCRIPTION 的格式
最终验证清单
使用此清单确保提交前没有遗漏:
文件和结构
-
NEWS.md存在,并记录此版本的更改 -
cran-comments.md存在,并包含提交说明 - 如果存在 README.Rmd,则已编辑该文件(而非 README.md),并已运行
devtools::build_readme() - README 包含有效的安装说明(
install.packages("pkgname")) - README 不含相对链接(所有链接均为完整 URL,或已移除)
DESCRIPTION 文件
-
Title:使用标题式大小写 -
Title:不含多余短语(“A Toolkit for”“Tools for”“for R”) -
Title:中所有软件/包名称均以单引号括起 -
Title:少于 65 个字符 -
Description:不以“This package”、包名称或“Functions for”开头 -
Description:用 3–4 个句子说明用途和效用 -
Description:中的软件/包/API 名称均以引号括起(包括 'R'),但函数名称除外 -
Description:在首次提及时展开所有缩写 -
Description:仅对出版物标题使用双引号 -
Authors@R:包含带有[cph]角色的版权持有者 - 对于 Posit 包:包含
person("Posit Software, PBC", role = c("cph", "fnd"), comment = c(ROR = "03wc8by49")) - LICENSE 年份与当前提交年份一致
函数文档
- 所有具有
.Rd文件的导出函数都包含@return文档 - 所有具有实际返回值的已文档化导出函数都包含
@examples - 仅使用
@export标记的 S3 方法 roxygen 块可正确豁免(无需.Rd文件,也无需@return/@examples) - 由包添加的 S3 泛型均有完整文档(
@return、@examples),因为它们是普通的导出函数 - 示例部分不使用注释掉的代码
- 除非确有必要,否则示例避免使用
\dontrun{} - 需要建议包的示例使用
@examplesIf或if守卫 - 含有示例的未导出函数使用
:::表示法或@noRd
URL 和链接
- 已运行
urlchecker::url_check() - 所有 URL 均使用 https 协议(不含 http 链接)
- 不含会重定向的 URL(期望中的 CRAN 徽章 URL 除外)
- 期望中的 URL(如 CRAN 徽章等)保持原样
- README 中不含指向
.Rbuildignore文件的相对链接
可选但建议
- 如果担心方法引用问题,已在
cran-comments.md中添加预先说明 - 如果包含第三方文件,已审核随附文件的许可协议