courieR 0.3.1
Bug fixes
- Fixed a second cause of shipped packages never showing up as
installed, on the copy path (offline/preserve modes and online
mode’s local/private packages). A manifest’s
libpath is the
library directory shared by every package, but .copy_plan()
passed it through as if it were the per-package source, so each “copy”
recursively cloned the entire source library into
target/<pkg>/ — leaving no valid package where R
looks and reporting a silent success. The package name is now joined
onto the library path, which also restores the cross-major
compiled-package warning (its libs/ check was always false
before). Covered by a .copy_plan +
copy_packages regression test and an opt-in browser
end-to-end test (COURIER_E2E=true).
- R installation detection no longer drops installs intermittently on
slow machines.
find_routes() probed each candidate with a
hard 3 s timeout and silently discarded any that exceeded it, so a cold
R start (antivirus, OneDrive-synced installs) made versions flicker in
and out between runs. The default probe timeout is now 30 s,
configurable via options(courier.probe_timeout = ), and a
probe that does time out is reported with a warning instead of
vanishing; the rig list timeout was also raised from 5 s to
15 s.
- Fixed shipped packages never showing up as installed:
find_target_lib() and the pak install subprocess inherited
the parent R session’s R_LIBS_USER, so ship()
installed into the parent’s library while Compare scanned the
real target. All subprocesses that launch another R now share one
environment-stripping helper (child_r_env()), and the
install destination is guaranteed to be a library that
manifest() scans.
- Library scans that time out are no longer cached as “empty library”
for the rest of the session; timeouts are reported loudly in the log and
the scan timeout was raised from 30 s to 5 min for slow machines.
- The “both installations share one library” warning no longer fires
vacuously when both scans returned no packages.
Routing
- Online mode now means online: every package resolvable from CRAN /
Bioconductor / GitHub is reinstalled via pak (binaries preferred). Only
local/private packages with no online source are copied from the source
library. (Previously pure-R CRAN packages were file-copied even in
online mode, which is much slower than pak on synced/network
libraries.)
- One manifest scan per library per session, shared across all tabs: a
ship right after Compare reuses the Compare scans and spawns no scan
subprocesses; the post-ship refresh rescans only the shipped-into
library.
Dashboard UX
- Bulk Dispatch now shows a live hero panel during
shipping (matching Custom Dispatch): packages delivered so far, the
current package being installed, elapsed time, and the estimated total.
The detailed log in the R console is also mirrored in the dashboard log
pane.
- Both Bulk Dispatch and Custom
Dispatch tables now default to showing only packages missing
from the target after Compare, instead of all diff statuses. The filter
chip bar lets you toggle other statuses.
- Custom Dispatch filter chips are now colour-coded —
orange for source-side differences (newer in source, not in target),
teal for target-side differences — matching Bulk Dispatch.
- Custom Dispatch comparison table gains a
Repo column showing where the package comes from (CRAN,
Bioconductor, GitHub, etc.). Packages with an unknown source are shown
in red in both tables.
report_issue() — new exported function. Call it from
the console after any error to open a pre-filled GitHub issue form in
your browser with your R version, platform, courieR version, and the
error message already populated. The dashboard’s error modal gains a
Send Report button that does the same in one
click.
- Custom Dispatch shows a live green hero panel while shipping:
packages delivered so far, the package currently being copied/installed,
elapsed time, and the estimated total.
- Time estimates (plan summary, ship confirmation, preview invoice)
now come from per-machine calibrated rates persisted across sessions —
every completed ship updates them — instead of fixed constants that were
off by 100x on synced/network drives.
- Custom Dispatch source/target header now shows the R version,
install location, and library path of both installations (was the bare
executable path).
- After a Custom Dispatch shipment the comparison tables refresh
automatically and the depot log says so; the refresh is logged when it
completes.
library(courieR) startup message now includes a link to
the user guide vignette
(vignette("get-started", package = "courieR")).
courieR 0.3.0
Dashboard UX
- Flattened the dashboard navigation from three nested tab levels to a
single row of five top-level tabs: Bulk Dispatch,
Browse, Custom Dispatch,
Manifest, and Maintenance. The former
Advanced wrapper tab is gone.
- Renamed Dispatch → Bulk Dispatch,
and the former Ship sub-tab is now the top-level
Custom Dispatch tab.
- Custom Dispatch now uses a two-pane layout — the
package table on the left and a live log panel (with a delivery receipt)
on the right — mirroring Bulk Dispatch. Its comparison columns are
labelled Source / Target (was
Version A / Version B), its filter chips read “newer
in source / newer in target / not in target / not in source”, and the
redundant
A → B context bar was removed.
- Shipping no longer upgrades the entire dependency tree of each
selected package: the dashboard now calls
ship() with
upgrade = FALSE. Selected packages still install or upgrade
to the latest compatible version, but their already-installed
dependencies are left alone unless a version requirement forces a
change. This removes the main cause of multi-minute single-package
shipments.
- Custom Dispatch now scans each library at most once per Ship click
and passes the scans to
ship()
(source_pkgs/target_pkgs), instead of
re-scanning both libraries for every batch.
Bug fixes
manifest() no longer leaks the parent R session’s
library/home environment into the target R subprocess. Previously
processx inherited R_LIBS_USER (and
R_HOME) from the R running courieR, so every probed
installation reported the parent’s library — making distinct R versions
appear to share one library and compare as 100% identical. The
subprocess now strips R_LIBS_USER, R_LIBS,
R_LIBS_SITE, and R_HOME while still reading
the target R’s own .Renviron/.Rprofile.
- Dashboard: fixed “Operation not allowed without an active reactive
context” on startup, caused by reading a
reactiveVal
outside a reactive consumer in the sync log helper (now wrapped in
isolate()).
Dashboard UX
- Renamed the core actions to match courieR’s shipping vocabulary:
Scout (detect installations),
Inventory (compare libraries), and
Ship (transfer packages). The main tab is now
Dispatch, and the Advanced tabs are
Restock, Depot, Delivery
Receipt, Route, and
Manifest.
- Detection is no longer automatic on startup; click
Scout to scan. A
Scout → Inventory → Ship
workflow note appears in the control panel, and the result is shared
across tabs.
- The logo twinkles while the app is busy (tied to Shiny’s busy/idle
events).
- Comparison table: per-column filters (search boxes for
package/versions, a dropdown for status), pagination grouped compactly
below the table, and the global search box removed. The log panel sits
beside the comparison, spanning its full height.
- Transfer mode options shortened (Online reinstall / Offline copy /
Preserve version) with a live description of the selected mode.
find_routes() is called once per scan and shared across
modules instead of being re-run by each, reducing startup/detection
time.
courieR 0.2.3
New features
ship() and migrate() gain a
mode argument:
"online" (default) — reinstall packages via pak from
CRAN/GitHub/Bioconductor.
"offline" — copy package directories by file; packages
with no valid source path are skipped and reported.
"preserve" — copy first to keep exact versions; fall
back to a pinned pak spec (pkg@version) for packages that
cannot be copied. The dashboard Sync tab exposes the same three options
as a dropdown.
migrate(from, to) — one-call CLI migration. Pass
version strings ("4.5.2", "4.6.0") or full
Rscript paths; courieR resolves the installations and runs
ship() automatically.
hub() — short alias for open_hub(). Run
hub() to launch the dashboard with less typing.
library(courieR) now prints the version number and a
reminder to run hub() or see ?ship.
ship() gains a log_callback argument for
real-time progress messages from the pak subprocess, including a notice
when first-time metadata loading may take 1–2 minutes.
Bug fixes
manifest() now reliably excludes base and recommended
packages on Windows. The previous path comparison was case-sensitive and
could let packages like translations slip through into a
sync plan, causing a pak error. The filter now uses case-insensitive
path comparison and a name-based guard via
installed.packages(priority = c("base", "recommended")).
find_routes() per-candidate subprocess timeout reduced
from 5 s to 3 s, shortening detection time when multiple R versions are
installed.
- Sync dashboard: replaced the floating
withProgress()
modal with an inline Bootstrap progress bar inside the log pane. Log
lines now append to the DOM immediately, removing the need for
shiny:::flushReact().
- Sync dashboard: detection phase shows a Bootstrap info alert while
scanning and records “Detection complete: found N installation(s).” in
the sync log.
courieR 0.2.2
- CRAN resubmission addressing reviewer feedback.
courieR 0.2.1
- Fixed correctness bugs identified during CRAN review.
- Added centralised error reporting in the Shiny module.
courieR 0.2.0
- CRAN readiness: hardened documentation, CRAN-safe examples, and CI
workflow.
ship() gains a @section Safety: block
documenting subprocess and library write behavior.
manifest() now uses deparse() for library
path quoting, fixing edge cases with special characters.
manifest() CSV fallback parsing now handles multi-line
CSV output correctly.
- Added
cran-comments.md and
.github/workflows/R-CMD-check.yaml.
- DESCRIPTION title simplified; version bumped.
courieR 0.1.0
- Initial release.
find_routes() detects R installations on Windows,
macOS, and Linux, including user-local installs.
manifest() scans installed packages from any R
installation via subprocess.
inventory() compares two package libraries and reports
missing, outdated, and newer packages.
ship() migrates packages from one R installation to
another using pak.
open_hub() launches a Shiny dashboard for
point-and-click migration.