Build local AI you control.
One CLI for the whole on-device lifecycle — run, serve, retrieve, fine-tune, quantize, and evaluate — plus inspect, benchmark, and trace what's happening under the hood. No frontier API required, on hardware you own or a GPU box you rent.
New here? Start with the Quickstart below.
01# enroll with your mentor, then:02mpl login # prove enrollment (sign-and-paste)03mpl setup # install pinned tools + models04mpl run qwen3:8b # chat locally05mpl serve qwen3:8b # OpenAI-compatible local API
From enrolled to serving
Six steps from a verified wallet to an OpenAI-compatible endpoint. It forks once — where your models run — and runs identically on metal you own or a GPU box you rent.
Enroll
Enrollment is your wallet on-chain — no email, no password. Enroll through your mentor; once your wallet is enrolled you receive the install one-liner. Your keys never leave your wallet.
Start your journey →# enroll through your mentor → receive your install one-liner
Install & activate
Install the toolchain, then prove enrollment with a wallet signature. Activation is bound to this machine — log in once per machine you use. mpl setup installs only what's missing and records it, so uninstall is clean.
$mpl login # sign in with your wallet (SIWE)$mpl setup # install pinned tools + models
Choose where it runs
The choice follows your mpl doctor verdict. At tier T2 and above, the curriculum runs on your own rig. Below the floor, mpl setup installs only the cockpit toolkit and the curriculum runs on a box you rent — mpl cloud launch spins it up (see the run-on-cloud guide).
Run on your own rig — a single purchase, full control, no beta.
pick a rig →$mpl doctor --profile # detect your rig$mpl run qwen3:8b # first local model
Spin up a bare-metal GPU billed by the second. Stop it when you're not learning.
the cloud lifecycle →$mpl cloud launch --gpus A100:1$mpl cloud stop my-box
Run & chat
Generate from an open model, or open the local coach — a ReAct agent on open weights that runs mpl verbs for you, never a frontier API.
$mpl run qwen3:8b # one-shot generate$mpl chat # local AI coach (REPL)
Serve
Expose an OpenAI-compatible endpoint on localhost and point any client at it — same API surface, your hardware.
$mpl serve qwen3:8b # OpenAI-compatible local API
Go deeper
Ground it in your data, fine-tune, quantize, and evaluate — or burst a job too big for your rig onto rented GPUs. Every verb takes --dry-run to print its plan first.
mpl ragmpl finetunempl quantizempl evalmpl burstRun on a rented GPU box
Local hardware is the intuitive default — but if you're not ready to buy, mpl cloud (beta) rents a persistent GPU you control. Here's the whole lifecycle, credentials to teardown.
Below the tier-T2 floor? This is the supported path: your machine is the cockpit, the curriculum runs on a box you rent from your own provider account — same sovereign mpl, keys and enrollment still yours. See the hardware guide for tier context.
mpl cloud is beta. It rents and controls GPU compute on your behalf, and like any beta that depends on third-party cloud providers and their APIs, mpl cloud can fail to launch, stop, start, or resume a cluster if something upstream changes or breaks — and work on a stopped cluster may be at risk until you recover it. We recommend mpl cloud for learners who accept this, back up their checkpoints to a network volume or object store, and don't mind a rough edge. Want full control with no beta? Bring any SSH-able GPU box, run mpl setup after enrolling, and connect it with mpl fleet add — any provider, fully sovereign.
VRAM capacity decides whether a model fits. The curriculum's lab models are 8B-class (Qwen3 8B is ~6 GB at Q4) and the capstone adds a fine-tune step — so two numbers matter: the floor you can get away with, and the card we'd actually rent.
The 8B-class lab models at Q4, plus serve, RAG, eval, and a small LoRA. The capstone's fine-tune step is tight here — same ceiling as a 16 GB local card: an entry point, not the comfortable full-curriculum run. Fine when you want the cheapest GPU you can rent.
The whole curriculum end to end — including the model → RAG → fine-tune → eval capstone — with headroom and real speed, no OOM wrestling. On most clouds an A100 is only a little more per hour than a 16 GB card, so this is the one we'd point you to.
Only if you go past the curriculum to 70B-class inference or a full (non-LoRA) fine-tune — not required to finish or to ship the capstone. That's mpl burst / multi-GPU territory.
Coarse guidance — capacity is what fits a model; rent live and check the matrix price before you commit.
Bring your own cloud credentials
mpl never holds your cloud credentials and never bills you — you keep your own provider account. Sign in with that provider's own login on this machine; mpl reads it only at launch and never stores or transmits it. mpl setup installs the toolchain — it does not set up cloud credentials, and you put no card on file with Mindpool.
# mpl never sees these — sign in with each provider's own CLI:$gcloud auth login # GCP$aws configure # AWS$az login # Azure$oci session authenticate # OCI
Launch — it picks the cheapest cloud you're connected to
Leave off --infra and launch reads the live price index across the four stop-capable clouds (AWS, GCP, Azure, OCI — the ones you can park & resume), shows a matrix, and pre-selects the cheapest cloud you're connected to. Press Y to take it, or pick another row. A cloud you haven't signed into shows — not set with a hint to sign in. With --yes or --json it auto-picks the cheapest connected, no prompt. If none of the four are connected, it tells you exactly which provider login to run. It then rents the box, provisions an mpl node, and registers it in your fleet — gated on enrollment, and your provider bills you directly.
$ mpl cloud launch --gpus A100:1 --name my-box --autostop 30 A100:1 — where should it run? (you can park & resume on all of these) CLOUD CONNECTED $/hr on-demand $/hr spot CHEAPEST REGION gcp ✓ 2.95 1.10 * us-central1 ← cheapest you're connected to aws ✓ 3.06 0.98 * us-east-1 azure — not set 2.81 0.92 * eastus cheapest overall — sign in to use it oci — not set 3.20 — us-ashburn-1 run on gcp (us-central1) at ~$2.95/hr? [Y / 1-4 to choose / n]
Go cheaper with spot — eyes open
Add --spot and the matrix shops the spot column instead — often ~3x cheaper. The catch: a spot box is preemptible (your provider can reclaim it any time) and can't be parked — there's no stop/start, so pair it with --autostop 30 --down to cap idle cost. Same four clouds; the chosen row is flagged so you know what you're getting.
$mpl cloud launch --gpus A100:1 --spot --autostop 30 --down# picks the cheapest spot you're connected to — preemptible, no park/resume
Check it's up
status hits your provider for the truth (UP / STOPPED / INIT, the box IP, the autostop timer); list is an instant read from mpl's local ledger. Both require enrollment, like every mpl cloud verb.
$mpl cloud status # live refresh from the provider$mpl cloud list # instant, from mpl's local ledger
Use it like local
It's a fleet node now. First tell it what to serve with mpl cloud serve — it drives the box to load the model and blocks until it's ready (a first serve pulls the weights, so it can take a few minutes). Then point the coach at it with --cloud my-box. mpl chat --cloud my-boxreaches the box's engine through its bearer-gated daemon, so the rented GPU does the work while the engine itself never leaves the box. Or drop into a root shell. Same engines and commands as owned metal, so your tok/s and VRAM numbers transfer to a future purchase. The box already has your enrollment and machine identity seeded at launch — no mpl login needed on it.
$mpl cloud serve qwen3:8b --name my-box # drive the box to serve (blocks until ready; first serve pulls weights)$mpl chat --cloud my-box # the coach, on the rented GPU$mpl cloud ssh my-box # root shell on the box
Park it when idle
Per-second billing means an idle box is wasted money. On the four stop-capable clouds you stop it (the disk survives) or let autostop do it, then start it back when you return.
The escape hatch: you can still launch on a no-park cloud like --infra runpod — launch warns you first, because it has no stop/resume and an idle box bills until you terminate it (and terminating wipes the disk). There the only idle guard is --autostop 30 --down, and mpl cloud stop points you to it instead of failing silently.
$mpl cloud stop my-box # keeps the disk (stop-capable clouds)$mpl cloud autostop my-box -i 30 # auto-stop after 30 idle minutes$mpl cloud start my-box # resume (the IP may change)
Watch the cost, then tear it down
cost shows the estimated $/hr for what you launched — estimate only, mpl adds no markup and never settles billing. down terminates the box and releases the GPU so billing stops for good — then confirms at the provider level that it's really gone (not just deregistered) and clears any leftover resources it created. The disk is lost without a network volume, so back up your checkpoints first.
$mpl cloud cost my-box$mpl cloud down my-box # back up checkpoints first — disk is gone
mpl cloud down terminates the box, then confirms at the provider level that it's actually gone — not just deregistered — and clears any leftover resources it created, so a teardown the provisioning layer reported done but that left a box running no longer bills you silently. Even so, confirming the teardown is your responsibility, not mpl's: after a teardown, open your provider's own console and verify the instance, its disk and any volumes, and any reserved IPs are actually gone. mpl cloud drives a third-party, pre-1.0 provisioning tool; if an upstream or provider API changes, a teardown can still leave resources running — and billing — that mpl believed it had removed. Your provider console is the source of truth, and mpl is not responsible for charges from resources a changed API left behind.
Prefer no beta? The sovereign door skips mpl cloud entirely: bring any SSH-able GPU box, run mpl setup on it after enrolling, and connect it with mpl fleet add — any provider, fully sovereign.
Multi-tenant host
One GPU box you own, several people who each get their own isolated environment and take a turn on the GPU. mpl host lets you share one machine across a group you trust — your own students or teammates.
Turn one GPU box you own into a multi-tenant host: add several people, each gets their own isolated environment and takes a turn on the GPU. It's a way to share one machine across a group you trust — your own students or teammates. Today it runs on that machine only, gives each person their own access token, and runs one job on the GPU at a time— read "what this is / isn't" below before you point it at anyone outside that group.
Two ways in
Rent a GPU host in one command, or set up a box you already own. Same feature either way — the cloud path just runs mpl host init for you when it provisions the box.
mpl cloud launch --host rents the box, installs everything it needs (Docker + the NVIDIA Container Toolkit), builds the tenant image, and runs mpl host init — turnkey. Then add people over SSH and go.
$mpl login # sign in (enrollment)$az login # your own Azure account$mpl cloud launch --host --infra azure --gpus T4:1 --yes$mpl cloud ssh mpl-cloud -- 'mpl host tenant add --peer alice'$mpl cloud ssh mpl-cloud -- 'mpl host tenant add --peer bob'# start the supervisor + submit jobs, then:$mpl host usage # per person$mpl cloud down mpl-cloud
On a Linux + NVIDIA box (Debian/Ubuntu), mpl host init installs what it needs, builds the tenant image, and checks the GPU works. Then start the supervisor, and it runs an environment for each person.
$mpl host init # installs Docker + toolkit, builds image, checks GPU$mpl host tenant add --peer alice$mpl host tenant add --peer bob$mpl host serve # supervisor: runs an environment per person$mpl host job run finetune -- --model=qwen3:1.7b$mpl host usage
How it works
init — get the box ready
mpl host init checks the box and, on Linux + NVIDIA, installs Docker + the NVIDIA Container Toolkit, builds the tenant image, and confirms the GPU works end to end. The NVIDIA driver must already be installed. --explain prints every step and runs nothing.
$mpl host init --explain # see the whole plan, run nothing$sudo mpl host init # on a cloud box
tenant add — one isolated space per person
Each mpl host tenant add --peer <id> gives that person their own access token and their own storage. peer is just an id you choose — any string, like a student handle.
$mpl host tenant add --peer alice$mpl host tenant list$mpl host state # who's registered (JSON)
serve — the supervisor keeps everyone running
mpl host serve runs the supervisor on this machine: it shares the GPU (one job at a time — others wait their turn), keeps an environment running for each person, and accepts their jobs. It needs the tenant image built first — run mpl host init.
$mpl host serve --dry-run # show what it would do, start nothing$mpl host serve
job run — take a turn on the GPU
A person submits with mpl host job run <verb> -- <args>; their token identifies them. The job runs with the GPU attached. Because only one job uses the GPU at a time, a second job waits its turn— on the rented Azure T4 (16 GB), use a small model; a self-owned box needs a card that clears the curriculum's enrollment floor (e.g. a used RTX 4090 24 GB) or mpl host init is blocked by the hardware gate.
$mpl host job run finetune -- --model=qwen3:1.7b# a second person's job waits until the GPU is free
usage — see it per person
mpl host usage shows usage per person — jobs run and tokens used. Everything is metered.
$mpl host usage$mpl host usage --tenant alice$mpl --json host usage
- Linux + NVIDIA, Debian/Ubuntu only. macOS, CPU-only, and AMD boxes are turned away with a clear message, and so is any other Linux flavor. An Apple-silicon path is planned.
- For a group you trust.It runs on one machine and gives each person their own access token — it's for sharing a GPU across people you trust, like your own students or teammates. It is nota hard security wall against someone actively hostile: everyone shares the same machine, and there's no isolation between people beyond their separate storage yet.
- One job at a time. The GPU runs one job at a time — people queuefor it, they don't split it. On the rented Azure T4 (16 GB) use a small model (e.g.
qwen3:1.7b). A self-owned box must clear the curriculum's enrollment floor (e.g. a used RTX 4090 24 GB) — below that, the hardware gate blocksmpl hostlocally. - Docker and the NVIDIA toolkit are yours to manage.mpl installs them if they're missing but never removes them —
mpl uninstallleaves them alone, since a shared Docker setup isn't ours to tear down. - Requires enrollment. The whole
mpl hostfeature needsmpl login. Each person signs in inside their own environment too.mpl cloud launch --hostneeds enrollment the same way.
Report a bug, track it to a fix
Something broke? mpl bug files a redacted, opt-in report and hands you a claim-check id — then follows it all the way to the release that fixes it, without an account, an inbox, or your keys ever leaving the machine.
Bug reporting is off by default and never turns itself on. When you do opt in, every field is scrubbed through an allowlist before anything leaves your machine — wallet addresses, home paths, keys, and seed phrases are stripped — and your keys never leave the wallet. You can see the exact payload before sending, and check a report's status without sending anything back.
Filing a report only works on mpl 0.17.2 and later — earlier builds ship without a reporting endpoint, so mpl bug records nothing and sends nothing. Run mpl update (or reinstall) to get on 0.17.2+ first. mpl bug status and mpl bug list stay available on any version.
Turn it on — once, on your terms
The first time you run mpl bug it asks for consent and remembers your answer; until then, nothing is sent. Want to see exactly what a report contains before you decide? Add --explain — it prints the full redacted payload and sends nothing. You can flip the setting any time with mpl config. No enrollment needed — mpl bug is open.
$mpl bug "serve didn't pick up my model" --explain # preview only — sends nothing$mpl config set telemetry.enabled true # opt in up front (optional)$mpl config set telemetry.enabled false # opt back out any time
File a report — and keep the receipt
Describe what went wrong and, if you can, name the verb with --verb. mpl attaches a redacted diagnostic — mpl version, OS/arch, the named verb, and a doctor snapshot — and prints a claim-check id like MPL-BUG-7F3A. That id is random, tied to nothing about you, and saved locally to ~/.mpl/bug-reports.json. It's your receipt — keep it and you can follow the report to a fix.
$mpl bug "serve didn't pick up my model" --verb "cloud serve"# ⚠ never paste seed phrases, private keys, or passwords into a report# → thanks — report MPL-BUG-7F3A sent. check status anytime with `mpl bug status`.
Track it — without giving anything away
mpl bug list is an instant read of your local reports; mpl bug status also checks whether any have been fixed. It does that by downloading a public list of resolved ids and matching locally — your id is never sent anywhere to look it up. The receipt is an opaque token: it means something only on your machine.
$mpl bug status# MPL-BUG-7F3A serve didn't pick up my model ✅ fixed in v0.2.0# MPL-BUG-9C2D doctor shows wrong VRAM ⏳ open
Get the fix — mpl tells you
When a release closes one of your reports, mpl update says so as it upgrades — no inbox, no account, no waiting on a dashboard. Update, and the thing you reported is fixed.
$mpl update# ✅ your bug report MPL-BUG-7F3A is fixed in v0.2.0.
Once you've opted in, an unexpected crash is reported automatically with the same redaction — so the hard-to- reproduce failures get seen without you having to catch them. Haven't opted in? A crash just points you to mpl bug and sends nothing.
The mpl command reference
Every verb, in full. macOS & Linux (Windows via WSL2). Gated verbs read your DefiMentor enrollment on-chain; mpl usage stays open since it's your own local data. Every verb supports --dry-run to print its plan before acting.
mpl login
openActivate mpl by proving your enrollment (sign-and-paste).
Proves you control an enrolled wallet via Sign-In-With-Ethereum. By default it opens mindpool.io/build-ai/cli-login to sign with the Trust Wallet extension or Trust Wallet mobile; --manual instead prints the one-time SIWE message to sign yourself (cast / hardware wallet) and paste back. mpl verifies your enrollment on-chain (Polygon) and activates the gated verbs locally — it never holds your keys and never writes on-chain, and re-checks enrollment periodically so access follows your on-chain status. Activation is bound to this machine: mpl records a hardware fingerprint at login, so a copied activation won't run on another machine — log in once per machine you use. Requires curl on PATH.
- --address <addr>
- The wallet address to activate; prompted if omitted.
- --rpc URL
- Override the Polygon RPC endpoint.
- --manual
- Skip the browser; print the SIWE message to sign yourself, then paste the signature.
$mpl login$mpl login --manual# → sign the printed message, paste the signature
mpl status
openShow identity + enrollment status.
Prints the cached signer identity, the machine this activation is bound to, and whether the on-chain enrollment entitlement is currently valid.
$mpl status
mpl logout
openClear the cached entitlement.
Removes the cached CAIP-10 entitlement from ~/.mpl/. Re-run mpl login to re-activate on this machine.
$mpl logout
mpl doctor
openVerify the local environment is ready.
Checks that the required tools are present and wired correctly, including a coach (llama-server): line that reports whether the pinned llama.cpp build is installed and the coach model is pulled (e.g. ready · default model gemma4:e4b). With --profile, appends this rig's capability profile and a per-model table of fit, estimated tok/s, and (when available) measured throughput. Chips not in the bandwidth table report — rather than a guess.
- --profile
- Append the rig capability profile + per-model fit / est-tok/s table.
$mpl doctor$mpl doctor --profile
mpl chat
gatedtier floor applies locallyChat with the AI coach — a local llama-server or a cloud node, one conversation.
Opens the mindpool coach: a ReAct-loop assistant that answers across all curriculum modules with cited lesson passages (search_curriculum retrieves from the real course content; lab solutions are excluded from its corpus), can run mpl verbs on your behalf (with confirmation), and uses web search when configured. It remembers you across sessions: a confirm-gated save_memory tool writes durable facts to ~/.mpl/coach/memory-store.jsonl on your disk — every save needs your y, /memory lists the store, /memory clear wipes it, and mpl memory inspect audits it. Mid-conversation you can switch model or hardware without losing the thread: /model <tag> swaps models, /cloud <name> moves the session to a registered fleet node's endpoint, /local brings it home — history carries across every swap, and responses stream token-by-token on both transports. Context is budgeted automatically (coach.context_tokens config, else the model's probed window, else 8192) with a visible '(trimmed N oldest turn(s)…)' notice when older turns are evicted. Slash commands: /exit /reset /save /tools /model [tag] /cloud <name> /local /memory [clear] /help. The coach talks to a llama-server it starts and owns for the session (default port 7719) — or a cloud node with --cloud — no frontier API, and memory + tools stay client-side even when chatting through a cloud node. mpl chat is always the streaming text REPL — there's no separate full-screen chat shell to open. Default model: gemma4:12b (Apache 2.0). Override with --model or set a persistent default with mpl config set coach.model <tag>.
- --model <tag>
- Coach model tag to use (overrides coach.model config and the hardware-picked default: gemma4:e4b on ≤24GB rigs, gemma4:12b on larger — the -mlx build on Apple Silicon).
- --cloud <node>
- Chat through a registered fleet node's OpenAI endpoint instead of the coach-owned local llama-server (precedence: --cloud > coach.url > coach-owned local). The model defaults to what the node serves; --model still wins. Register nodes with mpl cloud launch or mpl fleet add.
- --plain
- Accepted for back-compat; a no-op — mpl chat is always the plain streaming REPL.
$mpl chat$mpl chat --model gemma4:e4b$mpl chat --cloud mpl-cloud # coach on your rented GPU, memory stays local$mpl chat --model gemma4:12b-mlx --plain$mpl config set coach.model gemma4:e4b # persist the override$mpl config set coach.context_tokens 16384 # cap the conversation window
mpl top
openLive local operational dashboard — CPU/GPU/mem/disk/net, inference servers, throughput, footprint, health. Read-only, btop-style.
A read-only, btop-style dashboard over this rig: CPU/GPU utilization, memory, disk, and network; running inference servers (mpl serve / mpl run); recent throughput (tok/s, from ~/.mpl/usage.jsonl); the on-disk footprint (~/.mpl models + ledger); and a doctor-style health snapshot. A background thread samples roughly once a second; the terminal only renders what it reads — no writes, no mutating calls, no enrollment check, which is why mpl top is one of the few open verbs (alongside doctor and status). The global --json flag prints one snapshot as JSON and exits, for scripting. For the coach, use mpl chat (or mpl chat --plain).
$mpl top$mpl --json top # one snapshot, for scripting
mpl usage
your dataLocal token-usage summary + cloud-cost comparison.
Ungated — it is your own local data. Summarizes the append-only ~/.mpl/usage.jsonl ledger that every gated verb writes to. Token counts are reported from engine stats when available (true generation tok/s) or estimated from output length (always labelled as estimated). Compares your local usage against equivalent frontier-API cost.
$mpl usage
mpl config
openGet/set local coach configuration (e.g. the web-search key).
Reads and writes local coach configuration in ~/.mpl/ — open, since it is your own local data. Current keys include coach.model (the default coach model tag), coach.port (the port the coach's own llama-server binds on, default 7719), coach.url (point the coach at an external OpenAI-compatible server instead of one mpl spawns and owns), coach.context_tokens (the coach's context window size), search.brave-key (enables coach web search), rpc.polygon (overrides the Polygon RPC endpoint), burst.backend (hf | skypilot — the default backend for mpl burst submit), telemetry.enabled (opt in/out of bug reporting — ties to mpl bug), and teacher.anthropic-key / teacher.openai-key / teacher.gemini-key (frontier teacher keys).
- set <key> <value>
- Set a config key (e.g. mpl config set coach.model gemma4:e4b).
- get <key>
- Print the current value of a key.
- unset <key>
- Remove a key.
$mpl config set coach.model gemma4:e4b$mpl config get coach.model$mpl config set search.brave-key <KEY>$mpl config set burst.backend skypilot
mpl uninstall
openRemove mpl-installed components. Keeps models unless --purge.
Reverses what setup recorded in the install ledger, never touching tools that pre-existed. By default it keeps downloaded models and prints the one-liner to remove mpl itself; --remove-self also removes the mpl binary + ~/.mpl config (channel-aware via ~/.mpl/install.json).
- --purge
- Also remove downloaded models.
- --remove-self
- Also remove the mpl binary + config (self-removal).
- --keep-mpl
- Keep mpl itself; suppress the self-removal step entirely.
- --yes
- Perform self-removal without a confirmation step.
- --dry-run
- Print the plan without removing anything.
$mpl uninstall$mpl uninstall --purge --remove-self --yes
mpl update
openUpgrade mpl to the latest release (method-aware).
Ungated — updating the tool never requires enrollment. Detects how mpl was installed (via ~/.mpl/install.json): Homebrew installs run brew upgrade --cask mpl; curl installs download the latest signed release, verify sha256 (plus a minisign signature on Linux) before anything is replaced, then atomically swap the binary. Source/cargo builds get guidance. Prompts before replacing the binary unless --yes is given. If you've filed bug reports with mpl bug, update also tells you which of them are fixed in the new version. On an existing install, also re-run `mpl setup` after updating — `mpl update` alone swaps the binary; it doesn't refresh your Python venvs or `~/.mpl/scripts/`.
- --check
- Only report whether a newer version exists; never mutates.
- --yes
- Skip the confirmation prompt (for scripts).
- --dry-run
- Print what would be done without performing the upgrade.
$mpl update --check$mpl update$mpl update --yes
mpl bug
openReport a bug (opt-in, redacted) and track it to a fix.
Filing a report only works on mpl 0.17.2 and later — earlier builds ship without a reporting endpoint, so mpl bug records nothing and sends nothing. Run mpl update (or reinstall) to get on 0.17.2+ first; mpl bug status and mpl bug list stay available on any version.
Open — no enrollment needed, and off by default: the first run asks consent, and nothing leaves your machine until you agree. mpl bug "<desc>" files a report with a redacted diagnostic (mpl version, OS/arch, the named verb, a doctor snapshot) and prints a claim-check id — MPL-BUG-XXXX — saved locally to ~/.mpl/bug-reports.json. Every field is scrubbed through an allowlist before anything is sent: wallet/CAIP-10 addresses, home paths, keys, and BIP-39 seed phrases are stripped, and your keys never leave the wallet. --explain prints the exact redacted payload without sending, so you can see precisely what would go. mpl bug status and mpl bug list show your reports and whether any have been fixed — matched locally against a published manifest, so the id is never sent back to look it up. When a fix ships, mpl update tells you which of your reports it closes. Fixes are published to a public changelog (mindpool.io/build-ai/changelog); mpl bug status matches your ids against it locally.
- --verb <verb>
- The mpl verb the problem is about (e.g. "cloud serve") — groups related reports.
- --explain
- Print the exact redacted payload that would be sent, then exit without sending.
- --yes
- Skip the consent prompt (non-interactive opt-in).
- status | list
- status checks the manifest for fixes; list is an instant read of your local reports.
$mpl bug "serve didn't pick up my model" --verb "cloud serve"$mpl bug "serve didn't pick up my model" --explain # preview the redacted payload$mpl bug status # any of my reports fixed yet?$mpl bug list
mpl run
gatedtier floor applies locallyRun a model locally, interactively.
Starts an interactive local chat session with a model from the curriculum manifest, auto-selecting the best available backend for your hardware unless you force one. No frontier API, no data leaving the machine.
- --backend llama.cpp|mlx
- Force a backend (otherwise auto-selected).
- --ctx-size N
- Context length in tokens.
- --engine-arg=<tok>
- Raw engine token appended verbatim (repeatable). Use the equals form for hyphen-leading flags.
- --dry-run
- Print the plan without running.
$mpl run qwen3:8b$mpl run qwen3:8b --backend llama.cpp --ctx-size 8192
mpl serve
gatedtier floor applies locallyServe a model over an OpenAI-compatible local API.
Exposes a local OpenAI-compatible Chat Completions endpoint backed by your model — point any OpenAI client at it by changing the base URL. Supports streaming (server-sent events) exactly like the hosted API. Production engines (vLLM full-depth, llama.cpp full-depth on Apple Silicon, SGLang/TRT-LLM/NIM plan-only) are selected with --engine.
- --engine <name>
- Canonical engine selector: vllm | sglang | trtllm | nim | llama.cpp | mlx. (--backend is the back-compat alias.) vLLM + llama.cpp are wired full-depth; SGLang / TRT-LLM / NIM render real plans under --dry-run and need Linux+NVIDIA to serve live.
- --draft-model ID
- Speculative-decoding draft model (resolved like the main model).
- --kv-quant int8|fp8
- KV-cache quantization.
- --prefix-cache
- Enable prefix caching (vLLM APC / SGLang Radix; automatic on llama.cpp).
- --host H
- Bind host (engine default if omitted).
- --port P
- Bind port (engine default if omitted).
- --ctx-size N
- Context length in tokens.
- --engine-arg=<tok>
- Raw engine token appended verbatim (repeatable). Use the equals form for hyphen-leading flags.
- --nim-profile <NIM_PROFILE>
- NIM profile name to use when --engine nim is selected.
- --list-profiles
- List available NIM profiles for the given model and exit.
- --dry-run
- Print the plan without running. Pair with the global --json to get the resolved engine plan + rig requirement.
$mpl serve qwen3:8b --port 8080# then: curl http://localhost:8080/v1/chat/completions …
mpl burst
gatedcockpit — runs below the tier floorRun heavy AI jobs on hardware you own (SkyPilot) or rent managed cloud (Hugging Face Jobs) — one rail, your choice.
The burst compute rail for jobs too large for your local rig — a 70B full fine-tune, a multi-GPU eval sweep, anything that hits the memory ceiling. Two backends behind a single command: SkyPilot drives any cloud or your own cluster with no lock-in; Hugging Face Jobs is the turnkey managed option. submit queues a job from a template, previews the resolved backend and cost, and asks before it rents; list/status track it; logs stream it; cancel stops it; cost shows the estimate for tracked jobs. Cost is an estimate only — never billing or settlement. Add the global --explain to print the resolved plan without running anything. Every burst subcommand — submit, list, status, logs, cancel, cost — is enrollment-gated: nothing runs unless your wallet is enrolled.
- submit --template <name> [--file <FILE>] [--model <MODEL>] [--dataset <DATASET>] [--output <OUTPUT>] [--backend auto|skypilot|hf] [--accelerator <gpu>] [--infra <INFRA>] [--timeout <DUR>] [--secret <K=V>] [--spot] [--yes]
- Submit a burst job from a template (finetune, eval, …) or a native SkyPilot YAML via --file. --model and --dataset override template defaults; --output sets the artifact destination; --infra selects the cluster; --timeout limits wall-clock run time; --secret (repeatable) injects K=V env vars. Auto picks the backend (own hardware first); a rented job shows its cost and asks to confirm unless --yes. Prefix with --explain for a dry run. Enrollment required.
- list
- List all tracked burst jobs and their current state.
- status <job-id> [--watch]
- Show status for a job; --watch polls until it finishes.
- logs <job-id>
- Stream the job's logs to your terminal.
- cancel <job-id>
- Cancel a queued or running job.
- cost [<job-id>]
- Show the cost estimate for tracked jobs ($0 on hardware you own, per-hour on rented cloud). Estimate only — not billing.
$mpl --explain burst submit --template finetune --backend skypilot --accelerator A100:1$mpl burst submit --template finetune --backend hf --accelerator A100:1$mpl burst list$mpl burst status <job-id> --watch$mpl burst logs <job-id>$mpl burst cost
mpl cloud is beta. It rents and controls GPU compute on your behalf, and like any beta that depends on third-party cloud providers and their APIs, mpl cloud can fail to launch, stop, start, or resume a cluster if something upstream changes or breaks — and work on a stopped cluster may be at risk until you recover it. We recommend mpl cloud for learners who accept this, back up their checkpoints to a network volume or object store, and don't mind a rough edge. Want full control with no beta? Bring any SSH-able GPU box, run mpl setup after enrolling, and connect it with mpl fleet add — any provider, fully sovereign.
mpl cloud
gatedcockpit — runs below the tier floorRent a persistent GPU box you control — launch, stop/start, SSH, and tear down. (beta)
The cloud runtime (beta): rents a persistent GPU box, provisions an mpl node on it, and registers it in your fleet — so a rented box behaves like one you own. Leave off --infra and launch reads the live price index across the four stop-capable clouds (AWS, GCP, Azure, OCI), shows a matrix, and picks the cheapest one you're connected to (--yes/--json auto-picks; an explicit --infra skips the matrix, and a no-park cloud like runpod launches only after a warning). launch rents and provisions the box; stop / start / autostop / down control its lifecycle; status, list, ssh, and cost read or reach the box — every mpl cloud verb requires enrollment. Cost is an estimate only — never billing or settlement. Sovereign alternative with no beta: bring any SSH-able GPU box, run mpl setup after enrolling, and connect it with mpl fleet add — any provider, fully sovereign. A box launched this way inherits your machine identity and enrollment automatically — no separate `mpl login` on the box itself.
- launch --gpus <gpu> [--infra <cloud>] [--name <name>] [--cpus N] [--memory N] [--disk-size N] [--spot] [--autostop <min>] [--host] [--yes]
- Rent a persistent GPU box, provision an mpl node on it, and register it in the fleet. With no --infra, shows a price/capability matrix across the stop-capable clouds and pre-selects the cheapest you're connected to (--yes/--json auto-picks). --spot shops the cheaper, preemptible spot column (can't be parked). Asks before it rents unless --yes. Enrollment required.
- --host
- Set the box up as a multi-tenant host: it installs Docker + the NVIDIA Container Toolkit and builds the tenant image (runs mpl host init for you). Requires a Linux + NVIDIA instance. See the mpl host verbs.
- status [name]
- Show cluster status with live refresh. Enrollment required.
- list
- List cloud clusters recorded in mpl's local ledger (no live refresh). Enrollment required.
- stop <name>
- Stop a cluster (keeps disk on the stop-capable clouds: AWS/GCP/Azure/OCI). Errors with guidance on no-park clouds like RunPod and on spot boxes. Enrollment required.
- start <name>
- Restart a stopped cluster. Enrollment required.
- autostop <name> [-i <min>] [--down] [--cancel]
- Set or cancel an idle autostop. --idle <min> schedules a stop after N idle minutes; --down terminates instead of stopping; --cancel clears it. Enrollment required.
- ssh <name>
- SSH onto the cluster (convenience). Enrollment required.
- cost [name]
- Show estimated $/hr for a cluster. Estimate only — not billing. Enrollment required.
- down <name>
- Terminate a cluster and release the compute (data is lost without a Network Volume). Enrollment required.
$mpl cloud launch --gpus A100:1 --name my-box$mpl cloud launch --host --infra azure --gpus T4:1 --yes # a turnkey multi-tenant GPU host$mpl cloud status$mpl cloud list$mpl cloud stop my-box$mpl cloud ssh my-box$mpl cloud cost my-box$mpl cloud down my-box# sovereign manual door — no beta:$mpl fleet add lab-rig --url http://10.0.0.5:7717 --token <tok>
mpl host init
gatedtier floor applies locallyGet this box ready to be a multi-tenant GPU host — installs Docker + the NVIDIA Container Toolkit, builds the tenant image, and checks the GPU works.
The host runs on Linux + NVIDIA (Debian/Ubuntu) in v1. mpl host init turns away macOS, CPU-only, and AMD boxes with a clear message, and so is any other Linux flavor — never a silent skip. An Apple-silicon host path is planned.
Checks the box, then makes it able to run tenant GPU jobs. On a Linux + NVIDIA (Debian/Ubuntu) box it installs Docker + the NVIDIA Container Toolkit if they're missing, sets up the GPU runtime, and (on a shared box, log out/in once so the docker group takes effect — or run sudo mpl host init). The NVIDIA driver must already be installed — mpl doesn't install it (cloud GPU images ship it). It then builds the tenant image and confirms the GPU works by running a real container against it. Docker and the toolkit are system tools you manage: mpl installs them if missing but never removes them (mpl uninstall leaves them alone, since a shared Docker setup isn't ours to tear down). --explain prints every step and runs nothing.
$mpl host init$mpl host init --explain # print every step, run nothing$sudo mpl host init # on a cloud box — root owns the docker socket
mpl host profile
gatedtier floor applies locallyPrint the host's capability profile (chip, GPU memory, how many jobs at once) as JSON.
Prints the host profile written by mpl host init: the chip, GPU memory, GPU count, and how many jobs it runs at once (1 in v1 — one job uses the whole GPU at a time). Always JSON. It's written once the box is set up and GPU-verified, so its presence means the box is ready.
$mpl host profile
mpl host state
gatedtier floor applies locallyPrint the registered tenants and their status as JSON.
Prints the registered tenants and their status as JSON. Which job currently holds the GPU (and who's waiting) is reported by the running supervisor while mpl host serve is up.
$mpl host state
mpl host serve
gatedtier floor applies locallyRun the supervisor — shares the GPU, keeps an environment running per person, and accepts their jobs.
Runs on this machine only, and gives each person their own access token. It's for sharing a GPU across people you trust — not a hard security wall against someone hostile (everyone shares the machine). One job uses the GPU at a time; people queue, they don't split it.
Runs the supervisor. It shares the GPU (one job at a time — others wait their turn), keeps an environment running for each person, and accepts their jobs over a local connection. It needs the tenant image built first — run mpl host init. --dry-run (or --explain) prints what it would do and exits without starting.
- --bind <addr>
- Address to listen on (default 127.0.0.1 — this machine only).
- --port <port>
- Port to listen on (default 7718).
- --dry-run
- Print what it would do and exit without starting.
$mpl host serve$mpl host serve --dry-run # print the plan, start nothing
mpl host tenant
gatedtier floor applies locallyAdd / list / remove the people sharing the box — add gives each their own access token + storage.
Manage the people sharing the box. add gives a person their own access token and their own isolated storage; while mpl host serve is running, it starts an environment for them. list shows everyone; remove deletes a person and their storage. peer is just an id you choose — any string, like a student handle.
- add --peer <id>
- Add a person — creates their access token and storage; the supervisor starts their environment.
- list
- List the people sharing the box (JSON).
- remove <peer>
- Remove a person and delete their environment and storage.
$mpl host tenant add --peer alice$mpl host tenant add --peer bob$mpl host tenant list$mpl host tenant remove alice
mpl host job
gatedtier floor applies locallySubmit a GPU job as a tenant — it runs in its own container with the GPU attached.
Run from a person's own environment. Submits a GPU job to the supervisor; the person's access token identifies them. The job runs in its own container with the GPU attached. Because only one job uses the GPU at a time, a second job waits its turn — on a 16 GB card, use a small model (e.g. qwen3:1.7b). Args after -- are passed straight to the verb.
- run <verb> -- <args>
- Submit a GPU job; args after -- are passed straight to the verb.
$mpl host job run finetune -- --model=qwen3:1.7b$mpl host job run bench -- --analytic-only
mpl host usage
gatedtier floor applies locallySee usage per person across the box — jobs run and tokens used.
Shows usage per person — jobs run and tokens used (reported when the engine provides timing). --tenant filters to one person; the global --json emits a machine-readable summary. Everything is metered.
- --tenant <peer>
- Show usage for a single person.
$mpl host usage$mpl host usage --tenant alice$mpl --json host usage
mpl embed
gatedtier floor applies locallyCompute an embedding vector for text.
Embeds a snippet (positional, --file, or --stdin) and prints a JSON vector with a dimension summary. Uses the retrieval venv provisioned by mpl setup (sentence-transformers, 384-dim by default).
- --file PATH
- Read input from a file.
- --stdin
- Read input from stdin.
- --dry-run
- Print the plan without running.
$mpl embed "what is retrieval-augmented generation?"$echo 'hello world' | mpl embed --stdin
mpl index
gatedtier floor applies locallyChunk, embed, and store documents into the project-local vector store.
Walks one or more files or directories, chunks and embeds them, and writes a LanceDB store under ./.mpl (cwd-relative — add .mpl/ to your project's .gitignore). The index records its model and dimension so search can guard against a model mismatch.
- --chunk-size N
- Characters per chunk (default 512).
- --chunk-overlap N
- Overlap between consecutive chunks in characters (default 64).
- --dry-run
- Print the plan without running.
$mpl index ./docs --chunk-size 512 --chunk-overlap 64
mpl search
gatedtier floor applies locallySearch the project-local vector store.
Runs an exact nearest-neighbour search over ./.mpl and prints a JSON array of ranked results (source, text, score).
- -k / --top-k N
- Number of results to return.
- --dry-run
- Print the plan without running.
$mpl search "how does the enrollment gate work" -k 5
mpl rag
gatedtier floor applies locallyRetrieve, then answer with a local chat model + inline citations.
Composes retrieval + generation end-to-end: retrieves top-k chunks from ./.mpl, assembles a cited prompt (sources listed first, [n] citations inline), and streams the answer from a local chat model (default qwen3:8b). Context is budget-capped (12 000 chars); lowest-ranked chunks are trimmed when exceeded. Requires an index first.
- -k / --top-k N
- Number of chunks to retrieve (default 5).
- --model ID
- Chat model id (defaults to the manifest's qwen3:8b).
- --backend …
- Force llama.cpp | mlx.
- --ctx-size <N>
- Context length in tokens for the generation step.
- --json
- Capture retrieved chunks + answer as JSON instead of streaming.
- --dry-run
- Inspect the retrieval + generation plan without running.
$mpl rag "how does the enrollment gate work?"$mpl rag "explain RAG" -k 8 --model qwen3:8b
mpl finetune
gatedtier floor applies locallyLoRA-fine-tune a base model and export a deployable GGUF.
Trains a LoRA adapter, fuses it, and converts to an f16 GGUF (Apple Silicon via mlx-lm; Linux via CUDA/Unsloth or ROCm/PEFT — the accelerator is auto-detected by mpl setup). Dataset is JSONL of chat {"messages":[…]} or completion {"prompt","completion"} records; omit --data to use the bundled smoke set.
- --data PATH
- Training dataset JSONL (bundled smoke set if omitted).
- --base REPO
- Base model HF repo id (overrides the manifest default).
- --adapter-only
- Stop at the LoRA adapter (skip fuse/convert/quantize).
- --quantize TYPE
- After the GGUF, quantize it via mpl quantize (e.g. Q4_K_M).
- --epochs / --lr / --lora-rank / --lora-alpha / --batch-size / --max-seq-len
- Promoted training knobs.
- --output <dir>
- Output directory for the fine-tuned adapter / GGUF (defaults to ./output/).
- --force
- Overwrite an existing output directory.
- --dry-run
- Print every step's command, run nothing.
$mpl finetune --data train.jsonl --quantize Q4_K_M$mpl finetune --adapter-only
mpl quantize
gatedtier floor applies locallyConvert a GGUF to a smaller precision (llama.cpp).
The first single-backend verb (llama.cpp only). Quantizes to one of Q8_0…IQ2_M (default Q4_K_M). Low-bit quants (IQ*, Q2_K, Q3_K_S/M) auto-generate an importance matrix from the bundled calibration corpus; --calibration overrides it, --imatrix supplies a precomputed one, --no-imatrix skips it (quality warning). Every underlying llama-quantize / llama-imatrix command is printed before it runs.
- --quant TYPE
- Target quant type (default Q4_K_M). Q8_0…IQ2_M.
- --output PATH
- Output GGUF path (default <input>.<QUANT>.gguf).
- --calibration PATH
- Custom imatrix calibration corpus (overrides bundled).
- --imatrix PATH
- Use a precomputed importance matrix (skips generation).
- --no-imatrix
- Skip imatrix even for a low-bit quant.
- --force
- Overwrite an existing output file.
- --dry-run
- Print the plan(s) without running.
$mpl quantize model.gguf --quant Q4_K_M$mpl quantize model.gguf --quant IQ3_M # auto imatrix
mpl eval
gatedtier floor applies locallyEvaluate a model against a dataset of samples.
Scores a local chat model over a JSONL dataset — the scorer is inferred per sample: {"prompt","expected"} is exact-match (normalized, first-line anchored); {"prompt","choices","answer"} is MCQ (0-based index or letter). Scoring is pure Rust — no Python venv. Prints ✓/✗ per sample and an aggregate accuracy; --json emits a structured report. Omit --dataset to run the bundled smoke set.
- --dataset PATH
- Dataset JSONL (bundled smoke set if omitted).
- --model ID
- Chat model id (default qwen3:8b).
- --backend …
- Force llama.cpp | mlx.
- --limit N
- Evaluate at most N samples.
- --ctx-size <N>
- Context length in tokens for the generation step.
- --dry-run
- Print the plan + sample count without running.
$mpl eval$mpl eval --dataset evals.jsonl --limit 10 --model qwen3:8b
mpl inspect
openDump a model's real architecture from its weights.
Reads GGUF metadata off the file — no engine, no extra download — and prints the architecture: layer count, hidden dim, attention type with GQA/MLA head counts, RoPE config, normalization, vocab size, MoE expert count, and context window. Ungated: it only reads a local file's header. The lab bench for the Build-a-Model track.
$mpl inspect qwen3:8b$mpl inspect ./model.gguf$mpl --json inspect qwen3:8b
mpl bench
gatedtier floor applies locallyBenchmark inference — TTFT / TPOT / tok-s + analytic roofline.
Runs a short measured generation and reports time-to-first-token, time-per-output-token, tokens/sec, KV-cache footprint, and where the workload lands on the roofline. With the global --json flag it emits the machine-readable benchmark report — the specialization capstone artifact. --measure-batch goes further: it drives real concurrent load and measures aggregate serving throughput at each --batch size. Degrades to the analytic block on rigs without a usable engine.
- --backend llama.cpp|mlx
- Force a backend (otherwise auto-select).
- --ctx-size N
- Context length for the run + KV-cache calc (default 2048).
- --gen-tokens N
- Decode length for the measured run (default 128).
- --batch 1,8,32
- Batch sizes for the analytic KV/roofline projection (and for --measure-batch's live sweep).
- --measure-batch [--concurrency N]
- Drive real concurrent load and measure aggregate throughput per batch size — the §7 specialization capstone.
- --engine / --draft-model / --kv-quant / --prefix-cache / --port
- Tune the ephemeral server for the --measure-batch run (same knobs as mpl serve).
- --analytic-only
- Skip the live run; report the analytic block only (no model/engine needed).
- --dry-run
- Print the plan without running the generation.
$mpl bench qwen3:8b$mpl bench qwen3:8b --analytic-only$mpl --json bench qwen3:8b > bench.json
mpl trace
gatedtier floor applies locallyTrace one forward pass — per-layer activations + KV growth.
Runs a single forward pass (over HF safetensors) and summarizes, per layer, residual-stream norms, attention entropy / sink-mass / mean distance, and cumulative KV-cache growth. One positional = the prompt (model defaults to SmolLM2-135M); two positionals = model then prompt. --analytic-only does tokenization + KV accounting only, with no forward pass (still enrollment-gated).
- --max-tokens N
- Cap prompt tokens captured (bounds attention memory; default 64).
- --layers all|0,2,5
- Restrict the per-layer detail rows (default all).
- --analytic-only
- Tokenizer + KV accumulation only; no forward pass (still requires login).
- --dry-run
- Print the resolved plan without running anything.
$mpl trace "The capital of France is"$mpl trace smollm2:135m "Hello" --layers 0,2,5$mpl trace "hi" --analytic-only
mpl lab
gatedtier floor applies locallyMaterialize a Track B / D lab scaffold into the current directory.
Writes a lab scaffold (starter code + reference material) for a specialization-track module into the cwd, then points you at the Python env it uses. Serves two tracks: Build-a-Model (Track B, e.g. B1-kv-cache) and Agent Harness Engineering (Track D, e.g. D9-capstone). --dry-run prints the materialization plan without writing.
- --dry-run
- Print the plan without writing.
- --force
- Overwrite a non-empty target directory.
$mpl lab D9-capstone$mpl lab B1-kv-cache$mpl lab B1 --dry-run
mpl agent
gatedtier floor applies locallyBuild, run, trace, and grade a Track-D agent harness.
The Agent Harness Engineering toolchain (Track D). init materializes the generic agent-harness scaffold into ./agent-harness/; run executes the harness on a task and captures an episode package (artifacts/episode.json); trace reads, validates, and pretty-prints an episode.json; eval scores an eval-report.jsonl the harness emitted and flags regressions against a --baseline; compare renders an A/B harness-comparison.json and names the winner. mpl aggregates and renders; your harness produces the artifacts.
- init [--dry-run] [--force]
- Materialize ./agent-harness/ (--dry-run prints the plan without writing; --force overwrites a non-empty dir). Enrollment required even with --dry-run.
- run <task> [--path PATH] [--offline]
- Run the harness on a task; --offline emits a canned schema-valid episode with no model. Default dir ./agent-harness.
- trace [PATH]
- Validate + render an episode.json (default ./agent-harness/artifacts/episode.json).
- eval [PATH] [--baseline PATH]
- Score an eval-report.jsonl; flag regressions vs a golden baseline. Default ./agent-harness/artifacts/eval-report.jsonl.
- compare [PATH]
- Render a harness-comparison.json (A/B) and name the winner. Default ./agent-harness/artifacts/harness-comparison.json.
$mpl agent init$mpl agent run "summarize ./notes" --offline$mpl agent trace$mpl agent eval artifacts/eval-report.jsonl --baseline golden.jsonl
mpl memory inspect
gatedtier floor applies locallyRead, validate, and render a layered agent memory store (D5).
Reads a memory-store.jsonl a Track-D harness emitted and renders its layers (session, project, episodic, semantic), flagging records from untrusted sources. Default path: ./agent-harness/artifacts/memory-store.jsonl.
$mpl memory inspect ./agent-harness/artifacts/memory-store.jsonl
mpl permissions check
gatedtier floor applies locallyAudit a permission/audit log for unsafe allowed actions (D6).
Reads an audit-log.jsonl a Track-D harness emitted and flags any destructive or external action that was allowed ("⚠ unsafe action allowed"). Reuses the SP0 episode SideEffect/PermLevel enums. Default path: ./agent-harness/artifacts/audit-log.jsonl.
$mpl permissions check ./agent-harness/artifacts/audit-log.jsonl
mpl mcp
gatedtier floor applies locallyScaffold an MCP tool server and inspect a workflow run (D8).
scaffold writes a minimal MCP tool-server scaffold (stdio server + client) you can wire your tools into; inspect reads a workflow-run.json a Track-D harness emitted, validates the approval-gate invariant (external tools require an approved approval), and renders the state timeline, tool calls, approvals, and system-of-record outcome. Default inspect path: ./D8-workflows/artifacts/workflow-run.json.
- scaffold [--dry-run] [--force]
- Materialize the MCP server/client scaffold into ./mcp-server/.
- inspect [PATH]
- Validate + render a workflow-run.json (default ./D8-workflows/artifacts/workflow-run.json).
$mpl mcp scaffold$mpl mcp inspect ./D8-workflows/artifacts/workflow-run.json
mpl node
gatedtier floor applies locallyRun a node — the daemon on every box that streams telemetry up and reconciles desired-state down.
The node agent for the managed/cluster rails. Each box runs `mpl node serve`, a local HTTP + SSE daemon (state · desired-state · telemetry · invoke) that converges the box to a desired model + backend and reports health — nothing leaves the box. Identity is a signed node keypair (SIWE); a Day-0 client bootstraps with a join-token. Same `mpl-core` substrate the toolchain runs on. Requires enrollment, like every mpl verb outside the basics (login, doctor, status).
- serve [--bind 127.0.0.1] [--port 7717] [--engine-port 8080] [--drift-interval-secs 30] [--dry-run]
- Start the node daemon: serves /v1/state, accepts /v1/desired, streams /v1/telemetry, runs /v1/invoke, and reconciles on a drift interval. --dry-run prints the planned routes and exits 0 without binding.
- identity [--regenerate] [--peer <id>]
- Show or regenerate the node's signing keypair; set the abstract peer id (walks local → managed-org → wallet).
- enroll --token <tok>
- Accept a join-token to bootstrap this node against a control surface (Day-0).
- desired [--show] [--model <id>] [--quant <q>] [--backend <b>] [--ctx-size N]
- Read (--show) or write the node's desired-state — the model/backend it should converge to.
- state
- Print the live /v1/state payload as JSON (platform profile, identity, last reconcile).
- invoke <verb>
- Invoke a verb on the node remotely via /v1/invoke (v1 supports doctor only).
$mpl node serve --port 7717$mpl node identity --peer acme-org$mpl node desired --model qwen3:8b --backend llama.cpp$mpl node state
mpl fleet
gatedcockpit — runs below the tier floorDrive a whole fleet of nodes from one terminal — a TUI operator console over the node wire API.
The operator surface for a fleet of `mpl node` daemons. Bare `mpl fleet` opens a terminal dashboard that reads each node's /v1/state, streams /v1/telemetry, and pushes desired-state — including a read-only Burst jobs panel. Manage the persistent node registry with add/remove/list, or pass ad-hoc nodes with --node for a one-off session. A pure client of the node wire API — it holds no state of its own beyond the registry.
- (bare) [--node <name>=<url>[:<token>]]
- Launch the fleet TUI dashboard; --node adds an ad-hoc node for this session only (repeatable, not persisted).
- add <name> --url <URL> [--token <tok>]
- Add or update a node in the persistent registry.
- remove <name>
- Remove a node from the registry.
- list
- Print the node registry as JSON.
$mpl fleet add lab-rig --url http://10.0.0.5:7717 --token <tok>$mpl fleet list$mpl fleet$mpl fleet --node lab-rig=http://10.0.0.5:7717
mpl registry
gatedcockpit — runs below the tier floorPush, pull, and verify signed model/config artifacts — minisign signatures + streaming SHA-256.
A signed artifact registry for moving models, configs, and bundles across your fleet with provenance. Every artifact is content-hashed and minisign-signed on push; pull and verify check the signature and hash before placing the file, exiting non-zero on any mismatch. Keys live in ~/.mpl/registry. The supply-chain spine behind the managed rails.
- keygen [--pub-out PATH] [--key-out PATH]
- Generate a minisign keypair into ~/.mpl/registry.
- push <path> --kind gguf|config|bundle [--id <id>] [--key PATH]
- Hash, sign, and store an artifact.
- pull <id> [--out PATH]
- Verify (signature + hash) and place an artifact by id.
- list
- List stored artifacts.
- verify <path> --manifest <id>
- Verify a file against a stored manifest; non-zero exit on signature/hash mismatch.
$mpl registry keygen$mpl registry push ./model.gguf --kind gguf --id qwen3.5-9b$mpl registry pull qwen3.5-9b --out ./model.gguf$mpl registry verify ./model.gguf --manifest qwen3.5-9b
Available on most verbs, layered on top of each command's own flags.
- --explain
- Print the underlying tool commands as they run (does not execute on dry-run paths).
- --json
- Emit a machine-readable JSON report where supported (teaching lines go to stderr).
- --dry-run
- Per-verb flag on action verbs (run/serve/bench/setup/etc.); not available on doctor/status/usage/config/inspect. Dry-run invocations never write a usage entry.
- --engine-arg=<tok>
- Raw engine escape hatch on run / serve / quantize (repeatable; equals form for hyphen-leading flags).
~/.mpl/Global config: activation, install ledger, venvs, scripts.~/.mpl/models/<id>/<quant>.ggufPinned model GGUFs pulled by setup for mpl run / mpl serve (sha256-verified).~/.mpl/ledger.jsonAppend-only install provenance — what setup added, so uninstall can reverse it.~/.mpl/usage.jsonlAppend-only token-usage ledger read by mpl usage.~/.mpl/tools/llama.cpp/<tag>/The pinned engine build (sha256-verified archive), installed by mpl setup../.mpl/Project-local vector store (cwd-relative). Add .mpl/ to .gitignore.