CLI Quickstart (CLI-PKG-06)

Run Yaarbal entirely from a terminal — no desktop app, no browser — on macOS, Windows, or Linux/WSL. Every command below was re-verified against --help in the same session this doc was written; if something here stops matching the CLI, scripts/check_cli_docs.sh will catch it.

0. What you get / who this is for

Three pieces, all reachable through one entry point:

A desktop app exists in the repository but is not shipped in this beta, so the CLI is the way to earn on every platform; the Personal Cloud Quickstart walks through using it for your own GPU. The public tracker origin is https://rmg-tracker-oracle.yaarbal.app.

Everything below runs inside a Python venv the install scripts create. yaarbal is the single entry point for every command in this doc — yaarbal <command> --help always works and always reflects the real flags. (rentmygpu, the command's earlier name, still works as an alias for the same program.)

1. Install

You need Python 3.11 or newer. The yaarbal wheel (yaarbal-<version>-py3-none-any.whl), the installer scripts (install.sh, install.ps1) and a SHA256SUMS file are on the download page, https://docs.yaarbal.app/dl/, which lists the current wheel with its SHA-256. There is no package-index listing during the beta (no pip install yaarbal from an index), and the source repository is not public. The commands below fetch the installer and SHA256SUMS, then hand the installer the wheel's URL and SHA-256. It downloads the wheel itself and stops on a mismatch.

The installer creates a venv at ~/.rentmygpu-venv (%USERPROFILE%\.rentmygpu-venv on Windows), picks the llama-cpp-python build that matches your GPU from that project's prebuilt-wheel index, and installs the wheel into the venv. Nothing is installed system-wide. With neither a wheel nor a checkout it stops and tells you to set YAARBAL_WHEEL; it never guesses a download address.

YAARBAL_WHEEL_SHA256 is the hex from SHA256SUMS. The installer forwards it to pip as a #sha256= fragment and refuses a wheel that does not match. YAARBAL_WHEEL may also be a local file path if you downloaded the wheel yourself. To check the installer you downloaded against the listing, run sha256sum --ignore-missing -c SHA256SUMS (macOS: shasum -a 256 --ignore-missing -c SHA256SUMS).

macOS

curl -fsSLO https://docs.yaarbal.app/dl/install.sh
curl -fsSLO https://docs.yaarbal.app/dl/SHA256SUMS
YAARBAL_WHEEL=https://docs.yaarbal.app/dl/yaarbal-0.1.0-py3-none-any.whl YAARBAL_WHEEL_SHA256=c05a5304c936a34e1d82191903deb7b3b430905f0111aaa68bf08a2f473ad67d bash install.sh
source ~/.rentmygpu-venv/bin/activate

Apple Silicon picks the prebuilt Metal wheel automatically. Intel Macs have no prebuilt wheel, so install.sh falls back to a source build — install Xcode Command Line Tools first (xcode-select --install). Nothing here is code-signed or notarized, but that only matters for the desktop app, not the CLI. Manual fallback, in a venv of your own: pip install "yaarbal[seeder] @ https://docs.yaarbal.app/dl/yaarbal-0.1.0-py3-none-any.whl#sha256=c05a5304c936a34e1d82191903deb7b3b430905f0111aaa68bf08a2f473ad67d" --extra-index-url https://abetlen.github.io/llama-cpp-python/whl/metal/. Preview any run by adding --dry-run.

Windows

Requires PowerShell 5.1+ and Python 3.11+ from python.org (not the Microsoft Store alias — untick "App execution aliases" under Settings → Apps if python resolves to a stub):

Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
Invoke-WebRequest https://docs.yaarbal.app/dl/install.ps1 -OutFile install.ps1
Invoke-WebRequest https://docs.yaarbal.app/dl/SHA256SUMS -OutFile SHA256SUMS
$env:YAARBAL_WHEEL_SHA256 = "c05a5304c936a34e1d82191903deb7b3b430905f0111aaa68bf08a2f473ad67d"
.\install.ps1 -Wheel https://docs.yaarbal.app/dl/yaarbal-0.1.0-py3-none-any.whl
& "$env:USERPROFILE\.rentmygpu-venv\Scripts\Activate.ps1"

install.ps1 reads the hash from $env:YAARBAL_WHEEL_SHA256 (there is no hash parameter); for an https:// wheel, pip verifies it through the #sha256= fragment. Flags: -Wheel, -Flavor, -NoSeeder, -DryRun, -Extras. You can also skip activation and call %USERPROFILE%\.rentmygpu-venv\Scripts\yaarbal.exe directly. Manual fallback, in a venv of your own: pip install "yaarbal[seeder] @ https://docs.yaarbal.app/dl/yaarbal-0.1.0-py3-none-any.whl#sha256=c05a5304c936a34e1d82191903deb7b3b430905f0111aaa68bf08a2f473ad67d" --extra-index-url https://abetlen.github.io/llama-cpp-python/whl/cu124/ (NVIDIA) or the .../whl/cpu/ index otherwise. Preview with -DryRun.

Linux + WSL

curl -fsSLO https://docs.yaarbal.app/dl/install.sh
curl -fsSLO https://docs.yaarbal.app/dl/SHA256SUMS
YAARBAL_WHEEL=https://docs.yaarbal.app/dl/yaarbal-0.1.0-py3-none-any.whl YAARBAL_WHEEL_SHA256=c05a5304c936a34e1d82191903deb7b3b430905f0111aaa68bf08a2f473ad67d bash install.sh
source ~/.rentmygpu-venv/bin/activate

An NVIDIA GPU (detected via nvidia-smi) picks the cu124 wheel. On WSL, install.sh additionally installs the nvidia-*-cu12 runtime packages and prints "see the CLI quickstart docs for the preload command" — that's §7 below, and you must do it before llama_cpp will import. Manual fallback, in a venv of your own: pip install "yaarbal[seeder] @ https://docs.yaarbal.app/dl/yaarbal-0.1.0-py3-none-any.whl#sha256=c05a5304c936a34e1d82191903deb7b3b430905f0111aaa68bf08a2f473ad67d" --extra-index-url https://abetlen.github.io/llama-cpp-python/whl/cu124/ or .../whl/cpu/ on a machine with no NVIDIA GPU. Preview by adding --dry-run.

Options for every platform

Override the venv location with RMG_VENV_DIR, or force a wheel flavor with RENTMYGPU_LLAMA_FLAVOR=metal|cu124|cpu|source (same as --flavor/-Flavor). --no-seeder / -NoSeeder skips llama-cpp-python altogether — enough for yaarbal spend, not for the seeder or the proxy's tool-calling path.

Updating: run the installer again with the newer wheel URL and SHA-256 from the download page; it reuses the venv. Uninstalling: delete the venv folder. Your identity, models and settings live separately under ~/.rentmygpu and are not touched by either.

From a source checkout (team members)

This path needs access to the private source repository and is for people working on Yaarbal itself. From the root of your checkout, the same scripts do an editable install into <checkout>/.venv when no wheel is named:

scripts/install.sh
source .venv/bin/activate
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
.\scripts\install.ps1
.\.venv\Scripts\Activate.ps1

Manual fallback: pip install -e ".[tracker,seeder]" plus the --extra-index-url for your platform shown above. The wheel users install is built by python scripts/build_public_wheel.py --out dist, which builds the full wheel, strips the coordinator (rentmygpu/tracker/, rentmygpu/ledger/, migrations/, the token operator CLI and the rentmygpu-tracker / rentmygpu-token scripts), regenerates RECORD and prints its SHA-256. scripts/deploy_docs.sh builds that same wheel and publishes it with install.sh, install.ps1 and SHA256SUMS to the download page, re-rendering this guide with the current filename and hash (the yaarbal-0.1.0-py3-none-any.whl and c05a5304c936a34e1d82191903deb7b3b430905f0111aaa68bf08a2f473ad67d tokens in this file's source are replaced at build time, which is why they appear in the commands above). python scripts/check_wheel_contents.py --public --wheel dist/<file> re-checks it; without --public the same script checks the FULL wheel that pip install -e . and deploy/Dockerfile use. The tracker is not in the public wheel, so yaarbal --help lists no tracker / token there and yaarbal tracker prints "not included in the public build".

2. Identity

Your identity is a single Ed25519 keypair — this is your account on the network, no signup or email.

yaarbal identity init
yaarbal identity export

identity export prints an armored rmg1-... seed you can back up or move to another machine with yaarbal identity import <ARMORED> (or pipe it in with yaarbal identity import -). The key lives at ~/.rentmygpu/identity.key (Windows: %USERPROFILE%\.rentmygpu\identity.key — both resolve via Path.home()). This is the seeder's identity — see §5 for why the spender uses a separate one.

3. Get a model

yaarbal models list
yaarbal models pull llama-3.2-1b-instruct-q4_k_m
yaarbal models path llama-3.2-1b-instruct-q4_k_m
yaarbal models dir

models pull is resumable, downloads only from Hugging Face, and checks the finished file's size and — for every catalog entry that pins one — its SHA-256 before the model appears under its final name; a file that fails the hash is deleted and the pull exits non-zero. llama-3.2-1b-instruct-q4_k_m (0.8 GiB) is a good small first pull; phi-3-mini-4k-instruct-q4_k_m (2.2 GiB) is a second reasonable option. qwen3.5-9b-q4_k_m (5.7 GiB) is the newest catalog entry, and the model the operator's own public node usually serves. Models land under RENTMYGPU_MODELS_DIR (default ~/.rentmygpu/models; PowerShell: $env:RENTMYGPU_MODELS_DIR = "D:\rentmygpu\models"). The desktop app shares this same store, so a model pulled here is visible there too.

4. Earn: run the seeder against the public tracker

Claim your grant first. The public tracker only accepts a seeder whose identity has already redeemed an invite, so do this once before you start serving. The tracker issues one self-serve code per identity, and one command asks for it and redeems it:

yaarbal seeder --request-invite --claim-benchmark --tos-version <version> --tracker-url https://rmg-tracker-oracle.yaarbal.app

It prints two JSON lines: first {"status":"issued","invite_code":...}, then the claim result (the last line). The request is idempotent, so re-running it returns the same code. When the day's quota is used up, it prints {"status":"waitlisted","position":N,...} and exits with code 2 without claiming; re-run later, the same identity keeps its place.

If you would rather do it in two steps, or an operator gave you a code, ask for the code and redeem it separately:

yaarbal seeder --request-invite --tracker-url https://rmg-tracker-oracle.yaarbal.app
yaarbal seeder --claim-benchmark --invite-code <code> --tos-version <version> --tracker-url https://rmg-tracker-oracle.yaarbal.app

--request-invite and --invite-code are mutually exclusive.

Then serve:

yaarbal seeder --model llama-3.2-1b-instruct-q4_k_m --tracker-url https://rmg-tracker-oracle.yaarbal.app

--tracker-url falls back to RENTMYGPU_TRACKER_URL, then [tracker] url in ~/.rentmygpu/config.toml; with none of those set, the seeder serves standalone with no announce. --model-path <file.gguf> also works if you'd rather point at a file directly than a catalog id. A missing model file exits with code 2 and a yaarbal models pull <id> hint. Defaults: port 7001, host 127.0.0.1 — behind NAT, the tracker's pull-dispatch relay still routes jobs to you, no port forwarding needed. Ctrl+C stops the seeder cleanly (it unregisters on the way out).

Honest note on the beta gate: the claim above is what the invite is for. It mints your starting credits, and it is also what lets you announce: a seeder whose identity has claimed neither the benchmark grant nor the web welcome grant is rejected with 403 invite_required and never appears in discovery. (The seeder keeps running and logs announce.rejected; claim, and the next heartbeat goes through.) A tracker whose operator set RENTMYGPU_ANNOUNCE_REQUIRE_INVITE=0 accepts any signed announce. Invites are self-serve and one code per identity: the --request-invite command above asks for this identity's code. The tracker issues 25 codes a day network-wide; later requests are waitlisted in order and served on the following days. A code is single-use and goes to the first identity that claims it, so a spender identity needs its own (web app, Request an invite on the welcome-grant card). See (internal reference)INVITE-LOOSENING.md for the gate-loosening policy.

Run it unattended (systemd on Linux/WSL, launchd on macOS)

Ctrl+C-style clean unregister (the seeder's SIGTERM/SIGINT handler unregisters from the tracker before exit) also happens on systemctl --user stop / launchctl unload — no seeder code change was needed to support either.

Linux / WSL (systemd user unit):

# a) re-run scripts/install.sh once per machine before enabling the unit
bash scripts/install.sh

# b) copy the unit, then edit --model and (for a source checkout, or a
#    custom RMG_VENV_DIR) the venv path inside it
mkdir -p ~/.config/systemd/user
cp deploy/yaarbal-seeder.service ~/.config/systemd/user/
"$EDITOR" ~/.config/systemd/user/yaarbal-seeder.service

# c) WSL only: /etc/wsl.conf needs [boot] systemd=true, then restart WSL
#    from Windows (wsl --shutdown) — closing the terminal is not enough

# d) REQUIRED so the seeder survives logout/SSH close
loginctl enable-linger "$USER"

# e) enable + start
systemctl --user daemon-reload
systemctl --user enable --now yaarbal-seeder

# f) tail the logs
journalctl --user -u yaarbal-seeder -f

The CUDA fork (see (internal reference)deploy/yaarbal-seeder.service): Recipe A (§7, recommended) needs no extra environment in the unit; Recipe B needs LD_LIBRARY_PATH=... set in ~/.rentmygpu/seeder.env (the unit's EnvironmentFile).

macOS (launchd user agent):

# a) re-run scripts/install.sh once per machine before loading the agent
bash scripts/install.sh

# b) launchd does not expand ~, so substitute your real home directory
mkdir -p ~/Library/Logs/Yaarbal ~/Library/LaunchAgents
sed "s#/Users/<you>#$HOME#g" deploy/app.yaarbal.seeder.plist \
  > ~/Library/LaunchAgents/app.yaarbal.seeder.plist
"$EDITOR" ~/Library/LaunchAgents/app.yaarbal.seeder.plist   # edit --model

# c) load it
launchctl load -w ~/Library/LaunchAgents/app.yaarbal.seeder.plist

# d) tail the logs
tail -f ~/Library/Logs/Yaarbal/seeder.log

Stop with systemctl --user stop yaarbal-seeder (Linux/WSL) or launchctl unload ~/Library/LaunchAgents/app.yaarbal.seeder.plist (macOS).

Context window and prompt cap (Phase 26)

Raising the window (RENTMYGPU_SEEDER_N_CTX / --n-ctx). The seeder's context window (n_ctx) defaults to 8192, unchanged — CLI beats env (--n-ctx wins over RENTMYGPU_SEEDER_N_CTX, which wins over the 8192 default). The shipped default is deliberately NOT raised: an 8GB Apple Silicon machine does not fit a 32k window, and the memory pre-flight below fails open off-darwin, so a bad default would go uncaught on the machines that could least afford it. Raise it explicitly when you need a larger window (agentic coding prompts routinely need more than 8k):

export RENTMYGPU_SEEDER_N_CTX=32768
yaarbal seeder --model qwen3.5-9b-q4_k_m --tracker-url https://rmg-tracker-oracle.yaarbal.app
$env:RENTMYGPU_SEEDER_N_CTX = "32768"
yaarbal seeder --model qwen3.5-9b-q4_k_m --tracker-url https://rmg-tracker-oracle.yaarbal.app

The env knob exists specifically so the frozen desktop sidecar (spawned with fixed args by the Tauri shell) can be raised without a rebuild — the desktop process's environment is inherited by the sidecar it spawns.

Headroom (cited, not measured here): on a 12GB card, a 32k window fits in 7,884 MiB, and a 64k window fits in 9,996 MiB — figures recorded in .planning/ROADMAP.md / the Phase 26 context doc, not re-measured on this machine. Confirm on your own hardware before committing to a window size in production.

The macOS auto-fit ladder. On Apple Silicon, resolve_load_plan sizes the request against a fraction of total unified memory and auto-fits n_ctx DOWN the ladder 32768 → 16384 → 8192 → 4096 → 2048 → 1024 when the requested window doesn't fit, so a 64k request degrades rung by rung instead of cliffing straight to 4096. Off macOS (Linux/CUDA), this pre-flight fails OPEN — the guard cannot read VRAM from the stdlib, so it loads at whatever window you asked for with no auto-fit and no refusal; sizing a CUDA box correctly is the operator's responsibility (see the headroom figures above).

The prompt cap (RENTMYGPU_SEEDER_MAX_PROMPT_CHARS). The /infer char cap rises in step with the resolved window: it is derived from n_ctx at roughly 4 chars/token plus the e2ee ciphertext's exact 4/3 base64 expansion, floored at 32,000 chars so no currently-accepted request ever regresses. RENTMYGPU_SEEDER_MAX_PROMPT_CHARS sets an absolute ceiling on top of the derived value (applied as a minimum, never a second independent cap):

export RENTMYGPU_SEEDER_MAX_PROMPT_CHARS=100000

Honest note on the e2ee path: /infer is e2ee fail-closed in production, and the prompt is still ciphertext at the point the cheap pre-slot char cap runs. The token-accurate over-context check can only run AFTER decryption — which happens after the inference slot is already acquired — so on the real (e2ee) path, an over-context prompt is rejected with a clean 400 prompt_exceeds_context_window after the slot is taken, before any generation begins, not before the slot. The char cap still bounds the ciphertext pre-slot as a cheap DoS guard either way.

Prefix cache sizing. The seeder's LlamaRAMCache (on by default, RENTMYGPU_SEEDER_PROMPT_CACHE_MB, 0 disables it) needs to grow alongside a raised window to hold a full KV prefix and keep the time-to-first-token plateau CTX-05 relies on:

n_ctx Derived default cache
8192 1024 MB (unchanged)
16384 1056 MB
32768 2112 MB
65536 4224 MB

The ~66 KB/token estimate behind this table is back-computed from the cited VRAM totals above, NOT independently measured — treat it as a starting point, not a guarantee. A no-GQA model can be far denser than this table assumes (spike 024 measured ~0.4 MB/token on Phi-3-mini, roughly 6x denser than the estimate here). RENTMYGPU_SEEDER_PROMPT_CACHE_MB always overrides the derived value, and 0 disables the cache entirely regardless of window size.

Thinking models (RENTMYGPU_SEEDER_CHAT_THINKING)

Qwen3 / Qwen3.5 / 3.6 / 3.8 and Gemma 4 can "think" (write hidden reasoning) before they answer. The web app and yaarbal spend --chat send a prompt that stops right after the assistant turn opens, which leaves that choice to chance — and a thinking Qwen3.5-9B can spend its whole token budget on reasoning. So by default (off) the seeder closes the decision itself: when a raw prompt ends exactly at the assistant opener of a model whose own GGUF chat template has a thinking switch, it appends that template's own thinking-off text before generating (and counts it toward the context window). Prompts that already decide (end with <think> or an empty think block, as the agentic proxy renders them), raw completion prompts, and models without a thinking switch are untouched. Set passthrough to get the old behaviour back; any other value is treated as off with one warning. Read at model load, so restart the seeder after changing it:

export RENTMYGPU_SEEDER_CHAT_THINKING=passthrough

DeepSeek R1 (deepseek-r1-0528-qwen3-8b-q4_k_m) is the exception: it always thinks, and its template has no thinking switch, so off has no effect on it and the seeder never appends anything to its prompts. Expect long reasoning before the answer; on a hard question it can use most of the 8192-token job cap just thinking. (For this model the seeder also adds the model's beginning-of-sentence marker itself, because its GGUF asks the tokenizer not to.)

5. Spend from the CLI

Pull mode (no seeder URL needed, works through NAT). Right now the operator's own node usually serves qwen3.5-9b-q4_k_m — best-effort, and it may be offline when you try; GET /models on the tracker lists what's live at any moment, so substitute another --model-name if it isn't:

yaarbal spend --pull --model-name qwen3.5-9b-q4_k_m --param-size-b 9.0 --prompt "Say hi" --tracker-url https://rmg-tracker-oracle.yaarbal.app

Direct mode (talk straight to a seeder you know the address of):

yaarbal spend --seeder-url http://127.0.0.1:7001 --prompt "Say hi"

--tracker-url uses the same fallback chain as the seeder. --max-tokens defaults to 64. The spender identity is separate by default: ~/.rentmygpu/spend-identity.key (override with --identity) — a seeder can never bill itself, so never point --identity at your seeder's identity.key.

Plainly: the spender needs credits, and there is no CLI faucet command. On the public tracker, the spender identity's welcome grant comes from the web app: sign in there with this spender identity via the export/import in §2 and press Request an invite. That is one code per identity; the seeder's --request-invite is for the seeder identity only. See §6 for the local- tracker path, which works around this.

6. Everything on one laptop

Three terminals: a local tracker, a seeder, and a spender. Both a bash and a PowerShell version below.

bash

Terminal 1 — tracker:

export RENTMYGPU_INVITE_GATE=0
export RENTMYGPU_ANNOUNCE_REQUIRE_INVITE=0
yaarbal tracker

(Optionally set RENTMYGPU_LEDGER_PATH to a scratch file first, so this doesn't touch your real ledger.) yaarbal tracker always runs a single worker process — the peer registry and job queue live in that one process, so this is enforced, not configurable. (Team members: the full rundown is in (internal reference)../deploy/PERSONAL.md §3/§4 of the source checkout.) Verify: curl -fsS http://127.0.0.1:8000/health.

Terminal 2 — seeder:

yaarbal seeder --model llama-3.2-1b-instruct-q4_k_m --tracker-url http://127.0.0.1:8000

Terminal 3 — credits for the spender (the honest, awkward path): --claim-benchmark always signs with Path.home()/.rentmygpu/identity.key, so to mint the local RENTMYGPU_BENCHMARK_FAUCET_GRANT (30000 credits) onto a second identity, run it once under an overridden home:

HOME=$PWD/.spender yaarbal seeder --claim-benchmark --tracker-url http://127.0.0.1:8000
yaarbal spend --identity .spender/.rentmygpu/identity.key --seeder-url http://127.0.0.1:7001 --tracker-url http://127.0.0.1:8000 --prompt "Say hi"

--invite-code/--tos-version aren't needed here because RENTMYGPU_INVITE_GATE=0 turned the gate off, and the seeder in terminal 2 could announce without claiming anything because RENTMYGPU_ANNOUNCE_REQUIRE_INVITE=0 turned the announce gate off. Leave that second line out and the local seeder is rejected with 403 invite_required until its identity claims the benchmark grant.

PowerShell

Terminal 1 — tracker:

$env:RENTMYGPU_INVITE_GATE = "0"
$env:RENTMYGPU_ANNOUNCE_REQUIRE_INVITE = "0"
yaarbal tracker

Verify: Invoke-WebRequest http://127.0.0.1:8000/health.

Terminal 2 — seeder:

yaarbal seeder --model llama-3.2-1b-instruct-q4_k_m --tracker-url http://127.0.0.1:8000

Terminal 3 — credits for the spender, in a throwaway shell (setting USERPROFILE affects everything Path.home() touches in that shell):

$env:USERPROFILE = "$PWD\.spender"
yaarbal seeder --claim-benchmark --tracker-url http://127.0.0.1:8000
yaarbal spend --identity .spender\.rentmygpu\identity.key --seeder-url http://127.0.0.1:7001 --tracker-url http://127.0.0.1:8000 --prompt "Say hi"

RENTMYGPU_CORS_ORIGINS matters only for the web app, never for the CLI — no need to set it here. See "Known gaps" in §9 for why the HOME/USERPROFILE override is a workaround rather than a real feature.

7. WSL: preload the CUDA runtime (WSL only)

Symptom: ImportError: libcudart.so.12: cannot open shared object file on import llama_cpp — WSL passes through only the NVIDIA driver, not the CUDA runtime libraries the cu124 wheel links against.

Create <venv>/lib/python3.X/site-packages/_cuda_preload.py:

import ctypes
import os

_NVIDIA = os.path.join(os.path.dirname(os.path.abspath(__file__)), "nvidia")
for _sub, _lib in (
    ("cuda_runtime", "libcudart.so.12"),
    ("cublas", "libcublasLt.so.12"),
    ("cublas", "libcublas.so.12"),
):
    _p = os.path.join(_NVIDIA, _sub, "lib", _lib)
    if os.path.exists(_p):
        try:
            ctypes.CDLL(_p, mode=ctypes.RTLD_GLOBAL)
        except OSError:
            pass

That exact order matters (libcudart before libcublasLt before libcublas). Then create <venv>/lib/python3.X/site-packages/zzz_cuda_preload.pth containing exactly:

import _cuda_preload

Not sitecustomize.py — Ubuntu ships its own /usr/lib/python3.X/sitecustomize.py, which shadows a venv-local one. Failures are swallowed (except OSError: pass), so a non-CUDA machine still imports the package cleanly. This works for every entry point — pytest, the seeder, gunicorn — because it fires on interpreter startup, not per-command.

Recipe B (per-shell alternative)

Set LD_LIBRARY_PATH for the current shell instead of touching the venv. nvidia.cuda_runtime and nvidia.cublas are namespace packages (no __file__), so build the path from __path__:

export LD_LIBRARY_PATH="$(~/.rentmygpu-venv/bin/python -c 'import nvidia.cuda_runtime as a, nvidia.cublas as b, os; print(":".join(os.path.join(p,"lib") for p in list(a.__path__)+list(b.__path__)))')"

Test either recipe

~/.rentmygpu-venv/bin/python -c "import llama_cpp"

No output, no error = it worked. (<venv> above is ~/.rentmygpu-venv for a wheel install, <checkout>/.venv for a source checkout, or whatever RMG_VENV_DIR named.)

8. Troubleshooting

9. Validation status + Known gaps

What's been exercised: only the Linux/WSL install path was run end-to-end, on the maintainer's WSL box (install.sh ran fully via RMG_VENV_DIR from a source checkout; the §7 preload recipe is in daily use on that box). The wheel path was exercised on the same box only as far as it can go without a GPU build: the wheel was built, installed by a copy of install.sh with no checkout around it (--no-seeder), every yaarbal subcommand answered --help, yaarbal models list read the packaged catalog, and a tracker created its ledger from the migrations inside the wheel. A wheel install with the seeder extra, and any wheel install on macOS or Windows, has not been run. macOS was NOT run on a real Mac — the Apple-Silicon→metal / Intel→source flavor selection is covered only by unit tests with a stubbed uname. Windows was NOT validated on a real Windows machine — install.ps1 was only statically checked (script content, no execution), and the seeder's Windows-safe parent watchdog has simulated-win32 tests only, no real Windows run.

Known gaps:

10. Agentic proxy (Cline, OpenAI SDK)

yaarbal proxy runs a local OpenAI-compatible /v1 server for agentic coding tools (Cline, or any openai-python-shaped client), with tool-calling routed only to your own node. See docs/QUICKSTART-PROXY.md for the full setup, thinking opt-out, and refusal codes.

Cline-sized prompts routinely exceed the seeder's default 8192-token window — see "Context window and prompt cap (Phase 26)" in §4 above to raise the window on the node that serves this traffic.

Disclosures