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.
Implements structured self-debugging workflow for AI agent failures: capture errors, diagnose patterns like loops or context overflow, apply contained recoveries, and generate introspection reports.
This skill covers the fundamental structure of R packages, from directory layout to the five distinct package states. Understanding package structure is critical for proper package development.
R packages exist in five different states throughout their lifecycle:
.tar.gz file created by R CMD build. Single file for distribution..tgz on macOS, .zip on Windows). No source code.library() loads from.library() or loadNamespace().# State transitions:
# Source -> Bundled: R CMD build / devtools::build()
# Bundled -> Binary: R CMD INSTALL --build
# Source/Bundled -> Installed: R CMD INSTALL / install.packages()
# Installed -> In-memory: library() / loadNamespace()
Understanding these states helps you know:
.Rbuildignore)The package metadata file. Every package MUST have this.
Package: mypackage
Title: What the Package Does (One Line, Title Case)
Version: 0.1.0
Authors@R:
person("First", "Last", , "email@example.com", role = c("aut", "cre"),
comment = c(ORCID = "YOUR-ORCID-ID"))
Description: What the package does (one paragraph).
License: MIT + file LICENSE
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.3.1
Imports:
dplyr (>= 1.0.0),
rlang (>= 1.0.0)
Suggests:
testthat (>= 3.0.0),
knitr,
rmarkdown
Config/testthat/edition: 3
The namespace file. Controls what your package exports and imports.
CRITICAL: Never edit this file by hand! Use roxygen2 to generate it.
# Generated by roxygen2: do not edit by hand
export(my_function)
exportPattern("^[^\\.]")
importFrom(dplyr,filter)
importFrom(rlang,"%||%")
Directory containing all your R code files. Required if your package has any functions.
Rules for R/ directory:
.R files (case-sensitive on some platforms)R/zzz.R for .onLoad() and .onAttach()R/
├── data.R # Data documentation
├── import-standalone.R # Standalone imported utilities
├── my-package-package.R # Package-level documentation
├── utils.R # Utility functions
├── main-feature.R # Main functionality
└── zzz.R # .onLoad and .onAttach hooks
Directory containing documentation files (.Rd format). Required for packages with documentation.
CRITICAL: Never edit .Rd files by hand! Use roxygen2 to generate them.
man/
├── mypackage-package.Rd # Package overview
├── my_function.Rd # Function documentation
└── my_data.Rd # Data documentation
Contains exported data objects (.rda or .RData files).
# Create with:
usethis::use_data(my_dataset, overwrite = TRUE)
Important details:
.rda format only (use save() with compress = "xz" for best compression)data(my_dataset) or direct referenceR/data.Rdata() callContains all package tests.
tests/
├── testthat/
│ ├── helper-data.R # Test helpers (loaded before tests)
│ ├── setup.R # Setup run before tests
│ ├── test-feature1.R # Test files (must start with "test-")
│ └── test-feature2.R
└── testthat.R # Entry point (loads testthat and runs tests)
Setup with:
usethis::use_testthat(3) # 3rd edition
Long-form documentation and tutorials.
vignettes/
├── articles/ # Articles (not installed with package)
│ └── supplementary.Rmd
└── introduction.Rmd # Vignettes (installed with package)
# Create with:
usethis::use_vignette("introduction")
usethis::use_article("supplementary")
Key differences:
Files to be installed as-is. Only inst/ contents are copied to installation.
inst/
├── CITATION # How to cite the package
├── extdata/ # Example/raw data files
│ ├── example.csv
│ └── sample.json
├── scripts/ # Helper scripts
│ └── setup.R
└── templates/ # Template files
└── report.Rmd
Access inst/ files with:
system.file("extdata", "example.csv", package = "mypackage")
CRITICAL: Do NOT put a DESCRIPTION or NAMESPACE file in inst/ - this will break your package!
Scripts for creating package data objects. Not included in bundle.
data-raw/
├── DATASET.R # Script to create data/DATASET.rda
└── prepare_examples.R # Script for inst/extdata/ files
# Setup with:
usethis::use_data_raw("DATASET")
Pattern:
# data-raw/DATASET.R
library(tidyverse)
DATASET <- read_csv("source.csv") %>%
clean_names() %>%
filter(year >= 2020)
usethis::use_data(DATASET, overwrite = TRUE)
Compiled code (C, C++, Fortran).
src/
├── Makevars # Unix build configuration
├── Makevars.win # Windows build configuration
├── mycode.cpp # Source files
└── RcppExports.cpp # Auto-generated (Rcpp)
Files/directories to exclude from package bundle. Uses regex patterns (NOT glob patterns).
^.*\.Rproj$ # RStudio project files
^\.Rproj\.user$ # RStudio user files
^data-raw$ # Data preparation scripts
^LICENSE\.md$ # Full license (keep LICENSE)
^README\.Rmd$ # Source (keep README.md)
^\.github$ # GitHub-specific files
^_pkgdown\.yml$ # pkgdown config
^docs$ # pkgdown output
^pkgdown$ # pkgdown extras
^\.httr-oauth$ # OAuth credentials
^\.secrets$ # Secrets directory
^\.env$ # Environment files
^cran-comments\.md$ # CRAN submission notes
^revdep$ # Reverse dependency checks
^\.lintr$ # Linter configuration
^\.pre-commit-config\.yaml$ # Pre-commit hooks
Pattern rules:
^ for start, $ for end\. not .usethis::use_build_ignore("pattern")Files to exclude from version control.
# R specific
.Rproj.user
.Rhistory
.RData
.Ruserdata
# Build artifacts
/*.tar.gz
/*.zip
/check/
/revdep/
# Documentation
/docs/
/Meta/
/doc/
# Package specific
.httr-oauth
.secrets/
.env
# OS specific
.DS_Store
Thumbs.db
GitHub-specific files (excluded from bundle via .Rbuildignore).
.github/
├── workflows/
│ ├── R-CMD-check.yaml # CI checks
│ ├── test-coverage.yaml # Code coverage
│ └── pkgdown.yaml # Deploy docs
├── CONTRIBUTING.md
├── ISSUE_TEMPLATE/
└── PULL_REQUEST_TEMPLATE.md
Common confusion: LICENSE, README, NEWS files
# Correct structure:
LICENSE # Machine-readable (CRAN requires this at root)
LICENSE.md # Human-readable (at root, in .Rbuildignore)
inst/CITATION # Citation info (needs to be installed)
README.md # User-facing (at root, included in bundle)
README.Rmd # Source (at root, in .Rbuildignore)
NEWS.md # At root (automatically used by pkgdown)
data/ # Exported data (users can load)
└── dataset.rda
R/sysdata.rda # Internal data (your functions use, users cannot load)
inst/extdata/ # Raw data files (users access via system.file())
└── example.csv
mypackage/
├── DESCRIPTION # Package metadata (required)
├── NAMESPACE # Auto-generated by roxygen2 (required)
├── LICENSE # License file (required for most licenses)
├── README.md # Package overview (highly recommended)
├── NEWS.md # Change log (recommended)
├── .Rbuildignore # Build exclusions
├── .gitignore # Git exclusions
├── mypackage.Rproj # RStudio project (in .Rbuildignore)
├── R/ # R code (required)
├── man/ # Documentation (auto-generated)
├── tests/ # Tests (highly recommended)
├── vignettes/ # Long-form docs (recommended)
├── data/ # Data (if needed)
├── data-raw/ # Data preparation (in .Rbuildignore)
├── inst/ # Installed files (if needed)
├── src/ # Compiled code (if needed)
└── .github/ # GitHub files (in .Rbuildignore)
R/
├── mypackage-package.R # Package docs
├── main.R # Main functions
├── utils.R # Utilities
└── zzz.R # .onLoad if needed
R/
├── mypackage-package.R
├── feature1.R # Grouped by feature
├── feature2.R
├── feature3.R
├── utils.R
├── utils-feature1.R # Feature-specific utils
├── data.R
└── zzz.R
R/
├── mypackage-package.R
├── aaa-imports.R # Package-level imports (aaa = loaded first)
├── class-feature1.R # S3/R6 class definitions
├── feature1-methods.R # Methods for feature1
├── feature1-utils.R # Utilities for feature1
├── feature2-core.R
├── feature2-helpers.R
├── generics.R # Generic function definitions
├── import-standalone-*.R # Standalone imports
├── utils.R
├── data.R
└── zzz.R
Problem: These are auto-generated by roxygen2.
Solution: Always use roxygen2 comments in R files.
# WRONG: Editing man/my_function.Rd directly
# RIGHT: Add roxygen2 comments in R/my_function.R and run devtools::document()
#' My function title
#'
#' @param x Input data
#' @returns Processed output
#' @export
my_function <- function(x) {
# implementation
}
Problem: R/ does not support subdirectories.
Solution: Use file naming conventions instead.
# WRONG:
R/
└── feature1/
├── core.R
└── utils.R
# RIGHT:
R/
├── feature1-core.R
└── feature1-utils.R
Problem: Development files included in package bundle, inflating size.
Solution: Add patterns to .Rbuildignore.
usethis::use_build_ignore("data-raw")
usethis::use_build_ignore(".github")
Problem: Data in inst/extdata/ is for raw files, not R objects.
Solution: Use correct location for data type.
# For R data objects (users can load):
usethis::use_data(my_dataset) # Creates data/my_dataset.rda
# For raw files (users read):
# Put in inst/extdata/example.csv
# Access with system.file("extdata", "example.csv", package = "pkg")
Problem: script.r instead of script.R (matters on Linux).
Solution: Always use uppercase .R for R code files.
# WRONG: R/utils.r
# RIGHT: R/utils.R
Problem: Package too large for CRAN (<5MB total, <1MB per subdirectory).
Solution: Compress data, move examples to inst/extdata/, suggest large dependencies.
# Compress data maximally:
usethis::use_data(dataset, compress = "xz", overwrite = TRUE)
# Check package size:
devtools::build() # Look at .tar.gz size
Problem: API keys, OAuth tokens in package code.
Solution: Use .Rbuildignore and .gitignore, document user-side credential management.
# .gitignore and .Rbuildignore:
.httr-oauth
.secrets
.env
inst/secrets/
Problem: Misunderstanding what inst/ is for.
Solution: Remember: inst/ contents are copied to package root at installation.
# During development:
inst/extdata/file.csv
# After installation:
extdata/file.csv # (inst/ is stripped)
# Access:
system.file("extdata", "file.csv", package = "mypackage")
Problem: Data in data/ but users must call data() to load it.
Solution: Add to DESCRIPTION.
LazyData: true
Problem: Having both README.md and README.Rmd without .Rbuildignore.
Solution: Keep only README.md in bundle.
# Correct setup:
README.Rmd # Source (in .Rbuildignore)
README.md # Generated (included in bundle)
# .Rbuildignore:
^README\.Rmd$
# Create package structure:
usethis::create_package("~/mypackage")
# Setup development tools:
usethis::use_git()
usethis::use_github()
usethis::use_testthat(3)
usethis::use_mit_license()
usethis::use_roxygen_md()
# Configure build:
usethis::use_build_ignore(c("data-raw", ".github"))
usethis::use_data(dataset) # Add exported data
usethis::use_data_raw("dataset") # Create data-raw/ script
usethis::use_r("function") # Create R/function.R
usethis::use_test("function") # Create test file
usethis::use_vignette("intro") # Add vignette
usethis::use_package("dplyr") # Add dependency
usethis::use_build_ignore("file") # Add to .Rbuildignore
# Check overall structure:
devtools::check()
# Build package:
devtools::build()
# Install locally:
devtools::install()
# Check what's in bundle:
pkgbuild::build(path = ".", dest_path = tempdir())
# Then examine .tar.gz contents