Rig>Reference>Commands

Commands#

This page lists every command, what it does, and its flags. rig <command> --help is the documentation of record. This page is the map.

Overview#

Command Path Description
lock cold Resolve the workspace, hash every artifact, write deps.lock.
update [coord [version]] cold Re-resolve, or bump/pin one requirement (shared propagation).
add <coord> [version] cold Add a requirement (shared by default).
remove <coord> cold Remove a requirement (shared, from all modules).
check cold+hot Verify every lock artifact against the cache (the CI security gate), lock-vs-manifest consistency, and namespace load + AOT-compile per module. Never re-locks.
test [opt value…] hot Run the modules' test exec-fns on locked classpaths.
run [args…] hot Run the module's :rig/main on the (alias) classpath.
launch [jar] [args…] hot Launch the built artifact with Rig's production JVM flags (G1 + AlwaysPreTouch, exit-on-OOM, loopback JMX on 10101), overridable via :rig/launch-opts and the RIG_LAUNCH_OPTS env var. Replaces its own process with the JVM (process exec) — the app is the container's PID 1. The jar's baked launch plan, or the lock, supplies the main. Never re-locks, never uses the network.
nrepl hot nREPL server on the (alias) classpath (--alias, --host, --port).
exec <cmd> [args…] hot Run a command with the locked classpath as CLASSPATH.
build [--uber | --native] cold Jar / uberjar / native-image binary via the locked classpath.
install cold Install module jars into the local Maven repository.
publish cold Deploy module jars to their remote repository.
outdated [--breaking] cold Pinned vs available versions.
tree [--alias a] cold Dependency tree for a module.
clean hot Remove build-output directories.
fmt [--check] hot cljfmt on the module, pinned version (no lock needed).
new <group/name> cold Scaffold a new project.
new-module <name> cold Scaffold a module in the workspace, add it, re-lock.
migrate [--dry-run] cold Convert a legacy (:exoscale.* / :slipset.*) or Leiningen (project.clj) workspace to :rig/* in place.
jvm install <major> — Install the newest Temurin JDK for a major version into the Rig state dir.
jvm list — Installed JDKs + the system java.
jvm path <major> — Print the JAVA_HOME of an installed JDK (scripts/CI).
jvm uninstall <version> — Remove an installed JDK.
jvm update — Update the rig-managed JDK for the pinned major to the newest release.
graalvm install <major> — Install the newest GraalVM community JDK for a major version into the Rig state dir.
graalvm list — Installed GraalVMs.
graalvm path <major> — Print the GRAALVM_HOME of an installed GraalVM (scripts/CI).
graalvm uninstall <version> — Remove an installed GraalVM.
graalvm update — Update the rig-managed GraalVM for the pinned major to the newest build.
crac install — Install the rig-pinned Zulu CRaC JDK (kernel checkpointing).
crac status — Pinned CRaC JDK, installed?, active override.
crac clean — Prune checkpoint chains that can no longer be restored.
self-update [--check] — Update the Rig binary from the GitHub releases.
auth get [gate|url] — Print the bearer token of an OIDC gate (env, cache, or negotiated).
info hot Project and tool summary, including the project version.

Hot commands run from the lock (lock → hash-check → launch). They never write the lock: a missing or stale lock fails them (exit 3) and points at rig lock. Cold commands do deeper kernel work (resolve, build, publish, edit). Only the locking family — lock, add, remove, update, new, new-module — writes the lock, and it needs no flag. launch is hot because it never touches the kernel. It treats the lock as inert data: it never checks staleness, never re-locks, and never uses the network. clean and info read the workspace and the lock — they never write the lock, stale or not.

Locking and dependency changes#

rig lock#

rig lock

Resolve every module of the workspace, fetch and sha256-hash every artifact, and write deps.lock. A git dep resolves to its pinned commit and checks out under the gitlibs root (~/.gitlibs, or $GITLIBS) as part of the resolve. The command prints skipped version selections (cooldowns, forces) and a summary:

wrote /home/dev/app/deps.lock: 528 artifacts, 8 modules

Writing the lock is the command's whole job, and it needs no flag. The commands that consume the lock — test and the rest of the hot family — never write it. A missing or stale lock fails them (exit 3) and points back here. check consumes the lock too, but reports staleness instead of failing it: the stale module is a problem, and the command exits 1.

When a cooldown refuses a requirement, the command aborts with exit 5:

refused org.clojure/tools.logging (cooldown 48h)
1 requirement(s) refused by cooldowns (retry with --force)

Rig routes requests to an :auth :oidc repository through a local proxy that injects the gate's bearer token; tools.deps itself never talks to an authenticated repo. At lock time Rig accepts an artifact Maven already downloaded into ~/.m2/repository without refetching, and verifies it against the published SHA1. A cold m2 therefore locks as well, and every request that does go out bears the token. See authenticated repositories.

rig update#

rig update <coord> [version]
Form Effect
rig update <coord> <version> Pin the exact version (explicit, recorded in the lock).
rig update <coord> Newest eligible version (cooldown-gated, exit 5 if refused).

Flags: --alias <a> targets the :extra-deps of an alias, and --shared-only updates only :rig/deps. The global --force flag bypasses cooldowns.

rig add / rig remove#

rig add <coord> [version]      # no version: newest eligible (cooldown-gated)
rig remove <coord>

add flags: --alias <a> adds the requirement under the :extra-deps of an alias, and --shared defaults to true; --shared=false keeps the requirement local. -p <module> chooses which module supplies the :deps to edit. Shared propagation still applies unless you set --shared=false.

rig migrate#

rig migrate [--dry-run]

rig migrate converts a legacy workspace into :rig/*, in place. A legacy workspace uses the :exoscale.project/*, :exoscale.deps/*, and :slipset.deps-deploy/* key namespaces (the output of tools.project and deps-modules). The command reports every manifest:

deps.edn: migrated
modules/orchestrator/deps.edn: migrated

What it does, mechanically:

  • Renames the :exoscale.project/* keys to :rig/*, including the inverted :exoscale.project/bypass-test? → :rig/test?.
  • Materializes :exoscale.deps/managed-dependencies into the :deps of every module that inherits from it, then drops the pool with a warning. Rig does not carry the pool as a :rig/deps shared requirement. :exoscale.deps/inherit (:all or a subset) marks which coords inherit. The managed entry fills the keys a module leaves undeclared. When a module declares a version or source key, that key wins over the managed entry, and Rig reports each such case as a per-dep warning. Rig never rewrites such a key.
  • Drops :exoscale.deps/managed-aliases (only the :project alias exists; Rig has no alias inheritance) and the :project aliases themselves.
  • Rewrites :slipset.deps-deploy/exec-args into :rig/publish (:repo); publish enablement comes from the :exoscale.project/deploy? → :rig/publish? rename. A deploy repo with an s3p:// URL is a blocking problem (Rig publishes to http/https repositories only).

--dry-run runs the same analysis and reports per-file changes without writing anything. A blocking problem aborts the whole migration with exit 1, and Rig writes nothing. Blocking problems are, for example, an inherit-only coord that is absent from the managed map, or :sign-releases? true.

The same verb also converts a Leiningen workspace: project.clj → root and per-module deps.edn — profiles become :aliases, :deploy-repositories becomes :rig/publish, ~var version shorthands resolve, :sub monorepos decompose into sibling :local/root modules. See Migrating from Leiningen for the full key mapping.

After rig migrate, run rig lock and rig check. The check reports the remaining drift between the module requirements and the lock (cross-module conflicts, stale pins).

Inspection#

rig check#

Three stages, one exit code:

  1. Artifact verification (workspace-wide): every lock artifact is re-checked against the pinned hashes — verified from local sources on a warm cache, fetched and hash-checked on a cold one. A hash mismatch exits 4: a tampered entry is reported, never re-fetched and healed. This is the intended first CI gate: it verifies the committed lock, never a fresh re-resolution.

    check: verified 528 artifacts (510 cached, 18 fetched, 2 git deps pinned by commit sha)
  2. Consistency (workspace-wide, read-only) checks: stale-lock (a requirement the pin does not satisfy, or a manifest that changed since the lock was written). conflict (incompatible requirements). drift (a module requirement differs from the workspace requirement — a warning). floating-version (RELEASE/LATEST in a manifest — an error; fix it with rig update <coord>). git-ref (a git coordinate without a full 40-character :git/sha — an error; the refused forms are :git/tag, :git/branch, a short sha, and the legacy :tag/:sha keys). no-lib (publish without :rig/lib). unknown-repo (the lock pins via a repo that no manifest declares). pool-unpinned (a :rig/deps entry the lock does not pin — a warning).

  3. Namespace load and AOT-compile: Rig preloads the non-project requires on the locked base classpath of each target module, then AOT-compiles its namespaces in dependency order. A failing load or compile produces a load-fail error. A source the AOT plan left out — a data file without an ns form, a namespace whose name does not match its path — is a plan-skip warning. Rig reports a module that pins org.clojure/clojure below the 1.8.0 floor as clojure-floor, before it launches any JVM (the runner entry point cannot load on Clojure 1.7.x). Stage 3 launches on the locked classpath as-is: on Clojure ≥ 1.9 the runtime itself requires org.clojure/spec.alpha to be present (it loads clojure.core.server at init). A module that declares no spec (directly or transitively) therefore fails with a spec/alpha class-not-found — a missing project dependency, not a Rig failure.

check: error [stale-lock] modules/app org.clojure/clojure: manifest requires "1.11.0"; lock pins "1.12.5" — run rig update
check: 1 error(s), 0 warning(s)

or, clean:

check: verified 528 artifacts (510 cached, 18 fetched)
check: ok

A missing lock is the exception: one message, exit 3. --offline makes the artifact stage a hermeticity proof: every artifact must already sit in the cache or a checksum-checked ~/.m2, else exit 1.

-p restricts stage 3 only. check never re-locks and never exits 3 for a stale lock — it reports staleness as a problem and exits 1.

rig outdated#

mvxcvi/arrangement 1.2.0 -> 1.2.1 (latest 2.1.0, breaking)

--breaking lists only breaking updates. The command prints up to date when it finds none.

rig tree#

Print the resolved dependency tree for a module (-p), one line per occurrence with ├─/└─ connectors. Rig marks an occurrence that is not in the classpath (conflict, exclusion, duplicate) with its reason. --alias <a> includes the extra-deps of the alias.

rig info#

info prints the workspace summary: modules, lock state (and staleness), JVM, cache dir, Rig and kernel versions. The version line prints the project version from the VERSION file (module dir, then workspace root) or the locked module version; -p selects the module. When no source records a version, the line reads -.

Running#

rig test#

rig test [--timeout <dur>] [opt value…]

Run the test exec-fn of each target module (from the lock) on its locked test classpath. Without -p, every module with a test exec-fn runs, in the declaration order of :rig/modules. The arguments are EDN literals, and Rig forwards them to the runner:

rig test :kaocha.filter/focus '[:unit]'

When a runner fails, Rig exits 1 and names the failing modules. A hung run does not wedge CI: rig test kills a runner that has not finished in 30 minutes and fails — --timeout <dur> configures the watchdog, 0 disables it. A module that pins org.clojure/clojure below the 1.8.0 floor fails before anything runs (the same clojure-floor gate as check). The :test alias of a scaffolded module carries the kaocha JUnit XML and coverage reporters as extra-deps, dormant until a run loads them with :plugins — see day-to-day workflow.

rig run#

rig run [args…]

Launch the :rig/main of the module on the (alias) classpath. Program flags after -- pass through: rig run -p modules/app -- --env dev. --alias <a> selects the classpath. No main → usage error.

rig launch#

rig launch [jar] [args…]

Launch the built artifact with the production JVM flags of Rig — the entrypoint for a deployed app. rig launch replaces its own process with the JVM (process exec): the app is the process itself. In a container, the app is PID 1. Signals reach the JVM directly, and the exit code of the JVM is the exit code of the process. On Windows, where there is no process exec, rig forks the JVM and waits. Flags, in order:

  1. The production defaults of Rig: G1 garbage collection (-XX:+UseG1GC, with -XX:+AlwaysPreTouch), exit on out-of-memory (-XX:+ExitOnOutOfMemoryError, plus -XX:+HeapDumpOnOutOfMemoryError), and loopback-only JMX on port 10101 (-Dcom.sun.management.jmxremote with authenticate=false and ssl=false). Rig pins the RMI port to 10101, and -Djava.rmi.server.hostname=127.0.0.1 keeps JMX to same-host clients.
  2. The :rig/launch-opts of the module — later flags override the defaults (last JVM flag wins). A garbage collector in :rig/launch-opts, for example -XX:+UseZGC, replaces the G1 default: the JVM refuses to start with two collectors, so Rig drops its own rather than pass both.
  3. RIG_LAUNCH_OPTS (env var) — per-deployment JVM flags, whitespace-separated, appended last; the same rules apply (last JVM flag wins; a collector in it replaces any earlier selection).
  4. -jar <uberjar>, or -cp <locked classpath> <main> for the plain jar.

The first positional is the jar when it names an existing file. Otherwise (in a workspace) all positionals go to the main. The jar is then the build output of the target module from the lock (the uberjar when the module declares one).

The launch plan (main, :rig/launch-opts, build JVM) comes from META-INF/rig/launch.json. rig build bakes that descriptor into the jar of a module that declares a main (uberjars carry it too), so rig launch <jar> works outside the workspace (a standalone container). Without the descriptor, the lock is the plan.

rig launch is offline by definition: it runs what is already in the cache, from a previous build. The lock is inert data for it: it ignores a stale lock. Classpath artifacts must already be in the cache. The major version of the launch JVM must exactly match the major version of the build JVM; a different major fails with exit 2. A missing artifact fails too — it is not fetched — as a plain error (exit 1).

rig nrepl#

rig nrepl [--alias <a>] [--host <iface>] [--port <n>]

Start an nREPL server on the (alias) classpath, in the module directory, using the nREPL jar Rig ships inside the binary (so no dependency download, and the version is Rig's, not your project's). With neither --host nor --port, it binds the loopback interface on a free port and prints the endpoint (nREPL server started on port …) — point your editor at it. --host and --port override the bind target.

A project that declares nrepl/nrepl itself (in an alias, say) keeps its own version: Rig appends its jar to the classpath last, so the project's copy wins. The shipped nREPL needs Clojure 1.10 or newer; on an older pin rig nrepl stops with a hint to raise the pin or run your own nREPL via rig exec. --alias <a> selects the classpath, as with the other dev commands. A scaffolded project's development module is the usual target: rig nrepl -p dev.

rig exec#

rig exec [--alias <a>] <command> [args…]

Run any command with the locked classpath that Rig exports as CLASSPATH (and JAVA_OPTS from the module/alias JVM options), in the module directory. --alias <a> selects the classpath. Rig exits with the exit code of the command. Use it for scripts and tools Rig has no verb for.

Authentication#

rig auth get#

rig auth get [gate|url] [--flow browser|device]

Print the bearer token of an OIDC gate to stdout. The gate comes from the gate config (~/.config/rig/auth.yaml): pass a gate name or a repository URL the gate fronts, or nothing when the config holds a single gate. Rig uses the RIG_TOKEN_<GATE> environment variable of the gate when you set it, else the cached token of the gate, else a fresh negotiation with the issuer of the gate. Rig verifies a freshly negotiated token against the JWKS before caching it, and uses a token you supply in the environment as you supplied it. The output is machine-friendly: script it into a curl, or pipe it anywhere a bearer belongs. See authenticated repositories.

Building and publishing#

rig build#

rig build [--uber | --native]

Build the jar of the module. --uber builds the uberjar (requires :rig/uberjar?), and --native builds the native-image binary (requires :rig/native? and the :rig/jvm pin of the workspace; the entry point of the binary is :rig/main). Every build runs on the locked classpath. With the :rig/jvm pin of the workspace, Rig scans every jar the build produces against it as the bytecode floor. A class that would not load on the pinned JVM fails the build (see JVMs). The command prints built <path> on success. See Native images.

rig install#

Install the module jar(s) into the local Maven repository — every module with a :rig/lib without -p.

rig publish#

Deploy the module jar(s) to the remote repository from :rig/publish. Rig deploys only the :rig/publish? modules, and Rig requires the network. The repo (:repo is a :mvn/repos id or clojars) must be an http/https Maven repository. Rig uploads the jar and the POM with credentials from ~/.m2/settings.xml. For a repo marked :auth :oidc, Rig uploads instead with the bearer of the gate that fronts its :url (the RIG_TOKEN_<GATE> variable of the gate, the cached token, or a negotiated token).

Hygiene and scaffolding#

rig clean#

Remove the target directories of the target modules (one cleaned <dir> line each).

rig fmt#

Format the module with the cljfmt version pinned in the kernel jar — everyone formats identically. --check reports without fixing. No lock needed.

rig new / rig new-module#

rig new com.example/demo          # scaffold a project (workspace + module)
rig new-module reporting          # add a module to the current workspace, re-lock

new creates <name>/deps.edn (root, :rig/modules ["modules/<name>" "dev"]), <name>/modules/<name>/deps.edn, a runnable src, a test, and the workspace's development module <name>/dev — a deps.edn that loads the app module by :local/root plus reloaded.repl, and a scratch user.clj. new-module scaffolds under modules/, adds the entry to :rig/modules, and re-locks; it does not touch dev — add a new module to dev/deps.edn as {:local/root "../modules/<name>"} when you want it in the development REPL.

Both resolve the scaffold's tooling in one kernel call — the test runner, test.check, spy, and the two kaocha reporters for the module's :test alias, and reloaded.repl for the dev module — at the newest release past each coordinate's cooldown, so a new project starts on what the repositories serve rather than on versions compiled into the binary. --offline writes the versions bundled with the binary, and so does a lookup that has no answer for a coordinate — with a note naming it (every release inside its cooldown, or no repository of the workspace serves it).

rig self-update#

Update the Rig binary from the GitHub releases (hash-verified against the release SHA256SUMS, atomic replace). --check reports only; --version vX.Y.Z targets an exact release. Release builds only. GitHub limits unauthenticated release lookups to 60 requests per hour per IP address; when you set GH_TOKEN or GITHUB_TOKEN, Rig authenticates the lookup with it.

JVM management#

rig manages local Temurin (Eclipse Adoptium) JDKs, one per major version. The requirement of the project is :rig/jvm in the root deps.edn — a major (feature) version, for example 21. The rig-managed JDK takes precedence over the system java. A system JDK whose feature version matches the pin serves only when no managed JDK exists. When neither exists and rig is online, it installs the newest matching release on demand.

rig jvm install#

rig jvm install 21        # newest 21.x

<major> is a major (feature) version. The command resolves the release through the Adoptium API, downloads the archive for the current platform, and verifies the sha256 against the published checksum of the API. It extracts the JDK to the state dir (~/.local/share/rig/jdks/temurin-<version>/). Rig keeps one JDK per major version. When a JDK for the major already exists, this command exits without changes — use rig jvm update to move it to the newest release. --offline refuses (installing needs the network).

rig jvm list#

Installed managed JDKs, then the system java (from JAVA_HOME and PATH):

installed:
  temurin 21.0.12.1+1  linux/x64  /home/…/.local/share/rig/jdks/temurin-21.0.12.1+1
system:
  21.0.5  /usr/lib/jvm/java-21-openjdk/bin/java (JAVA_HOME)

rig jvm path#

rig jvm path 21        # the JAVA_HOME of the installed 21.x

Prints the home directory of the newest installed managed JDK satisfying <major>, as a bare path on stdout, for scripts and CI. This path is the JAVA_HOME value Rig exports for launched processes. The state dir is read only: the command never installs or downloads and needs no network. When no installed JDK satisfies <major>, it fails (exit 2) with the install hint.

rig jvm uninstall#

rig jvm uninstall 21              # the installed 21.x
rig jvm uninstall 21.0.12.1+1     # exact, or unique prefix (rig jvm uninstall 21.0.12)

rig jvm update#

rig jvm update is a workspace command (it needs a :rig/jvm pin in the lock). It updates the rig-managed JDK for the pinned major to the newest release, and replaces the installed one. Rig keeps one JDK per major version. When no JDK for the major exists, the command installs the newest release. The command does not touch the manifest or the lock. --offline refuses (updating needs the network).

Kernel checkpointing (CRaC)#

Cold kernel forks cost 1–3 seconds per command. On Linux, Rig can instead restore the kernel JVM from a checkpoint of a warmed run (~0.3 s). Every command refreshes the checkpoint, so it stays warm with use. Checkpointing is opportunistic: without a CRaC-capable JVM every command takes the cold path, unchanged. See Configuration — Kernel checkpointing.

rig crac install#

rig crac install        # the Zulu CRaC JDK pinned by this Rig release

Downloads the exact CRaC JDK build (Azul Zulu) pinned by the Rig release into the state dir (~/.local/share/rig/jdks/zulu-crac-<version>/), verifying the sha256 against the pin. The kernel picks it up automatically for checkpointing; nothing else changes. --offline refuses (installing needs the network).

rig crac status#

The pinned build, its install status, and whether RIG_CRAC_JDK currently overrides the managed install.

rig crac clean#

Rig keys image chains to the kernel jar bytes, the JVM build and the CPU features: after a kernel or JDK rotation the old chains can never restore again. This prunes them, plus interrupted-run leftovers. Chains rebuild themselves — pruning one that was still live costs one cold command. Old-kernel chains actually clean themselves up: a daily boot sweep prunes chains bootstrapped from a different kernel jar. clean covers what that sweep cannot see (JVM rotations, leftovers). It refuses to run while RIG_KERNEL_JAR is set.

GraalVM management#

rig manages GraalVM community JDKs, one per major version, for native-image builds (rig build --native). Rig derives the requirement from the :rig/jvm pin. You install missing GraalVMs explicitly: rig build --native never downloads, it fails with a hint until rig graalvm install has run.

rig graalvm install#

rig graalvm install 21        # newest 21.x build

<major> is a major (feature) version. The command resolves the build through the graalvm/graalvm-ce-builds GitHub releases, downloads the archive for the current platform, and verifies the sha256 against the .sha256 sidecar of the release. It extracts the GraalVM to the state dir (~/.local/share/rig/graal/graalvm-<version>/graal). Rig keeps one GraalVM per major version. When a GraalVM for the major already exists, this command exits without changes — use rig graalvm update to move it to the newest build. --offline refuses (installing needs the network).

rig graalvm list#

Installed managed GraalVMs:

installed:
  graalvm 21.0.2  linux/x64  /home/…/.local/share/rig/graal/graalvm-21.0.2/graal

rig graalvm path#

rig graalvm path 21        # the GRAALVM_HOME of the installed 21.x

Prints the home directory of the newest installed managed GraalVM satisfying <major> — the GRAALVM_HOME rig build --native uses — as a bare path on stdout, for scripts and CI. The state dir is read only: the command never installs or downloads and needs no network. When no installed GraalVM satisfies <major>, it fails (exit 2) with the install hint.

rig graalvm uninstall#

rig graalvm uninstall 21             # the installed 21.x
rig graalvm uninstall 21.0.2         # exact, or unique prefix (rig graalvm uninstall 21.0)

rig graalvm update#

rig graalvm update is a workspace command. It needs a graalvm block in the lock, so the workspace needs a :rig/jvm pin and a :rig/native? module. It updates the rig-managed GraalVM for the pinned major to the newest community build, and replaces the installed one. Rig keeps one GraalVM per major version. When none exists, the command installs the newest build. The command does not touch the manifest or the lock. --offline refuses (updating needs the network).

Global flags#

Flag Meaning
-p, --path <module> Target one module (default: all workspace modules, in :rig/modules order; . = root module). One module per command — a repeated -p is a usage error (exit 2).
--offline Never use the network. Artifacts come from the cache or a checksum-checked ~/.m2; fail if in neither.
--force Bypass cooldowns (the decision is recorded in the lock).
--cache-dir <dir> State directory (artifact cache + kernel jars). Default ~/.local/share/rig; honors $XDG_DATA_HOME.
-v, --verbose Debug logging.
--autocomplete [shell] Print the shell completion script to stdout: bash, zsh, fish or powershell; no value = detect the running shell.

Shell completion (detects your shell; -p completes module paths, --alias completes the aliases of the module):

eval "$(rig --autocomplete)"            # bash
source <(rig --autocomplete)            # zsh
rig --autocomplete | source             # fish
rig --autocomplete | Invoke-Expression  # PowerShell

Exit codes#

Code Meaning
0 success
1 failure — build/test/publish/resolve error, or a check error
2 usage error — bad flag, missing main, module not in the lock, …
3 lock problem — missing or stale lock on a command that does not write it
4 security failure — artifact hash mismatch / not in the lock
5 cooldown refused — retry with --force

Commands that launch a child process (run, nrepl, exec, fmt) propagate the exit code of the child verbatim, above these. launch is the purest form of it: it execs the JVM, so the exit code of the JVM is the exit code of the process. test and check interpret their runner instead: a failing runner makes Rig exit 1 with its own message; any other runner exit code becomes a plain Rig error (exit 1).