Package Dev Workflow: Starting a New Package

June 19, 2018

(This article was first published on Ye Olde R Blog Grogram, and kindly contributed to R-bloggers)


  • A basic workflow to set up an R package


Instructions here will rarely be explicit. These workflows are essentially notes for experienced users to help remind them of the minimal steps to complete the task at hand.


  • Strongish familiarity with RStudio, R packages, and R projects
    • R Packages – contains almost all information to get up and running
  • Medium familiarity with git and github
  • Installation of R, R-Studio, devtools, test_that, and associated dependencies
  • Link Travis and Appveyor accounts to github


  • File -> New project -> New directory -> R package -> check create git repository
  • Write functions:
    • Write functions within .R files in /R directory
    • During dev, to interactively work with functions:
      • reinstalled and load package: devtools::load_all() or ctrl-shift-L
    • Add #' @export comment above all functions intended for user
      • ctrl-shift-D or devtools::document() to add function to NAMESPACE
    • External functions:
      • Add package to Imports field of DESCRIPTION using: devtools::use_package("name_of_package")
      • Reference in code as package::function()
      • Best practice – add min version number in DESCRIPTION:

        dplyr (>= 0.7.5),
      • Frequently used external functions
        • To remove requirement to ref with package::
        • Create imports.R file in /R
        • Populate with:

          #' importFrom package function
  • Document ref
    • Add roxygen2 comments above each exported function:

          #' Title (short and descriptive)
          #' Description (slightly longer)
          #' Details (longer description)
          #' @param a description of parameter a
          #' @param b description of parameter b
          #' @return output of function
          #' @export
          #' @examples
          #' # Short example of use
          #' sum(1, 2)
    • (Re-)build documentation: ctrl-shift-D or devtools::document()
    • Helpful tags:

      # Use parameters from other function:
      #' @inheritParams source_function
      # Document in another function (useful for directing 
      # class-specific methods to documentation within generic)
      #' @describeIn source_function
      # Link to other documentation
      ## If in different package
      #' @seealso \code{\link[package]{function}}
      ## If in same package
      #' @seealso \code{\link{function}}
      # Format as code
      #' \code{x}
      # To add additional sections
      #' @section SectionName:
      # Adding a link
      #' \code{\link{Summary}}
      # If you have a family of related functions where every function ]
      # should link to every other function in the family
      #' @family aggregate functions
      # Ordered list
      #' \enumerate{
      #'   \item First item
      #'   \item Second item
      #' }
      # Unordered list
      #' \itemize{
      #'   \item First item
      #'   \item Second item
      #' }
      # Include an example that is not executed when building package
      sum(1, 2)
  • LICENSE: devtools::use_gpl3_license or devtools::use_mit_license
    • Edit as needed
  • README.Rmd ref
    • devtools::use_readme_rmd
    • Must update .md file after each .Rmd file edit: ctrl+shift+k
  • Vignettes ref
    • devtools::use_vignette("vignette-title")
    • Modify vignette as necessary
    • After each modification: devtools::build_vignettes() or ctrl+shift+k
  • Github
    • Create new repository on github with same name as package
    • Copy commands for pushing an existing repo and enter into RStudio terminal
Push commands

Push commands

  • Testing: ref
    • devtools::use_testthat()
    • Create a .R file for each test in projDir/tests/testthat/
    • Populate with unit testing

      # Describe context at top
      # Example rom tidyr
      test_that("basic invocation works", {
        df <- tibble(x = 1:2, y = 1:2, z = 3:4)
        out <- complete(df, x, y)
        expect_equal(nrow(out), 4)
        expect_equal(out$z, c(3, NA, NA, 4))
    • Run tests: devtools::test() or ctrl + shift + T
  • Continuous integration ref
    • Travis:
      • devtools::use_travis()
      • Flip project repo switch on Travis
      • Add badge to README file

        [![Build Status](](
    • AppVeyor:
      • devtools::use_appveyor()
      • Flip project repo switch on AppVeyor
      • Add badge to README file

        [![AppVeyor Build Status](](
  • Checks and cleanup
    • running devtools::check()
    • Consider lintr or formatR to tidy code
      • lintr::lint_package() adds markers to code and allow for manual cleanup

To leave a comment for the author, please follow the link and comment on their blog: Ye Olde R Blog Grogram. offers daily e-mail updates about R news and tutorials on topics such as: Data science, Big Data, R jobs, visualization (ggplot2, Boxplots, maps, animation), programming (RStudio, Sweave, LaTeX, SQL, Eclipse, git, hadoop, Web Scraping) statistics (regression, PCA, time series, trading) and more...

If you got this far, why not subscribe for updates from the site? Choose your flavor: e-mail, twitter, RSS, or facebook...

Comments are closed.

Search R-bloggers


Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)