Scripts

rig run runs R scripts with any installed R version. A script can also declare the R version and the packages it needs in a comment block at its top. rig then installs R and the packages if needed, and runs the script in its own environment, so you can share a single .R file and it runs the same way on every machine, without a project or any setup. A lock file next to the script can pin the exact R and package versions, too.

NoteExperimental

Scripts with inline dependencies use the same machinery as rig proj, which is experimental. The format of the comment block may still change.

Running a script

rig run script.R              # run with the default R version
rig run -r 4.5 script.R       # run with R 4.5
rig run --rscript script.R    # run with Rscript instead of R
rig run script.R --verbose 3  # pass arguments to the script

Every argument after the script goes to the script, unchanged, where commandArgs(TRUE) picks it up. This includes arguments that look like rig’s own flags, and --. rig’s own flags go before the script.

rig run -f script.R is the same as rig run script.R. Without -f, rig treats a file as a script if its name ends in .R or .r, or if it starts with #!. Use -f for other files.

Inside an R project, rig run script.R runs the script in the project’s environment, unless the script has its own inline dependencies, see below. Use --no-project to ignore the project.

Inline dependencies

A script can declare what it needs in a # /// script comment block:

# /// script
# [dependencies]
# R = ">= 4.4"
# cli = "*"
# dplyr = ">= 1.1"
# ///

library(dplyr)
cli::cli_text("Hello from {.pkg cli}!")

The block starts with a # /// script line and ends with a # /// line. Every line in between must be a comment. Without the leading #, these lines form a TOML document. A block can also use ## instead of #, but then every line of the block must start with ##. A script can have at most one block.

The block takes these tables of rproj.toml, with the same meaning:

  • [dependencies]: the packages the script needs, with optional version requirements (^1.2.3, ~1.2.3, >= 1.0, < 2.0, or * for any version). R is the R version. A dependency can also come from git, GitHub, GitLab, a URL or a local path, see rig proj add for the syntax. A relative path is relative to the directory of the script.
  • [[repository]]: extra package repositories.
  • [tool.rig]: rig settings, e.g. exclude-newer, see below, and prefer-binary, see rig proj lock.

Any other table is an error, so typos do not go unnoticed.

Creating and editing the block

You can write the block by hand, or let rig manage it:

rig proj init --script script.R           # add a block, or create the script
rig proj add --script script.R cli dplyr  # add packages to the block
rig proj remove --script script.R dplyr   # remove packages from the block

rig proj init --script adds a block with an R requirement to the top of the script, after the #! line if there is one. If the script does not exist yet, it creates it. It does not replace a block that is already there, unless you pass --force.

rig proj add --script adds packages to the block, and creates the block if the script has none. You give the packages the same way as for a project, e.g. 'dplyr@>= 1.1' or r-lib/cli, and a local path is recorded relative to the script’s directory. rig proj remove --script removes packages from the block.

Both commands then set up the script’s environment, so the next rig run script.R starts right away. If the script has a lock file, they update it, too. --no-sync and --no-lock work the same way as for a project. If resolving the dependencies fails, rig proj add --script restores the script, and its lock file, to what they were.

The script’s environment

When you run a script with a block, rig:

  1. picks an installed R version that fits the R requirement, or installs one,
  2. resolves the dependencies to exact package versions, like rig proj lock,
  3. installs the packages into a library of their own, like rig proj sync,
  4. runs the script with that R version and library.

If the script has a lock file, rig skips the first two steps, and installs the R version and the package versions the lock file names instead.

The environment lives in rig’s cache directory, isolated from your own package libraries, so running a script never changes them. Later runs reuse the environment and start right away. Scripts with the same block share one environment, and changing the block creates a new one. A script with a lock file always gets an environment of its own.

A script with a block always uses its own environment, even inside a project. --r-version (-r) selects the R version, which must fit the R requirement. For a script with a lock file, it must be one of the R versions in the lock file.

While rig sets up the environment, it writes its messages to standard error, so standard output belongs to the script, and you can redirect it:

rig run report.R > report.csv

Scripts with inline dependencies work the same way in admin and user mode. If rig needs to install R for a script, it installs it the way the current mode does.

Upgrading packages

Like a project’s lock file, a script’s environment keeps the package versions it was created with, even if newer versions come out. To solve the dependencies again with the latest versions that fit, use --upgrade, or --upgrade-package to upgrade only some packages:

rig run --upgrade script.R
rig run --upgrade-package cli script.R

For a script with a lock file, these also update the lock file.

Reproducible scripts

There are two ways to make a script use the same package versions every time: a cutoff date for CRAN packages, and a lock file.

Excluding newer packages

Set exclude-newer in the script’s [tool.rig] table. The solver then ignores CRAN package versions published after that date:

# /// script
# [dependencies]
# R = ">= 4.4"
# dplyr = "*"
#
# [tool.rig]
# exclude-newer = "2026-06-01"
# ///

exclude-newer also takes a time interval back from today, e.g. "7 days", to skip packages released in the last few days. See rig proj lock for the details.

This keeps everything in the script itself, but it only fixes the CRAN packages. The R version and git, GitHub and URL dependencies can still change.

Lock files

A lock file pins everything: the R version, and the exact version, build and download URL of every package. Lock the script with:

rig proj lock --script script.R

This writes script.R.lock next to the script, with the exact R and package versions, for this machine and the other common platforms. Keep the two files together, e.g. commit both to git. rig proj lock --script takes the same options as rig proj lock, e.g. --r-version or --platform.

When script.R.lock exists, rig run script.R installs the R version and the package versions it names, on any machine it has a target for.

If you change the block, e.g. with rig proj add --script, so the lock file does not fit it any more, rig locks the dependencies again, for the same R versions and platforms, keeps the versions the lock file pins where they still fit, and updates script.R.lock. To fail instead, e.g. in CI, use --locked:

rig run --locked script.R

On a machine, or with an --r-version, that the lock file has no target for, rig run fails, and tells you how to add one with rig proj lock --script.

Executable scripts

On macOS and Linux, a script can start with a #! line that runs it with rig:

#!/usr/bin/env -S rig run
# /// script
# [dependencies]
# cli = "*"
# ///

cli::cli_text("Hello from {.pkg cli}!")

Make it executable, and then run it directly, like any other command:

chmod +x hello
./hello

A file that starts with #! is a script for rig run, whatever its name, so it does not need an .R extension. You can also put rig’s own flags in the #! line, e.g. #!/usr/bin/env -S rig run --rscript.

On Windows, rig system script-assoc makes .R files run with rig from cmd and PowerShell, e.g. hello.R a b, or just hello a b if the script is on the PATH. It changes how .R files open for the current user, and double-clicking a .R file then runs it, instead of opening it in your editor. rig system script-assoc --undo restores the old association.

Scripts from packages and projects

rig run <pkg>::<script> runs a script from the exec directory of an installed package, e.g. a command line tool that a package ships.

A project can give its own scripts a name, in the [[bin]] tables of rproj.toml, and then rig run <name> runs them in the project’s environment. See Named scripts.

Cleaning up

rig cache info shows how much space the script environments take, and

rig cache clean --category scripts

deletes all of them. rig creates them again the next time you run the scripts. Lock files next to the scripts are not touched.

See also