Creating renv cache in an offline environment

Is there any useful way to use renv in an environment that doesn't have access to the internet? The current state is that I have a working analysis with X package versions. My goal is the same as anyone who uses renv - i want access to the exact package versions used to create the analysis. My problem is that I don't have control over package installation (indeed packages could be changed at any moment) nor do I have access to the internet.

So I am wondering if renv can, rather than go to the internet to access packages, it uses the versions of packages I currently have installed at any library tree from .libPaths(). Is there a way to copy those over into the project directory and use those? That is, i'd like to do that from within renv if possible. This might betray my lack of understanding of exactly how renv works but ultimately I am just wondering how to create a snapshot when I don't have access to the internet.

Thanks in advance,


Is creating your own local CRAN-like repository an option? If so, you could then do something like:

options(repos = c(CRAN = "file:///path/to/my/repository"))

and renv (and R) would use this local repository for package installations.

It sort of sounds like you really just want to set .libPaths() to point to some pre-curated library path on a project-specific basis? If so, it seems like you could do that without relying on renv.

It sounds like renv::hydrate() may do what you want here -- its job is to copy packages from a source library path into the project library, basically "forking" the state of that library for use in a particular project. In your case, you would want:

renv::hydrate(sources = <your library path(s)>)

See ?renv::hydrate for more details.

I think actually it was options(renv.config.cache.symlinks = FALSE) that was giving me grief here. I am not totally sure why but I can see that renv::hydrate is happier if it proceeds to renv:::renv_hydrate_copy_packages rather than linking.

BTW - such a wonderfully documented package and wonderfully documented code. Thanks!

Interesting -- any chance you'd be willing to file a bug report at with a few more details? I'd be curious to know why this was failing. (Most commonly, failures would happen on Windows systems when attempting to make cross-device junction points; that is less of a concern on Linux / macOS)

I am still figuring exactly what is going on to put into a succinct issue but one thing I have noticed is that renv:::renv_hydrate_libpaths doesn't seem to like when I give it two library locations on two different drives:

options(renv.config.hydrate.libpaths = c("U:/RLIBS", "R:/.libs/RLIBS/3.6"))
#> [1] "C:/Users/salbers/AppData/Local/Temp/RtmpE3Q2aA/reprex612844cd75a5/U"
#> [2] "C:/RLIBS"                                                           
#> [3] "C:/Users/salbers/AppData/Local/Temp/RtmpE3Q2aA/reprex612844cd75a5/R"
#> [4] "C:/.libs/RLIBS/3.6"

Created on 2021-02-10 by the reprex package (v1.0.0)

I think that's not operating like it is supposed to but maybe I am also misunderstanding exactly what hydrate.libpaths is doing.

Certainly part of the issue is that my R_LIBS_SITE (R:) and R_LIBS_USER (U:) are on different volumes.

(Would you prefer a slightly rambly GitHub issue to this?)


That would be appreciated! It's okay if the issue is not completely reproducible -- please just provide as much information as you can that appears to be relevant to the issue.

(Am I reading your output correctly that even though you're setting U:/RLIBS as a library path, that's being "flipped" to C:/RLIBS; that is, the drive letter is changing for some reason?)