Managing R environment with renv

RaukR 2026 • Data Science With R

Hands-on exercises with renv
Author

Roy Francis

Published

18-Aug-2026

Note

Welcome to the hands-on lab on Managing R environment with renv. In this lab you will practice using renv for package management.

Each section builds on the previous one. Complete the exercises in order. When you are stuck, expand the Hints or Solution blocks — but try on your own first!


1 Setup

Before starting, make sure the required packages are available:

install.packages(c(
  "renv", "tidyverse", "broom", "palmerpenguins", "quarto", "knitr"
))

Work in a new directory throughout this lab. All exercises should be done inside that project directory.

2 Initialise renv

Initialise renv in your project and inspect what it creates.

renv::init()

Remember to restart the R session after calling renv::init() to ensure the private library is used.

Questions:

  1. Which files and folders were created?
  2. What does the .Rprofile file contain, and why is it important?
  3. Open renv.lock in a text editor. What format is it? What information does it record?

After calling renv::init(), look at your project directory. You should see new files and folders. List them with list.files(all.files = TRUE) to include hidden files.

3 Install and Snapshot

Create a new R script test.r in your project with the following content:

library("palmerpenguins")
  • Check status of the project with renv::status()

Install the palmerpenguins package.

renv::install("palmerpenguins")
  • Check status again with renv::status()

Snapshot the project to update the lock file.

  • Check status again with renv::status()

Questions:

  1. What does renv::status() report before and after renv::snapshot()?
  2. Find the palmerpenguins entry in renv.lock. What fields does it have?
  3. How would a collaborator recreate this exact environment on their machine?

This may not look exactly the same for everyone depending on your local setup. If you already had palmerpenguins installed, the first renv::status() may not report it as missing.

# Check status before install
renv::status()
# The following package(s) are used in this project, but are not installed:
# - palmerpenguins

# Check status after install before snapshot
renv::status()
# The following package(s) are in an inconsistent state:
#
# package        installed recorded used
# palmerpenguins y         n        y 

renv::snapshot()

# Check status after snapshot
renv::status()
# → "No issues found -- the project is in a consistent state."

# Collaborator would run:
renv::restore()

4 Simulate Restore

Simulate what happens when a collaborator clones your project.

  1. Note the current renv.lock contents.
  2. Remove palmerpenguins from the library:
renv::remove("palmerpenguins")
renv::status()
  1. Restore from the lock file:
renv::restore()
  1. Confirm palmerpenguins is back and renv::status() is clean.

renv::remove() removes a package from the private library but does not update the lock file. renv::restore() uses the lock file to reinstall everything that is missing.


5 Detect Dependencies

Create a script analysis.r in your project with the following content:

library(tidyverse)
library(palmerpenguins)
library(broom)

penguins_clean <- penguins |> tidyr::drop_na()
model <- lm(body_mass_g ~ flipper_length_mm + species, data = penguins_clean)
tidy(model)

Then run:

renv::dependencies()

Questions:

  1. Does renv detect all three packages (tidyverse, palmerpenguins, broom)?
  2. What happens if you add library(ggplot2) inside a function body? Does renv detect it?
  3. Snapshot again. Does the lock file change?
# renv::dependencies() scans project files such as .R, .Rmd, .qmd,
# .Rnw, and DESCRIPTION files, excluding ignored paths.
deps <- renv::dependencies()
print(deps)

# ggplot2 inside a function body is still detected because renv parses
# all R code, not just top-level statements.

renv::snapshot()
# If ggplot2 was already in the library (as a tidyverse dependency),
# it may already be in the lock file. If it was new, the lock file updates.

6 Session

Click here
sessionInfo()
R version 4.5.3 (2026-03-11)
Platform: x86_64-conda-linux-gnu
Running under: Ubuntu 26.04 LTS

Matrix products: default
BLAS/LAPACK: /home/roy/miniforge3/envs/r-4.5/lib/libopenblasp-r0.3.33.so;  LAPACK version 3.12.0

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
 [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

time zone: Europe/Stockholm
tzcode source: system (glibc)

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

loaded via a namespace (and not attached):
 [1] htmlwidgets_1.6.4 compiler_4.5.3    fastmap_1.2.0     cli_3.6.6        
 [5] tools_4.5.3       htmltools_0.5.9   otel_0.2.0        yaml_2.3.12      
 [9] rmarkdown_2.31    knitr_1.51        jsonlite_2.0.0    xfun_0.59        
[13] digest_0.6.39     rlang_1.3.0       evaluate_1.0.5