An R package library can accumulate older releases while CRAN publishes compatible replacements. Checking the repository comparison first makes the available version change visible before any installed package is replaced.

R's old.packages() function compares one installed library with the selected repositories, and update.packages() can restrict installation to rows chosen from that result. This path is intended for repository-managed packages in a regular library, not dependencies controlled by an renv lockfile.

The jsonlite update uses the first active library and copies its installed directory before the change. Substitute a package shown by the comparison, keep the update confined to its reported library, and run a package-specific smoke test after confirming that no selected update remains pending.

Steps to update installed R packages:

  1. Start R without loading a saved workspace.
    $ R --quiet --no-save
    >
  2. Select the cloud CRAN repository.
    > options(repos = c(CRAN = "https://cloud.r-project.org"))
  3. Store the first active package library.
    > package_lib <- .libPaths()[1]
  4. Print the selected library path.
    > package_lib
    [1] "/home/analyst/R/library"

    The path differs by account and operating system, and it must identify the writable library intended for the update.
    Related: Set a user package library in R

  5. Query repository updates for the selected library.
    > updates <- old.packages(lib.loc = package_lib, repos = getOption("repos"))
  6. Display the installed and repository versions.
    > updates[, c("Package", "Installed", "ReposVer"), drop = FALSE]
             Package    Installed ReposVer
    jsonlite "jsonlite" "1.8.9"   "2.0.0"

    A NULL result means that the selected repository has no suitable newer release for a package in this library.

  7. Select the package rows to update.
    > selected <- updates[rownames(updates) %in% "jsonlite", , drop = FALSE]

    The selection may contain one or more package names from the preceding result.

  8. Review the selected package versions and library.
    > selected[, c("Package", "LibPath", "Installed", "ReposVer"), drop = FALSE]
             Package    LibPath                   Installed ReposVer
    jsonlite "jsonlite" "/home/analyst/R/library" "1.8.9"   "2.0.0"
  9. Set a directory for the pre-update package copy.
    > backup_dir <- path.expand("~/R/package-backup-before-update")
  10. Create the backup directory.
    > dir.create(backup_dir, recursive = TRUE, showWarnings = FALSE)
  11. Copy the selected installed package into the backup directory.
    > file.copy(file.path(package_lib, rownames(selected)), backup_dir, recursive = TRUE)
    [1] TRUE

    Any FALSE result means the backup is incomplete and the previous package version is not protected. A successful update replaces the installed directory, so this copy is the local rollback source if the new release breaks the workload.

  12. Update only the selected package rows.
    > update.packages(lib.loc = package_lib, repos = getOption("repos"), oldPkgs = selected, ask = FALSE)
    trying URL 'https://cloud.r-project.org/src/contrib/jsonlite_2.0.0.tar.gz'
    Content type 'application/x-gzip' length 1055849 bytes (1.0 MB)
    ##### snipped #####
    * DONE (jsonlite)

    Source-package output includes compiler and installation checks. Windows and macOS may install a binary package instead when the repository provides one.

  13. Check the installed versions of the selected packages.
    > installed.packages(lib.loc = package_lib)[rownames(selected), "Version", drop = FALSE]
             Version
    jsonlite "2.0.0"
  14. Refresh the repository comparison.
    > remaining <- old.packages(lib.loc = package_lib, repos = getOption("repos"))
  15. Confirm that none of the selected packages remains pending.
    > intersect(rownames(selected), rownames(remaining))
    NULL
  16. Parse a JSON value with the updated package.
    > jsonlite::fromJSON('{"answer":42}')$answer
    [1] 42