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:
- CLI seeder — earn credits by serving GGUF inference from your own GPU.
- CLI spender — spend credits on inference, no browser required.
- Optional local tracker — run your own coordinator (e.g. for the one-laptop loop in §6), instead of the public one.
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.
Recipe A (recommended — what the maintainer runs)
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
no yaarbal wheel was named and this script is not inside a source checkout— the installer was run withoutYAARBAL_WHEEL/--wheel/-Wheel. Point it at the wheel file you were given (§1). There is no built-in download location to fall back to.wheel SHA-256 mismatch— the file is not the one whose hash you were given. Do not install it; get the wheel again.pythonresolves to a Microsoft Store stub — install real Python 3.11+ from python.org; untick "App execution aliases" under Settings → Apps if it still resolves there.ensurepipmissing —install.shfalls back toget-pip.pyautomatically; on Debian/Ubuntu,apt install python3-venvalso fixes it.libcudart.so.12: cannot open shared object file— see §7.Illegal instruction(SIGILL) on the first inference, or the seeder exits 4 withseeder.cpu_backend_unsupported— the prebuilt llama-cpp-python wheel's CPU backend was compiled for a different CPU (upstream builds the CUDA wheels with the build runner's-march=native; the 0.3.35 cu124 wheel needs AVX512-FP16 + AMX, which no AMD or consumer Intel CPU has). Full GPU offload still works; any CPU-side compute (CPU-only or partial offload) is refused instead of crashing.install.shprobes this after install; re-check any time withyaarbal seeder --cpu-backend-probe(exit 0 ok / 1 unsupported / 2 unknown). Fix: re-runinstall.shwith--flavor source(andCMAKE_ARGS='-DGGML_CUDA=on'for NVIDIA), which builds a backend for your own CPU, or install a different release from the same wheel index and re-probe.RENTMYGPU_SEEDER_CPU_PROBE=0skips the startup probe.--modelsays "not downloaded" — follow the printedyaarbal models pull <id>hint.- Port already in use —
--porton the seeder,RENTMYGPU_TRACKER_PORTon the tracker. - "seeder cannot bill itself" / spend fails with a 402 — you need a separate identity with credits; see §5/§6.
invite_requiredfrom--claim-benchmark— the tracker's invite gate is on (§4), or, for a local tracker, setRENTMYGPU_INVITE_GATE=0(§6). On the public tracker run--request-invite --claim-benchmark(§4) instead of hunting for a code; aself_serve_disabledorinvite_gate_offerror from--request-invitemeans that tracker is not issuing self-serve codes.- The seeder runs but never shows up in discovery, and logs
announce.rejectedwith status 403 (invite_required) — the tracker's announce gate is on and this identity has not claimed a grant. Claim the benchmark grant using this identity's invite code (§4); on your own local tracker, setRENTMYGPU_ANNOUNCE_REQUIRE_INVITE=0before starting it (§6). - Intel Mac / Windows ARM64 falls back to a source build — needs Xcode Command Line Tools + cmake (macOS) or MSVC + cmake (Windows).
systemctl --user ...reports "Failed to connect to bus" (WSL) — systemd user units need[boot] systemd=truein/etc/wsl.conf, then a real WSL restart from Windows (wsl --shutdown) — closing the terminal is not enough (§4 "Run it unattended").- The seeder stops the moment you log out or close the SSH session —
loginctl enable-linger "$USER"was not run; a systemd user unit is killed when the user's last session ends without it (§4 "Run it unattended"). - The systemd unit / launchd agent exits immediately with "No such file"
or status 203/EXEC — the
ExecStart/ProgramArgumentspath points at the wrong venv (the shipped default is the wheel-install path~/.rentmygpu-venv/bin/yaarbal; a source checkout lands at<repo>/.venv/bin/yaarbalinstead). Re-runscripts/install.shand fix the path in the copied unit/plist (§4 "Run it unattended").
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:
- There is no CLI faucet command. The
HOME/USERPROFILEoverride in §6 is a workaround, not a supported feature. - The seeder has no
--identityflag — it always usesPath.home()/.rentmygpu/identity.key. yaarbal trackertakes no CLI flags at all; it is entirely env-configured.
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
- Prompts sent to a seeder are visible to that seeder's owner.
- The network tax applies to your own seeder's earnings too — even chatting against your own GPU is not exempt.
- Rate limits apply to all requests.
- Credits and access may reset during the beta.
- Terms of Service: https://rmg-web.yaarbal.app/tos