Changelog
Source:NEWS.md
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
libpathis 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 intotarget/<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 (itslibs/check was always false before). Covered by a.copy_plan+copy_packagesregression 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 viaoptions(courier.probe_timeout = ), and a probe that does time out is reported with a warning instead of vanishing; therig listtimeout 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’sR_LIBS_USER, soship()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 thatmanifest()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.)
Performance
- 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 → Bcontext bar was removed.
Performance
- Shipping no longer upgrades the entire dependency tree of each selected package: the dashboard now calls
ship()withupgrade = 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. PreviouslyprocessxinheritedR_LIBS_USER(andR_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 stripsR_LIBS_USER,R_LIBS,R_LIBS_SITE, andR_HOMEwhile 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
reactiveValoutside a reactive consumer in the sync log helper (now wrapped inisolate()).
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 → Shipworkflow 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()andmigrate()gain amodeargument:-
"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 runsship()automatically. -
hub()— short alias foropen_hub(). Runhub()to launch the dashboard with less typing. -
library(courieR)now prints the version number and a reminder to runhub()or see?ship. -
ship()gains alog_callbackargument 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 liketranslationsslip through into a sync plan, causing a pak error. The filter now uses case-insensitive path comparison and a name-based guard viainstalled.packages(priority = c("base", "recommended")).
Performance & UX
-
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 forshiny:::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.1
- Fixed correctness bugs identified during CRAN review.
- Added centralised error reporting in the Shiny module.
courieR 0.2.0
CRAN release: 2026-05-30
- CRAN readiness: hardened documentation, CRAN-safe examples, and CI workflow.
-
ship()gains a@section Safety:block documenting subprocess and library write behavior. -
manifest()now usesdeparse()for library path quoting, fixing edge cases with special characters. -
manifest()CSV fallback parsing now handles multi-line CSV output correctly. - Added
cran-comments.mdand.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.