0Pricing
R Academy · Lesson

Package Structure with usethis and devtools

Scaffold a package directory, DESCRIPTION, and NAMESPACE with usethis helpers.

Package Structure with usethis and devtools is a free R Academy lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the R Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Why Build an R Package?

An R package is the standard way to share reusable code, data, and documentation. Even if you never publish to CRAN, packaging your code enforces good practices: documented functions, unit tests, and a clear namespace. devtools and usethis make the process straightforward.

Creating a Package Skeleton

usethis::create_package('~/mypackage') creates a directory with all required files: DESCRIPTION, NAMESPACE, and an R/ directory. It opens the new project in RStudio automatically.

# library(usethis)
# library(devtools)
#
# usethis::create_package('~/mypackage')
#
# Creates:
# mypackage/
#   DESCRIPTION     <- package metadata
#   NAMESPACE       <- exported symbols (auto-managed by roxygen2)
#   R/              <- your R source files
#   .Rbuildignore   <- files to exclude from package builds

The DESCRIPTION File

The DESCRIPTION file is the package manifest. Its key fields:

  • Title — one-line description (title case, no period)
  • Version — semantic version (e.g., 0.1.0)
  • Author / Authors@R — package author
  • Depends — R version required
  • Imports — packages your package calls
  • License — e.g., MIT, GPL-3
# DESCRIPTION example:
# Package: mypackage
# Title: Tools for Analyzing Survey Data
# Version: 0.1.0
# Authors@R: person('Alice', 'Smith', email='alice@example.com', role=c('aut','cre'))
# Description: Provides helper functions for cleaning and summarizing survey responses.
# Depends: R (>= 4.1.0)
# Imports: dplyr, stringr
# License: MIT + file LICENSE

Adding Functions with use_r()

usethis::use_r('my_function') creates R/my_function.R and opens it for editing. Each file in R/ should contain one or a small group of closely related functions. Do not use source() calls inside package files.

# usethis::use_r('add')  # creates R/add.R
#
# Write your function in R/add.R:
# add <- function(x, y) {
#   if (!is.numeric(x) || !is.numeric(y)) stop('x and y must be numeric')
#   x + y
# }
#
# Then document it with roxygen2 comments above the function.

devtools::load_all() — The Development Loop

devtools::load_all() (keyboard shortcut Ctrl+Shift+L in RStudio) simulates installing and loading the package. It sources all files in R/ into the current session without actually installing. This is the core of the iterative development cycle.

# Development loop:
# 1. Edit R/add.R
# 2. devtools::load_all()   # Ctrl+Shift+L
# 3. add(2, 3)              # test interactively
# 4. Go to step 1
#
# load_all() is much faster than install.packages()
# because it skips compilation and installation steps.

devtools::check() — The Full Audit

devtools::check() (Ctrl+Shift+E) runs R CMD check — the comprehensive suite used by CRAN. It checks documentation, tests, examples, namespace, and more. Aim for 0 ERRORs, 0 WARNINGs, and as few NOTEs as possible.

# devtools::check()  # runs R CMD check
#
# Common errors to fix:
# ERROR:   Undocumented function 'add' => add roxygen2 docs
# WARNING: No NAMESPACE file => run devtools::document()
# NOTE:    No examples => add @examples in roxygen2
# NOTE:    Dependencies in DESCRIPTION not used => clean up Imports

The R/ Directory Structure

All source files go in R/. Common conventions:

  • One file per function family (e.g., R/utils.R, R/plot_helpers.R)
  • R/data.R for dataset documentation
  • R/zzz.R for .onLoad() and .onAttach() hooks

No subdirectories inside R/ — all files are at the top level.

# Typical R/ directory for a small package:
# R/
#   add.R          <- add() function + documentation
#   subtract.R     <- subtract() function
#   utils.R        <- internal helpers (not exported)
#   data.R         <- documentation for bundled datasets
#   package.R      <- @docType package documentation

The man/ Directory

man/ contains .Rd help files, one per exported function. You should never edit these manually — they are generated from roxygen2 comments by devtools::document(). Commit them alongside your source.

# man/ is auto-generated:
# man/
#   add.Rd         <- generated from @title, @param etc. in R/add.R
#   subtract.Rd    <- generated from R/subtract.R
#
# Regenerate with:
# devtools::document()  # also updates NAMESPACE
#
# Never edit .Rd files directly -- changes will be overwritten
cat('Always edit roxygen2 comments, never man/*.Rd files directly
')

The tests/ Directory

usethis::use_testthat() creates the tests/testthat/ directory and adds testthat to DESCRIPTION. Write test files named test-*.R inside that directory. Run all tests with devtools::test() (Ctrl+Shift+T).

# Set up testing:
# usethis::use_testthat()
#
# Creates:
# tests/
#   testthat.R            <- runner script (do not edit)
#   testthat/
#     test-add.R          <- your test file
#
# Run tests:
# devtools::test()
# devtools::test_file('tests/testthat/test-add.R')

Adding Dependencies Properly

Never use library(pkg) inside package source files. Instead:

  • Add the package to Imports in DESCRIPTION with usethis::use_package('dplyr')
  • Call functions with pkg::function() or add @importFrom pkg function in roxygen2
  • Use Suggests for packages only needed in examples or tests
# Add a dependency:
# usethis::use_package('stringr')           # adds to Imports
# usethis::use_package('ggplot2', 'Suggests') # adds to Suggests
#
# In R/my_function.R:
# clean_names <- function(x) {
#   stringr::str_to_lower(stringr::str_trim(x))  # use pkg:: prefix
# }

Package Development Workflow Summary

The standard iterative cycle for R package development:

  1. create_package() — create the skeleton once
  2. use_r('name') — create a source file
  3. Write and document functions (roxygen2)
  4. load_all() — load into session for interactive testing
  5. document() — regenerate man/ and NAMESPACE
  6. test() — run unit tests
  7. check() — full R CMD check

Quick Check: DESCRIPTION Fields

Which DESCRIPTION field lists the R packages that your package calls directly (hard dependencies)?

Package Structure Recap

Key files and commands for R package development:

  • usethis::create_package() — create skeleton with DESCRIPTION, NAMESPACE, R/
  • DESCRIPTION — Title, Version, Imports, License metadata
  • usethis::use_r('name') — add a source file to R/
  • devtools::load_all() — fast iterative reload (Ctrl+Shift+L)
  • devtools::document() — regenerate man/ from roxygen2
  • devtools::check() — full R CMD check targeting 0 errors/warnings
  • Never put library() in package source — use pkg::fn()

Frequently asked questions

Is the “Package Structure with usethis and devtools” lesson free?

Yes — the full text of “Package Structure with usethis and devtools” is free to read here on the web, and the R Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the R Academy course, upgrade to CoddyKit PRO.

What will I learn in “Package Structure with usethis and devtools”?

Scaffold a package directory, DESCRIPTION, and NAMESPACE with usethis helpers. You practise R Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start R Academy?

No prior experience is required. R Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Package Structure with usethis and devtools” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this R Academy lesson?

Yes. Every R Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Package Structure with usethis and devtools
  2. Documenting Functions with roxygen2
  3. Unit Testing with testthat
  4. CRAN Submission and Package Maintenance
← Back to R Academy