Genesi Mesh
Pool the GPU memory of several machines so a model that fits on none of them still runs.
Genesi Mesh lets several machines contribute their GPUs to a single inference run. A model that fits on none of them individually still runs accelerated, because the layers are spread across all of them.
Your old PC becomes extra VRAM.
Two ways to share, and they are not interchangeable
Mesh can lend a machine's GPU in two different ways. Picking the wrong one is the most expensive mistake available here, so decide this first.
| Serve (Turbo over HTTP) | Pool (VRAM over RPC) | |
|---|---|---|
| Command | genesi-mesh serve on | genesi-mesh worker on |
| Crosses the network | Text | Layer activations, every token |
| Use when | The model fits on the GPU machine | It fits on neither machine alone |
| Speed | The network barely matters | Bounded by round-trip latency |
If the model fits on the GPU machine, serve it — do not pool it.
Measured on two real machines: a 1.9 GB model, a GPU-less client, an RTX 3050 worker with 6.7 GB free, over a direct LAN link. Pooling behaved exactly as designed and the weights landed on the remote GPU — which then sat at 2–3% utilisation, idle, waiting on a 9 ms round trip. The bottleneck is latency, and no tuning moves it.
Serving over HTTP moves text instead of tensors, and the network stops mattering.
Serving is also the path that needs no configuration on the client: the mesh
advertises which peers are serving Turbo, so a machine with no usable GPU picks
one up automatically instead of quietly building a CPU server next to an idle
remote GPU. genesi-mesh peers tags such a peer [turbo: <model>], naming the model it is actually serving.
How it works
llama.cpp can treat a remote GPU as an extra device through its RPC backend. One machine holds the model and serves the API; the others simply lend their GPUs:
machine A (client) machine B (worker)
llama-server --rpc B:50052 ───────► rpc-server -H 0.0.0.0 -p 50052
holds the model, serves :11435 contributes its GPUWhat llama.cpp does not do is find the machines, prove they are yours, keep the worker alive, or decide whether pooling is even a good idea. That is what Genesi Mesh adds. The daemon is never in the data path, so restarting it cannot interrupt a running generation.
Read this before you start
Pooling is not a speed-up. Every token's activations cross the network, so spreading a model that already fits your GPU makes it slower. The payoff is binary: a model that could not run at all, runs.
Genesi Turbo enforces this on purpose — it refuses to use the mesh for a model that fits locally, and tells you why.
Practical expectations:
| Link | Verdict |
|---|---|
| Gigabit Ethernet | The realistic floor. This is what to aim for. |
| Wi-Fi | Works, but hurts. |
| Internet / VPN | Only for a model that otherwise cannot run at all. See Over the internet. |
MoE models suit pooling best (qwen3:30b-a3b, gpt-oss:20b): only a few
experts fire per token, so far less data crosses the wire than for a dense model
of the same size.
Integrated graphics
An integrated GPU has no memory of its own — what it calls VRAM is a slice of system RAM, backed by bandwidth shared with the CPU (~50–90 GB/s) rather than a discrete card's 200+ GB/s. And llama.cpp splits layers by reported capacity, not by speed, so an integrated peer takes a full share of the work and then makes every token wait for it.
So Mesh does not pool integrated GPUs by default. They appear in
genesi-mesh peers tagged [integrated] and are skipped, with plan naming
them. Override with pool_integrated = on in mesh.conf if you want to measure
it yourself.
This restriction is about a machine contributing its GPU. A laptop whose only GPU is integrated can still use the mesh — in fact that is the case Mesh exists for. Its local budget is reported as 0 dedicated VRAM, which is exactly what lets a remote discrete GPU step in and run the model.
Requirements
Every machine needs a llama.cpp built with the RPC backend:
sudo pacman -Syu genesi-llama-cppAny current build; genesi-mesh doctor confirms the RPC backend is present.
sudo pacman -Syu genesi-llama-cpp-cudaFaster than Vulkan on NVIDIA. genesi-mesh doctor confirms it.
Check everything at once — this tells you exactly what is missing and how to fix it, so run it first whenever something is not working:
genesi-mesh doctorThe machines do not need the same backend. Pick per machine: CUDA on an
NVIDIA worker (faster, and that machine does the compute), Vulkan everywhere
else. The RPC protocol is backend-agnostic — each worker executes on whatever
backend its own rpc-server was built with.
What does have to match is the llama.cpp version. Both Genesi packages are pinned to one upstream commit for exactly this reason: two machines on different builds hang forever at "loading model" with nothing printed on either end. Mesh now refuses such a pairing outright rather than letting it hang. Update every machine in the mesh together.
Verifying with one machine
You do not need a second computer to verify the mesh works. selftest starts a
real rpc-server, connects a real client to it over loopback, and reports what
llama.cpp itself sees. No mocks.
sudo systemctl enable --now genesi-meshd
genesi-mesh selftestA pass means this machine can serve its GPU to a mesh. The only thing a second machine adds is the network hop.
Pooling across two or more machines
This is what Mesh is built for.
Start the daemon on every machine
sudo systemctl enable --now genesi-meshdCreate the mesh on the first machine
sudo genesi-mesh initThis prints a secret. Every machine in the mesh shares it — it is what makes your machines visible to each other and everyone else's invisible.
Lost it? Print it again with sudo genesi-mesh show-secret.
Join from every other machine
sudo genesi-mesh join <secret>Lend VRAM from the machines that should contribute
sudo genesi-mesh worker onRun this on the machines that should lend their GPU. The machine you actually work on does not need it — though enabling it there too does no harm.
This moves the RPC listener from 127.0.0.1 to 0.0.0.0 so peers can reach
it, and the command warns you when it does. See Security.
Confirm they see each other
genesi-mesh peersPeers (1)
old-pc 192.168.1.7 Vulkan 6871 free of 8192 MiB worker [turbo: llama3.2:3b]The figure is free VRAM, not the size of the card: a worker busy running its own model has little to lend, and announcing capacity instead of availability made pooled loads fail at allocation time after transferring everything.
Peers appear within a few seconds. Nothing? Run genesi-mesh doctor on both
machines — the usual causes are a missing secret, a firewall blocking UDP
47100, or the daemon not running.
Just use it
Nothing else to configure. Genesi Turbo checks the mesh on its own:
genesi-ai-turbo serveWhen a model does not fit locally but fits pooled, it says so and spreads it:
[mesh] 11.0 GB model does not fit locally (6.8 GB) but fits across 1 machine(s) (13.6 GB pooled)
[mesh] pooling across: 192.168.1.7:50052Will a given model pool?
Ask before downloading anything. Accepts a .gguf path or a plain size in GB:
genesi-mesh plan qwen3-30b-a3b-Q4_K_M.gguf
genesi-mesh plan 17Model 17.0 GB
local VRAM budget: 6.8 GB
pooled across mesh: 13.6 GB
→ run locally
too big even pooled (17.0 GB needed, 13.6 GB across the mesh)Over the internet
Never forward the RPC port on your router. rpc-server has no
authentication and does not validate what it receives. Exposing it to the open
internet hands your machine to anyone who finds it. Treat it exactly like an
unauthenticated database port.
The correct approach is a private network overlay, which makes the remote machine behave as if it were on your LAN.
Install Tailscale on both machines
sudo pacman -S tailscale
sudo systemctl enable --now tailscaled
sudo tailscale upSign in with the same account on both. Each machine gets a stable 100.x.y.z
address. WireGuard works identically if you prefer to run your own.
Set the mesh up as usual
init on one machine, join on the other, worker on where the GPU is shared.
Find the worker's Tailscale address with tailscale ip -4.
Register each machine with the other
Multicast discovery does not cross a VPN, but unicast does. Run on both machines, each naming the other:
sudo genesi-mesh peer 100.x.y.zDiscovery then works normally and genesi-mesh peers lists the far machine.
GENESI_MESH_ENDPOINTS=host:port genesi-ai-turbo serve still works as an
escape hatch for a peer discovery cannot reach at all. Prefer peer: a forced
endpoint bypasses the planner, so the "would pooling actually help?" check
never runs.
Do not do this for the common case
If what you actually want is "use my powerful desktop from my laptop", do not pool. Pooling sends activations across the link on every token, which over a home connection is far slower than running on the laptop's own CPU.
Instead, run Genesi Turbo on the desktop and point the laptop at its OpenAI-compatible endpoint over Tailscale:
# on the laptop — only the text crosses the network, so it stays fast
curl http://100.x.y.z:11435/v1/modelsGenesi Code and any other OpenAI-compatible client can use that URL directly. Remote pooling is only worth it for a model that genuinely cannot run at all on either machine alone.
Security
rpc-server performs no authentication and no validation of what it
receives. Genesi Mesh is built around that fact:
- Worker mode is off by default. A machine never offers its GPU on its own.
rpc_binddefaults to127.0.0.1.genesi-mesh worker onmoves it to0.0.0.0and warns while doing it; the daemon repeats the warning at every start.- Discovery beacons are HMAC-SHA256 signed with your mesh secret, and carry a timestamp checked against a ±180 s window, so only your machines see each other and a captured beacon cannot resurrect a machine that is gone.
That authenticates discovery, not the RPC port itself. It is not a substitute for running this on a network you control.
Do not enable worker mode on a public, café, campus or hotel network.
Choosing where the AI runs
serve and use are mirrors of each other:
| Decides | |
|---|---|
genesi-mesh serve on|off | What this machine offers to others |
genesi-mesh use auto|local|<peer> | What this machine uses for itself |
genesi-mesh use # what is selected, and what is actually in effect
sudo genesi-mesh use auto # pick the best available Turbo (default)
sudo genesi-mesh use local # always run here, even if a peer is serving
sudo genesi-mesh use old-pc # pin one particular machineAutomatic is the right default, not the right only behaviour. Wanting the chat on the machine in front of you, or pinned to one specific box, is a legitimate preference rather than a misconfiguration — and silently routing someone elsewhere is the kind of helpfulness they cannot see well enough to argue with.
A pinned peer that stops serving falls back to this machine, not to some
other peer: you picked that one on purpose. It switches back on its own when the
peer returns. genesi-mesh use with no argument shows both the selection and
what is currently in effect, because those differ exactly when it matters.
The AI Mode Monitor's Mesh tab has this as the "Onde a IA roda" card: it lists every Turbo available with the model each is serving, and marks the one in effect.
Command reference
| Command | What it does |
|---|---|
genesi-mesh status | This node, its GPU, and who it can see |
genesi-mesh peers | The live peer table |
genesi-mesh init | Start a new mesh here (generates the secret) |
genesi-mesh show-secret | Print the secret, to carry to another machine |
genesi-mesh join <secret> | Join an existing mesh |
genesi-mesh peer <addr> | Register a peer reachable over a VPN |
genesi-mesh serve on|off | Start/stop serving this machine's Turbo over HTTP |
genesi-mesh use auto|local|<peer> | Choose where the AI runs for this machine |
genesi-mesh worker on|off | Start/stop lending this machine's VRAM |
genesi-mesh plan <model|GB> | Would pooling help for this model? |
genesi-mesh selftest | Prove the RPC path works on this machine |
genesi-mesh doctor | Check prerequisites and explain what is missing |
Configuration
/etc/genesi-mesh/mesh.conf. Apply changes with
sudo systemctl reload genesi-meshd — the CLI does this for you.
| Key | Default | Meaning |
|---|---|---|
worker | off | Offer this machine's GPU to the mesh |
rpc_bind | 127.0.0.1 | Address rpc-server listens on |
rpc_port | 50052 | TCP port for rpc-server |
rpc_mem_mb | 0 | VRAM to advertise; 0 = whatever the device has |
discovery | on | Announce this node and collect peers |
name | (hostname) | Display name in genesi-mesh peers |
pool_integrated | off | Use peers whose only GPU is integrated |
peers | (empty) | Addresses to beacon directly, for networks multicast cannot cross |
turbo_source | auto | Where this machine's AI runs: auto, local, or a peer |
Turbo environment overrides
| Variable | Effect |
|---|---|
GENESI_TURBO_NO_MESH=1 | Never use the mesh |
GENESI_MESH_ENDPOINTS=host:port,... | Force these endpoints, skipping discovery |
Troubleshooting
Peers do not appear. Check genesi-mesh doctor on both machines. The usual
causes are a missing or mismatched secret, a firewall blocking UDP 47100, the
daemon not running, or the two machines being on different subnets (in which
case register it with genesi-mesh peer <addr>).
rpc-server is missing. Your llama.cpp was built without the RPC backend.
Install genesi-llama-cpp r0-4+ or genesi-llama-cpp-cuda r0-2+.
Turbo never mentions the mesh. That is usually correct behaviour — the model
fits locally. Confirm with genesi-mesh plan <model>.
It is slower than running locally. Then the model probably fits locally and
something forced the mesh (a GENESI_MESH_ENDPOINTS override). Unset it and let
Turbo decide.