Hosted, ephemeral R notebooks (Kaggle, Colab, Binder, and similar) ship with a large pre-installed set of packages at fixed versions. When you install an additional package, its dependencies can silently upgrade or downgrade a package that is already loaded elsewhere in your session, breaking code further down the notebook with no install-time error. The same thing happens on a normal desktop whenever you install into a library you share between projects.
Tools like renv solve this well for projects you fully
own and can persist, but assume you can write lockfiles and restore a
private library. That often doesn’t fit a throwaway notebook, or a quick
script. depguard fills the narrower gap: lightweight checks
that run entirely from locally installed metadata, so they work
offline.
dep_env() detects Kaggle, Colab, Binder, RStudio and
plain desktop sessions, and reports which libraries are writable.
depguard uses it to word its advice (for example, how to
restart the session).
Run this before installing anything new:
Install what you need as usual:
Then check what changed:
The comparison is made on the versions on disk. R keeps
running the old version of an already-loaded package until you restart,
so a package that changed and is still loaded is flagged
risk = "high" and session_stale: code you
already ran used one version, and code run after a restart will use
another.
In hosted notebooks you normally have to restart the session after
installing. Saving the snapshot with path lets you compare
after the restart:
If you know what your notebook needs up front, declare it once:
dep_manifest(
dplyr = ">= 1.1.4", # at least this version
ggplot2 = "3.5.0", # a bare version also means "at least"
quantmod = "== 0.4.26" # exactly this version
)Or pin whatever you are using right now:
Any file extension other than .rds produces a plain-text
manifest that is easy to read, edit and commit:
# depguard manifest: package (operator version)
dplyr (== 1.1.4)
Then, any time later:
This walks the dependency tree of each declared package using only
locally installed metadata and compares the version constraints that the
packages declare on one another (for example,
cli (>= 3.4.0)) with what is actually installed. It
reports missing, mismatch, and
restart (the version on disk is right but the session is
still running an older one), along with which package required each
dependency. In scripts and CI, use
dep_check(stop_on_problem = TRUE) to fail on any
problem.
At the top of a notebook:
This describes the environment, warns about packages hidden by another library, and then checks a manifest if one exists, or captures a baseline snapshot otherwise.
R loads the first copy of a package it finds on the library path. A stale copy in a library earlier on the path hides the one you just installed.
If a specific package got silently bumped and broke something, you can roll just that package back to a specific version, and preview it first:
dep_fix() uses pak or remotes
when installed and otherwise downloads the source from the CRAN archive
using only base R. It checks the result and tells you if you need to
restart, or if another library is still hiding the rolled-back copy.
This performs a single-package rollback only; it does not resolve
cascading conflicts the rollback might introduce elsewhere. For full
dependency resolution, use renv::restore() or
pak’s solver.