Skip to main content
Optimized model packages are large. A kit can run to tens of gigabytes, and the machine that needs it is usually a GPU host you reached over SSH, not the laptop you are reading this on. The RunInfra CLI exists for that: you approve the terminal once from your browser, then pull packages your workspace owns directly onto the machine that will serve them.
The CLI never asks for your password and never asks you to copy an API key. Approving in the browser creates the credential, stores it in a file only your user account can read, and you revoke it from Settings whenever you want.

Before you start

A terminal, and nothing else

The standalone build needs no Node and no Python. If you would rather use a package manager you already have, pip and npm install the same client.

A role that can deploy

Connecting a terminal grants package downloads, so it needs a role in the workspace that can deploy. A viewer sees an explanation instead of an Approve button.
Your workspace also has to own the package you are pulling. Buy it from the catalog first, then come back here.

Install

Three ways in. They install the same client, so pick whichever matches the machine you are standing on.
A single self-contained executable that carries its own runtime. This is usually the right answer on a GPU host, which is the machine most likely to be pulling forty gigabytes and least likely to have a toolchain on it.The installer checks the download against the release checksums, and checks those checksums against our signature, before it writes anything into place. It tells you the directory it used and prints the command to add it to your PATH rather than editing your shell profile behind your back.On Windows, in PowerShell:
Whichever you choose, the CLI tells you when a newer version is out. It reads that from a response header on a request it was already making, so it never phones home, and it never updates itself. It prints the one command to run, correct for how you installed it.

The happy path

1

Connect the terminal

The CLI prints a short code and a URL:
The code is valid for 15 minutes.
2

Approve it in your browser

Open the URL on any device where you are signed in to RunInfra and type the code. You will see the account, the workspace, the terminal that asked (shown as user@host), the code you typed, and the single thing it grants: downloading optimized model packages the workspace already owns.Press Approve. The browser confirms, and the terminal continues on its own:
Access lasts 90 days unless you revoke it sooner.
3

Pull the package

The final path is the only thing printed to standard output, so MODEL=$(runinfra pull qwen3-6-27b) captures the path and nothing else.
Use --concurrency N (1 to 16, default 8) to tune parallel connections, and --out DIR to choose the destination. Without --out the file lands in the current directory.

On a headless GPU host

Nothing changes. The CLI does not try to open a browser over SSH, in CI, or on a machine with no graphical display, so it goes straight to the code and tells you why:
Type that code into your laptop’s browser and approve. The GPU host is connected without a browser ever running on it. runinfra login --device forces this path from any machine.
You type the code, you never click a link that contains it. The approval page has no field that can be filled in from a URL. If you ever receive a link with a sign-in code already in it, it did not come from RunInfra, and approving it would connect somebody else’s terminal to your workspace.

Check what a machine is holding

This reads the local file. It does not ask the server, so a terminal revoked five minutes ago still appears here and fails on its next command.

Verify the CLI you downloaded

The installers already do this for you and refuse to install anything that does not check out. This section is for when you want to confirm it yourself, or when your policy requires a signature on anything that reaches a production host. Every release publishes SHA256SUMS alongside the executables, and SHA256SUMS.sig, an Ed25519 signature over those checksums.
Confirm the key is ours before you trust it. Its fingerprint is:
A key you downloaded from the same place as the file it verifies proves nothing on its own, because whoever replaced one could replace both. That fingerprint is also pinned inside install.sh and published on the npm page, neither of which serves the binaries.
What a good signature proves. The file came out of the RunInfra release pipeline and has not been altered since. That is what defeats an edited asset or a hostile mirror. What it does not prove. That the pipeline itself was not subverted. The signing key lives in our release automation, so anyone who could tamper with that automation could also sign. We would rather say this plainly than let a green checkmark imply more than it means. On macOS, /usr/bin/openssl is LibreSSL and has no -rawin, so the command above needs a real OpenSSL, for example brew install openssl@3. Windows PowerShell has no built-in Ed25519 at all, so install.ps1 verifies the checksum and tells you the signature was not checked rather than pretending otherwise.

Revoke a terminal

Two different actions, and it matters which one you need.
Open Settings, API keys in the dashboard. Every terminal you connected is listed as RunInfra CLI: user@host, with when it was created and when it was last used. Revoke the row.The next command that terminal runs is refused:
This is what to use for a lost laptop, a decommissioned GPU host, or a contractor who is finished. Revocation applies to the next request. A download URL already handed out stays usable for up to 30 minutes, so revoking stops new downloads rather than reaching into a transfer already in flight.
This deletes the local file only. It does not revoke anything, and it says so, because deleting a file on a machine you still control is not how you handle a machine you have lost.
Your role is re-checked on every command. Removing someone from the workspace, or lowering their role below deploy, cuts off their connected terminals immediately without touching any keys.

When a download is interrupted

Run the same command again. That is the whole procedure. The CLI keeps the bytes it already has and continues from there.
A second Ctrl-C exits immediately. Dropped connections, expired download URLs and slow links are all handled inside a single run and need no action from you. While a download is in progress you will see two files next to the destination: <name>.part holds the bytes, and <name>.part.json records which parts are safely written. Both disappear when the download finishes. The finished file only ever appears under its real name once the bytes are complete and verified, so anything watching that directory can never pick up a half-downloaded package.
The CLI restarts rather than resuming in three cases, and prints which one applies:
  • The resume record is missing or unreadable. The partial file is preallocated to the full size, so its length says nothing about which bytes are real. Guessing would produce a file that fails its checksum hours later.
  • The package was republished while you were downloading. Continuing would mix two versions into one file.
  • A file with the final name already exists at a different size. Nothing is overwritten. Move it, or pass a different --out.
The file is never renamed to its final name when this happens, so you cannot accidentally serve corrupt bytes. Delete the .part file and pull again. If it happens twice on the same package, contact support with the slug.
Free space is checked before the first byte is written, against what is left to fetch plus a small margin:
Free space or point --out at a larger volume. Anything already downloaded is still there.
Check the slug on the package page in the catalog. If you are in more than one workspace, check that this terminal is connected to the one that bought it: runinfra whoami prints the workspace id.
A connected terminal lasts 90 days. Run runinfra login again to reconnect it. Downloads you already completed are unaffected.

Exit codes for scripts

Failures are grouped so a CI job can tell a transient blip from a permanent refusal instead of retrying everything forever.
In a container image build, run runinfra login --device once on a machine with a browser and mount the credentials directory, or set RUNINFRA_CONFIG_DIR to a path your build can read. Sign-in is interactive by design: there is no way to mint a terminal credential without a human approving it.