| Type: | Package |
| Title: | Migrate Installed R Packages Between R Versions |
| Version: | 0.3.1 |
| Description: | Detects all R installations on the current machine and migrates installed R packages between them. Provides find_routes() to discover R versions, manifest() to scan package libraries in a child R process, inventory() to compare two libraries, and ship() to install packages into a target R version using 'pak'. Includes a Shiny dashboard (open_hub()) for interactive source-to-target migration. |
| License: | MIT + file LICENSE |
| URL: | https://lennon-li.github.io/courieR/, https://github.com/lennon-li/courieR |
| BugReports: | https://github.com/lennon-li/courieR/issues |
| Language: | en-US |
| Encoding: | UTF-8 |
| RoxygenNote: | 8.0.0 |
| Config/testthat/edition: | 3 |
| Imports: | processx (≥ 3.8.0), callr (≥ 3.7.0), pak (≥ 0.7.0), jsonlite (≥ 1.8.0), desc (≥ 1.4.0), fs (≥ 1.6.0), cli (≥ 3.6.0), data.table (≥ 1.14.0), shiny (≥ 1.8.0), shinyjs (≥ 2.1.0), bslib (≥ 0.7.0), bsicons (≥ 0.1.2), DT (≥ 0.31) |
| Suggests: | stringr (≥ 1.5.0), testthat (≥ 3.0.0), withr (≥ 3.0.0), mockery (≥ 0.4.4), knitr (≥ 1.45), rmarkdown (≥ 2.26), pkgdown (≥ 2.0.0), shinytest2 (≥ 0.3.0), chromote (≥ 0.1.0) |
| VignetteBuilder: | knitr |
| NeedsCompilation: | no |
| Packaged: | 2026-06-14 17:00:28 UTC; Lennon.Li |
| Author: | Lennon Li |
| Maintainer: | Lennon Li <yeli@biostats.ai> |
| Repository: | CRAN |
| Date/Publication: | 2026-06-14 18:00:15 UTC |
courieR: Migrate Installed R Packages Between R Versions
Description
Detects all R installations on the current machine and migrates installed R packages between them. Provides find_routes() to discover R versions, manifest() to scan package libraries in a subprocess, inventory() to compare two libraries, and ship() to install packages into a target R version using 'pak'. Includes a Shiny dashboard (open_hub()) for interactive source-to-target migration.
Author(s)
Maintainer: Lennon Li yeli@biostats.ai (ORCID)
Authors:
Lennon Li yeli@biostats.ai (ORCID)
See Also
Useful links:
Report bugs at https://github.com/lennon-li/courieR/issues
Copy packages by file system
Description
Copies package directories from their source libpath into a target library
directory. Packages with no usable source path are skipped; missing source
directories are reported as errors.
Usage
copy_packages(plan, target_lib, log_callback = NULL)
Arguments
plan |
data.table with columns |
target_lib |
Character. Path to the target library root. |
log_callback |
Function or NULL. Called with a single string per event. |
Value
data.table with columns package, status ("success",
"skipped", or "error"), and message.
Run an R command in the background and log output
Description
Run an R command in the background and log output
Usage
dispatch(
project_path,
expr,
phase,
label,
rscript_path = NULL,
timeout_sec = 600L
)
Arguments
project_path |
Path to the project |
expr |
Expression to run (as a quoted expression or function) |
phase |
Character: "baseline" or "post_migration" |
label |
Character: "document", "test", or "check" |
rscript_path |
Optional path to Rscript |
timeout_sec |
Timeout in seconds |
Value
A list with process info
Examples
tmp <- tempdir()
job <- dispatch(tmp, "message('hello')", "baseline", "document")
Sys.sleep(1)
job$process$is_alive()
Detect R installations on the system
Description
Scans the current machine for every R installation it can find, across multiple sources per platform, and returns a tidy data frame of results.
Usage
find_routes(search_paths = NULL)
Arguments
search_paths |
An optional character vector of additional paths to
search. Each element may be a directory containing |
Details
Detection sources by platform:
Windows
HKLM registry (
SOFTWARE\R-core\R) - standard admin installs via the CRAN Windows installer.HKCU registry (
SOFTWARE\R-core\R) - non-admin installs that register under the current user hive only.-
%ProgramFiles%\R- directory scan for admin installs not in the registry. -
%LOCALAPPDATA%\Programs\R- rig-managed and other user-local installs. -
%USERPROFILE%\Documents\R- installs placed in the user's Documents folder. rig (
rig list) - any additional versions managed by rig that were not found by path scanning.
macOS
-
/Library/Frameworks/R.framework/Versions- system-wide CRAN installer. -
~/Library/Frameworks/R.framework/Versions- user-local framework installs (no admin required). Homebrew:
/opt/homebrew/opt/r(Apple Silicon) and/usr/local/opt/r(Intel).rig (
rig list) - rig-managed versions.
Linux
-
/opt/R- rig system-wide installs. -
~/.local/share/rig/R- rig user-local installs. conda environments (active
$CONDA_PREFIX).System
Rscripton$PATH.
Symlinks are resolved via fs::path_real() so that duplicate entries from
different detection sources pointing to the same executable are collapsed.
Each candidate is probed in a short subprocess. The probe timeout defaults
to 30 seconds and can be adjusted via options(courier.probe_timeout = );
installations whose probe times out are skipped with a warning rather than
silently dropped.
Value
A data frame with one row per unique R installation and the following columns:
- version
Character. R version string, e.g.
"4.4.1".- rscript_path
Character. Absolute path to the
Rscriptexecutable.- home
Character. The installation directory (
R.home()), i.e. where this R is installed. Normalized lexically for comparison.- library
Character. The installation's primary library location (
.libPaths()[1]under a vanilla session) - whereinstall.packages()writes by default. This is the effective package store; two installs that share alibraryhold the same packages. Normalized lexically for comparison.NAif it could not be determined.- is_current
Logical.
TRUEfor the R session running courieR.
Examples
routes <- find_routes()
routes[, c("version", "rscript_path", "is_current")]
# include a non-standard install
routes <- find_routes(search_paths = "/opt/custom-r/bin/Rscript")
Resolve the primary target library for an R installation
Description
Resolve the primary target library for an R installation
Usage
find_target_lib(target_path)
Arguments
target_path |
Full path to target |
Value
Character scalar path to .libPaths()[1L] in the target R.
Detect project characteristics
Description
Detect project characteristics
Usage
inspect_shipment(project_path)
Arguments
project_path |
Path to the project |
Value
A named list
Examples
res <- inspect_shipment(tempdir())
res$is_package
Compare two package libraries
Description
Takes two package manifests (from manifest()) and classifies every
source package as missing, outdated, newer, or the same relative to the
target.
Usage
inventory(source_pkgs, target_pkgs)
Arguments
source_pkgs |
|
target_pkgs |
|
Value
A named list with the following elements:
missingPackages in source that are absent from target.
outdatedPackages where the source version is newer than the target version.
newerPackages where the target already has a newer version than the source.
samePackages at identical versions in both installations.
comparisonFull merged
data.tableof all source packages with astatuscolumn ("missing","outdated","newer", or"same").summaryOne-row
data.framewith counts:missing,outdated,newer,same,total_source.
Each data.table includes columns package, version.x (source
version), version.y (target version), and source.
Examples
src <- data.table::data.table(
package = c("dplyr", "ggplot2"),
version = c("1.1.4", "3.5.1"),
priority = NA_character_
)
tgt <- data.table::data.table(
package = "dplyr",
version = "1.0.0"
)
inventory(src, tgt)
List packages installed in a library
Description
Runs a subprocess under the given R executable and returns all user-installed packages. Base and recommended packages are excluded automatically.
Usage
manifest(
rscript_path = NULL,
lib_path = NULL,
format = c("data.table", "data.frame"),
timeout_sec = 30L
)
Arguments
rscript_path |
Full path to an |
lib_path |
Library path to query within the target R. Defaults to the
first element of |
format |
|
timeout_sec |
Maximum seconds to wait for the subprocess. Increase
this on slow machines or network-mounted drives. Default |
Value
A data.table (or data.frame) with one row per user-installed
package and columns: package, version, source ("CRAN",
"GitHub", "Bioconductor", or "unknown"), remotetype,
remoteusername, remoterepo, libpath. Base and recommended packages
are never included in the output.
Examples
pkgs <- manifest()
head(pkgs)
Migrate packages between two R installations in one call
Description
Convenience wrapper around find_routes() and ship(). Matches
installations by version string (e.g. "4.5.2") or full Rscript path, then
runs the migration. Use ship() directly if you need fine-grained control.
Usage
migrate(from, to, dry_run = FALSE, upgrade = TRUE, mode = "online", ...)
Arguments
from |
Version string or Rscript path of the source installation (packages are copied from here). |
to |
Version string or Rscript path of the target installation (packages are installed into here). |
dry_run |
If |
upgrade |
If |
mode |
Transfer mode passed to |
... |
Additional arguments passed to |
Value
The same named list returned by ship(): plan, results,
comparison, dry_run, elapsed_sec.
Examples
## Not run:
# dry run first
migrate("4.5.2", "4.6.0", dry_run = TRUE)
# for real
result <- migrate("4.5.2", "4.6.0")
table(result$results$status)
## End(Not run)
Ensure the courier depot directory structure exists
Description
Creates .courier-depot/ and its subdirectories in the project path.
Writes a .gitignore to prevent tracking of logs and artifacts.
Usage
open_depot(project_path)
Arguments
project_path |
Path to the R project |
Value
Invisibly returns the path to the .courier-depot directory.
Examples
depot <- open_depot(tempdir())
Launch the courieR dashboard
Description
Opens the Shiny dashboard in your browser. The dashboard detects all R installations on the machine and lets you compare and sync packages between any two of them without writing any code.
Usage
open_hub(project_path = NULL, port = NULL, launch.browser = TRUE)
hub(project_path = NULL, port = NULL, launch.browser = TRUE)
Arguments
project_path |
Reserved; currently unused. |
port |
Port to run the Shiny app on. |
launch.browser |
Whether to open the system browser automatically. Default |
Details
hub() is a short alias for open_hub().
Value
Called for its side effect of launching a Shiny application.
Examples
if (interactive()) {
hub() # short form
open_hub() # same thing
}
Parse test log
Description
Parse test log
Usage
parse_dispatch_log(log_path)
Arguments
log_path |
Path to the log file |
Value
data.table
Examples
tmp <- tempfile(fileext = ".log")
writeLines(c(
"-- Failure (test-foo.R:1): addition works ----",
"Expected 3, got 4."
), tmp)
parse_dispatch_log(tmp)
file.remove(tmp)
Parse R CMD check log
Description
Parse R CMD check log
Usage
parse_inspection_log(log_path)
Arguments
log_path |
Path to the log file |
Value
data.table
Examples
tmp <- tempfile(fileext = ".log")
writeLines(c(
"* checking examples ... WARNING",
" An example result is marked with \\donttest."
), tmp)
parse_inspection_log(tmp)
file.remove(tmp)
Classify shipment risk based on check and test results
Description
Classify shipment risk based on check and test results
Usage
rate_shipment(baseline_results, post_results)
Arguments
baseline_results |
data.table from baseline check |
post_results |
data.table from post-shipment check |
Value
A list
Examples
baseline <- data.table::data.table(
severity = character(), message = character(),
file = character(), line = character()
)
post <- data.table::data.table(
severity = "ERROR", message = "undefined symbol",
file = "R/foo.R", line = "10"
)
rate_shipment(baseline, post)
Report a bug or error to the courieR issue tracker
Description
Opens a pre-filled GitHub issue form in your browser with your R version, platform, and (optionally) an error message already populated. Use this when you encounter a problem outside of the dashboard, or when you want to file a feature request.
Usage
report_issue(message = NULL, context = NULL)
Arguments
message |
Character. A short description of the problem. If |
context |
Character. Additional context about where the error occurred
(e.g. |
Value
Called for its side effect (opens browser). Returns the issue URL invisibly.
Examples
if (interactive()) {
report_issue("ship() fails with 'library not found'")
}
Check if rig is available
Description
Check if rig is available
Usage
rig_available()
Value
Logical
Examples
rig_available()
Install R via rig
Description
Install R via rig
Usage
rig_install(version, wait = TRUE)
Arguments
version |
R version |
wait |
Logical |
Value
The result of processx::run().
Examples
if (interactive() && rig_available()) {
rig_install("4.5.0", wait = FALSE)
}
List rig installations
Description
List rig installations
Usage
rig_list()
Value
data.frame
Examples
if (rig_available()) rig_list()
Ship packages between R installations
Description
Compares the package libraries of two R installations and transfers missing or outdated packages into the target.
Usage
ship(
source_path,
target_path,
packages = NULL,
dry_run = FALSE,
upgrade = FALSE,
log_callback = NULL,
mode = c("online", "offline", "preserve"),
source_pkgs = NULL,
target_pkgs = NULL,
...
)
Arguments
source_path |
Full path to the |
target_path |
Full path to the |
packages |
Character vector of package names to act on. If |
dry_run |
If |
upgrade |
Passed to |
log_callback |
Optional function of one argument. When provided, it is called with a single character string for each progress message emitted during package transfer. |
mode |
Transfer mode: |
source_pkgs, target_pkgs |
Optional pre-scanned manifests (as returned by
|
... |
Reserved for future arguments. |
Value
A named list with the following elements:
plandata.tableof planned actions with columnspackage,action("install"or"upgrade"),mode,version.x(source version),version.y(target version,NAif the package is missing), andpak_spec(the spec passed to pak).resultsdata.tableof per-package outcomes with columnspackage,status("success","skipped", or"error"), andmessage.comparisonThe raw
inventory()comparison table.dry_runTRUEif no packages were installed.elapsed_secTotal wall-clock time in seconds.
Safety
ship() can install packages into the target R library via
pak::pkg_install() running in a subprocess, or copy package directories
directly for offline/preserve transfers. Set dry_run = TRUE to preview the
migration plan without installing or copying anything. The source R need not
have pak installed. Subprocess calls and file copies are confined to the
target library path and R temporary directory.
Examples
routes <- find_routes()
if (nrow(routes) >= 2) {
result <- ship(
source_path = routes$rscript_path[1],
target_path = routes$rscript_path[2],
dry_run = TRUE
)
print(result$plan)
}
Scan project dependencies
Description
Scan project dependencies
Usage
take_inventory(project_path)
Arguments
project_path |
Path to the project |
Value
A data.table
Examples
take_inventory(tempdir())
Generate a pak specification for a package
Description
Generate a pak specification for a package
Usage
wrap(package, version = NULL, source_hint = NULL, github_ref = NULL)
Arguments
package |
Package name |
version |
Optional version constraint or exact version |
source_hint |
Optional hint: "CRAN", "Bioconductor", "GitHub", "local" |
github_ref |
Optional GitHub ref like "owner/repo@ref" |
Value
A character vector of pak specs
Examples
wrap("dplyr")
wrap("dplyr", version = "1.1.4")
wrap("mypackage", source_hint = "Bioconductor")
wrap("r-lib/rlang", source_hint = "GitHub", github_ref = "r-lib/rlang")