Lightweight, offline-first checking of R package dependencies against the currently installed environment, without requiring a full project lockfile. Verifies a declared manifest of package versions, including version constraints declared by transitive dependencies, reports session-level snapshot differences (including stale versions still loaded in a running session), detects packages shadowed by another library, and offers single-package version rollback. Designed for hosted notebooks (e.g. Kaggle, Colab, Binder) where 'renv'-style lockfile ownership is impractical, and equally usable on a normal desktop.
Manifest-based, transitive-aware dependency conflict detection for R. Built
for hosted notebooks (Kaggle, Colab, Binder) where a full renv lockfile
workflow doesn't fit, and just as useful on a normal desktop.
Hosted notebooks ship a pre-installed package set at fixed versions.
Installing a new package can silently upgrade or downgrade a dependency that's
already loaded elsewhere in your session, breaking code downstream with no
install-time error. The same happens on a desktop when libraries are shared
between projects. renv and pak are great but assume you own and can
persist the environment. depguard fills the narrower gap: lightweight checks
that work from locally installed metadata, offline, without lockfile
ownership.
install.packages("depguard")
Development version:
# install.packages("remotes")
remotes::install_github("sunraycodes/depguard")
Snapshot / diff, around an install. Changes are detected on disk, so an upgrade of an already-loaded package is caught even though R keeps running the old version until restart. Save the snapshot to survive the restart hosted notebooks require:
library(depguard)
snap <- dep_snapshot(path = "snapshot.rds")
install.packages("someNewPackage")
dep_diff(snap) # or, after a restart: dep_diff("snapshot.rds")
Manifest, declared once per project. Bare versions mean "at least"; operators give you control; text manifests are readable and diff-friendly:
dep_manifest(dplyr = ">= 1.1.4", ggplot2 = "3.5.0", cli = "== 3.6.2")
dep_manifest_freeze(path = "depguard.txt") # pin what you use right now
dep_check() # or dep_check(path = "depguard.txt")
dep_check() also verifies the constraints your packages declare on each
other (Imports: cli (>= 3.4.0)), which is where real conflicts hide.
Use dep_check(stop_on_problem = TRUE) in scripts and CI.
One-shot health check, at the top of a notebook:
dep_healthcheck()
Diagnostics:
dep_env() # Kaggle / Colab / Binder / RStudio / desktop; writable libraries
dep_libraries() # packages hidden by a different copy in another library
Single-package rollback (uses pak or remotes if installed, otherwise
base R and the CRAN archive):
dep_fix("stringr", "1.5.0", dry_run = TRUE)
dep_fix("stringr", "1.5.0")
See the vignette
for the full walkthrough, or run vignette("kaggle-colab-workflow") locally.
All checks are local-only by default (no network calls) and cover transitive
dependencies. Pass check_cran = TRUE to additionally query CRAN for the
latest versions. dep_fix() performs a single-package rollback only; it does
not resolve cascading conflicts. Use renv::restore() or pak's solver for
that.
If you use depguard in your work, please cite:
Shah S, Patel K (2026). depguard: Manifest-Based Dependency Conflict Detection for Sandboxed R Sessions. R package version 0.1.0, https://CRAN.R-project.org/package=depguard. doi:10.32614/CRAN.package.depguard
Or in R:
citation("depguard")
Bug reports and pull requests are welcome at github.com/sunraycodes/depguard/issues.
MIT + file LICENSE