| Title: | Fast Package and Project Manager |
|---|---|
| Description: | Manages the packages and the R version of a project. Packages are resolved from dated snapshots of the 'Posit Package Manager' <https://packagemanager.posit.co> and recorded in a lockfile, so that a project can be reproduced as it was. The work is done by the 'rok' command-line program, which this package downloads from the project's 'GitHub' releases on first use, after asking for user consent. |
| Authors: | Yosuke Abe [aut, cre, cph] |
| Maintainer: | Yosuke Abe <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.2.0 |
| Built: | 2026-11-14 15:53:21 UTC |
| Source: | https://github.com/cran/rok |
Declares packages in rok.toml, then updates rok.lock and the project library. Accepts
the same forms as pak: "fixest" from CRAN, "owner/repo" and "owner/repo@ref" from
GitHub. With repo, the packages come from that CRAN-like repository (such as R-multiverse
or an r-universe), which is declared in rok.toml if it is not yet.
add(..., version = NULL, latest = FALSE, repo = NULL, project = ".")add(..., version = NULL, latest = FALSE, repo = NULL, project = ".")
... |
Package names or GitHub repositories. |
version |
A version constraint for one package, such as |
latest |
Take the packages from the latest snapshot, keeping the project's snapshot. |
repo |
The URL of one CRAN-like repository to take the packages from, such as
|
project |
A directory of the project (default: the working directory). |
Some packages build from source better with known environment variables (such as
NOT_CRAN = "true" for polars). Adding them is offered before anything is installed.
The result (the changes), invisibly.
dir <- tempfile("my-analysis") init(dir) add("R6", project = dir) add("jsonlite", version = ">= 1.8", project = dir) # GitHub packages, optionally at a tag, branch or commit add("gaborcsardi/praise", project = dir) # A package from a CRAN-like repository add("polars", repo = "https://community.r-multiverse.org", project = dir)dir <- tempfile("my-analysis") init(dir) add("R6", project = dir) add("jsonlite", version = ">= 1.8", project = dir) # GitHub packages, optionally at a tag, branch or commit add("gaborcsardi/praise", project = dir) # A package from a CRAN-like repository add("polars", repo = "https://community.r-multiverse.org", project = dir)
Writes a minimal renv.lock (without Hash) that renv::restore() can use: each package
names the dated Posit Package Manager snapshot it comes from, and GitHub packages their
commit. Unmanaged packages are left out. To write it every time rok.lock changes, add
[export] with renv = true to rok.toml.
export_renv(path = NULL, project = ".")export_renv(path = NULL, project = ".")
path |
Where to write it (default: |
project |
A directory of the project (default: the working directory). |
The result, invisibly.
dir <- tempfile("my-analysis") init(dir) add("R6", project = dir) export_renv(file.path(tempdir(), "renv.lock"), project = dir)dir <- tempfile("my-analysis") init(dir) add("R6", project = dir) export_renv(file.path(tempdir(), "renv.lock"), project = dir)
Creates rok.toml and rok.lock from renv.lock, with exactly the same package versions
(CRAN versions from the snapshot dates they were current, GitHub packages at the same
commits). The packages to declare are the ones no other package needs and the ones the code
uses; you are asked before anything is written. renv.lock and renv/ are left as they
are, and undo() reverts the migration.
import_renv(file = NULL, unsupported = NULL, project = ".")import_renv(file = NULL, unsupported = NULL, project = ".")
file |
The renv lockfile (default: |
unsupported |
What to do with packages from sources rok cannot install yet (such as
Bioconductor): |
project |
A directory of the project (default: the working directory). |
The result, invisibly.
dir <- tempfile("from-renv") dir.create(dir) writeLines(c( '{"R": {"Version": "4.6.1", "Repositories": []},', ' "Packages": {"R6": {"Package": "R6", "Version": "2.6.1", "Source": "Repository"}}}' ), file.path(dir, "renv.lock")) import_renv(project = dir)dir <- tempfile("from-renv") dir.create(dir) writeLines(c( '{"R": {"Version": "4.6.1", "Repositories": []},', ' "Packages": {"R6": {"Package": "R6", "Version": "2.6.1", "Source": "Repository"}}}' ), file.path(dir, "renv.lock")) import_renv(project = dir)
Creates rok.toml, rok.lock and the startup hook in path. The project uses the minor
version of the R that is running, and the latest snapshot date that Posit Package Manager
has published. If the rok binary is not installed yet, setup() installs it first.
init(path = NULL, r = NULL, name = NULL)init(path = NULL, r = NULL, name = NULL)
path |
The project directory (created if needed). By default, the working directory, after asking. |
r |
The R version, such as |
name |
The project name (default: the directory name). |
Without path, the project is created in the working directory, after asking (the same
question also covers installing the binary, the first time). Without anyone to ask, give
path or set options(rok.yes = TRUE).
In an interactive session, R then switches to the project: in Positron or RStudio, R
restarts (after asking if the global environment has objects), or the IDE opens the new
project's folder; elsewhere, you are told to start R in the project's folder. In Positron,
the project's R is also written to .vscode/settings.json, after asking.
The result, invisibly.
dir <- tempfile("my-analysis") init(dir) list.files(dir, all.files = TRUE, no.. = TRUE)dir <- tempfile("my-analysis") init(dir) list.files(dir, all.files = TRUE, no.. = TRUE)
Installs R without administrator rights. Without version, installs the version the
project in the working directory needs (or, outside a project, the latest release). Before
installing, it says which version and where it goes, and asks (without anyone to ask, set
options(rok.yes = TRUE)).
install_r(version = NULL, system = FALSE)install_r(version = NULL, system = FALSE)
version |
A version such as |
system |
Only show the commands that install R for all users (they need |
The result, invisibly.
# Show how to install the latest R for all users (nothing is installed) install_r("latest", system = TRUE)# Show how to install the latest R for all users (nothing is installed) install_r("latest", system = TRUE)
Moves the project to another minor version of R and resolves its packages again. If some packages have no binary for the new R, asks how to handle them. If the new R is not installed, offers to install it.
pin_r(version, strategy = NULL, project = ".")pin_r(version, strategy = NULL, project = ".")
version |
A version such as |
strategy |
What to do with packages without binaries: |
project |
A directory of the project (default: the working directory). |
The result, invisibly.
dir <- tempfile("my-analysis") init(dir) pin_r("latest", project = dir)dir <- tempfile("my-analysis") init(dir) pin_r("latest", project = dir)
Removes packages from rok.toml, then updates rok.lock and the project library. The
packages stay in rok's cache.
remove(..., project = ".")remove(..., project = ".")
... |
Package names (or |
project |
A directory of the project (default: the working directory). |
When rok is attached, this function masks base::remove(). Calls meant for it still reach
it: if an argument is an unquoted name (remove(x)), or list, pos, envir or
inherits is given, the call goes to the remove() that rok masks. To remove packages
whose names are in a variable, call rok::remove(pkgs).
The result (the changes), invisibly.
dir <- tempfile("my-analysis") init(dir) add("R6", project = dir) remove("R6", project = dir)dir <- tempfile("my-analysis") init(dir) add("R6", project = dir) remove("R6", project = dir)
Checks that a rok binary with the same version as this package can be found (see
rok_binary()). If not, setup() installs one.
rok_available()rok_available()
TRUE or FALSE.
rok_available()rok_available()
Looks for the binary in this order: the option rok.binary, the environment variable
ROK_BINARY, the place setup() puts it, and the PATH. The binary must have the same
version as this package.
rok_binary()rok_binary()
The path of the binary. An error if no matching binary is found.
rok_available() to check without an error.
rok_binary()rok_binary()
Syncs the project, then runs file with Rscript in a separate process, using the
project's R (or r) and library.
run(file, args = character(), r = NULL, project = ".")run(file, args = character(), r = NULL, project = ".")
file |
The script. |
args |
Arguments passed to the script. |
r |
The R version to use instead of the project's, such as |
project |
A directory of the project (default: the working directory). |
The exit status of the script, invisibly.
dir <- tempfile("my-analysis") init(dir) script <- file.path(dir, "hello.R") writeLines('cat("Hello from", R.version.string, "\\n")', script) run(script, project = dir)dir <- tempfile("my-analysis") init(dir) script <- file.path(dir, "hello.R") writeLines('cat("Hello from", R.version.string, "\\n")', script) run(script, project = dir)
Downloads the rok binary that matches this package (or copies binary), and keeps a copy
of this package where activated projects can load it. Everything goes under
tools::R_user_dir("rok", "data"), after asking once. init() calls this when needed;
run it yourself to repair an installation or to install without the network.
setup(binary = NULL)setup(binary = NULL)
binary |
The path of a rok binary to install instead of downloading one. |
A list with the paths of the binary and of the package library, invisibly.
setup()setup()
Shows what is out of sync between rok.toml, rok.lock, the library and R, without
using the network, and returns the details invisibly.
status(packages = FALSE, project = ".")status(packages = FALSE, project = ".")
packages |
List every package. |
project |
A directory of the project (default: the working directory). |
A list, invisibly: ok (whether there is nothing to fix), problems (a data
frame with one row per problem) and packages (a data frame with one row per package),
among others.
dir <- tempfile("my-analysis") init(dir) s <- status(project = dir) s$okdir <- tempfile("my-analysis") init(dir) s <- status(project = dir) s$ok
Updates rok.lock first if rok.toml changed.
sync(locked = FALSE, project = ".")sync(locked = FALSE, project = ".")
locked |
Fail instead of updating |
project |
A directory of the project (default: the working directory). |
The result, invisibly.
dir <- tempfile("my-analysis") init(dir) sync(project = dir)dir <- tempfile("my-analysis") init(dir) sync(project = dir)
Show the dependency tree
tree(pkg = NULL, depth = NULL, project = ".")tree(pkg = NULL, depth = NULL, project = ".")
pkg |
Show only this package's dependencies (default: every declared package). |
depth |
How many levels to show. |
project |
A directory of the project (default: the working directory). |
The lines of the drawing, invisibly.
dir <- tempfile("my-analysis") init(dir) add("R6", project = dir) tree(project = dir)dir <- tempfile("my-analysis") init(dir) add("R6", project = dir) tree(project = dir)
Restores rok.toml and rok.lock as they were before the last add(), remove(),
update() or pin_r(), and the library with them.
undo(project = ".")undo(project = ".")
project |
A directory of the project (default: the working directory). |
The result, invisibly.
dir <- tempfile("my-analysis") init(dir) add("R6", project = dir) undo(project = dir)dir <- tempfile("my-analysis") init(dir) add("R6", project = dir) undo(project = dir)
Without packages, moves the project's snapshot date to the latest one (or to) and
resolves again. With packages, updates only those (and what they need) from the latest
snapshot, keeping the project's date.
update(..., to = NULL, dry_run = FALSE, project = ".")update(..., to = NULL, dry_run = FALSE, project = ".")
... |
Packages to update (default: all). |
to |
The snapshot date to move to. |
dry_run |
Show what would change without changing anything. |
project |
A directory of the project (default: the working directory). |
When rok is attached, this function masks stats::update(). Calls meant for it still
reach it: if the first argument is not a character vector (a fitted model or a formula,
as in update(fit, . ~ . + x)), the call goes to the update() that rok masks, as if rok
were not attached.
The result (the changes), invisibly.
dir <- tempfile("my-analysis") init(dir) add("R6", project = dir) update(dry_run = TRUE, project = dir) update("R6", project = dir) # Models are still updated by stats::update() fit <- lm(dist ~ speed, data = cars) update(fit, . ~ . + I(speed^2))dir <- tempfile("my-analysis") init(dir) add("R6", project = dir) update(dry_run = TRUE, project = dir) update("R6", project = dir) # Models are still updated by stats::update() fit <- lm(dist ~ speed, data = cars) update(fit, . ~ . + I(speed^2))
Shows the packages that need pkg, up to the declared ones.
why(pkg, project = ".")why(pkg, project = ".")
pkg |
A package name. |
project |
A directory of the project (default: the working directory). |
The lines of the drawing, invisibly.
dir <- tempfile("my-analysis") init(dir) add("jsonlite", project = dir) why("jsonlite", project = dir)dir <- tempfile("my-analysis") init(dir) add("jsonlite", project = dir) why("jsonlite", project = dir)