Effortless local & self-hosted model backends for the Pi coding agent.
Crossbar is an extension for the Pi coding agent that makes wiring Pi to any local or self-hosted model backend effortless — zero hand-edited JSON, all setup inside Pi's TUI, with auto-discovery, multi-server support, live "currently loaded" indicators, and in-place model switching.
Built by Hypabolic.
Existing connectors stop short: manual config files, a single server at a time, Ollama-only discovery, or hardcoded model lists. Crossbar beats them on three axes:
- Widest backend support — Ollama, LM Studio, llama.cpp, llama-swap, vLLM, OpenAI, Anthropic, plus a generic adapter for the OpenAI-compatible long tail (TabbyAPI, KoboldCpp, text-generation-webui, Jan, llamafile, …).
- Easiest onboarding —
/crossbarauto-discovers running servers on localhost and registers them. No JSON. API-key and no-auth endpoints, with a connection test before you commit. - Highest-fidelity UX — multiple simultaneous servers, a live loaded-model widget, and capability- driven model switching that gracefully hides what a backend can't do.
| Backend | Discover | Loaded indicator | Switch model | Load/Unload | Auth |
|---|---|---|---|---|---|
| Ollama | ✅ | ✅ live | ✅ implicit | ✅ | none (local) |
| LM Studio | ✅ | ✅ live | ✅ JIT | ✅ | optional key |
llama.cpp (llama-server) |
✅ | ✅ (single) | ❌¹ | ❌ | optional key |
| llama-swap | ✅ | ✅ live | ✅ proxy swap | ✅ | optional key |
| vLLM | ✅ | last-known | ❌¹ | ❌ | optional key |
| OpenAI | configured | — | pick model | — | API key |
| Anthropic | configured | last-known | pick model | — | API key |
| Generic OpenAI-compatible | ✅ (fallback) | last-known | ❌ | ❌ | optional key |
¹ Single model per instance. Run llama-swap in front of llama-server/vLLM to unlock switching —
Crossbar detects it automatically and prefers it.
Full endpoint-level detail is in CAPABILITY-MATRIX.md; research notes and
Pi-integration citations are in RESEARCH.md and ARCHITECTURE.md.
# from npm
pi install npm:@hypabolic/crossbar
# or from git
pi install git:github.com/hypabolic/crossbar
# or a local checkout
pi install /path/to/crossbarThen start Pi and run /crossbar.
/crossbar(alias/local) — open the server manager. Discover/rescan servers, add one manually, enable/disable or remove saved servers, switch/load/unload models where supported, and inspect a server's currently loaded models. Esc/Back from a server returns to the server list.- Adding a server registers its chat models immediately. Choosing Select model to use in Pi also makes that model current; Esc skips selection while keeping the server registered.
- Auto-discovery runs on session start: reachable no-auth servers on localhost are registered automatically; keyed servers are surfaced with a prompt to add them.
- Registered models appear in Pi's standard
/modelpicker and/loginprovider list. - The loaded-model widget shows what's currently resident (
●live via introspection,◷with a(last-known)suffix where a backend can't report live state).
LAN discovery (beyond localhost) is off by default — no backend advertises over mDNS, so Crossbar
never touches your network unless you opt in. Toggle it (and edit the LAN host / probe-port lists)
from /crossbar → ⚙ Discovery settings; changes are saved to crossbar.json and apply on the
next scan. When enabled with no explicit hosts, Crossbar auto-detects your machine's own private
subnet (e.g. 10.0.0.0/24, derived at runtime from the system's network interfaces — never
hardcoded) and sweeps it. You can override that by entering specific hosts, a CIDR (10.0.1.0/24),
or a range (10.0.1.10-50); the expansion is capped at 1024 addresses. A full /24 sweep is a few
seconds to ~20s depending on how many probePorts are set — narrow the port list to your backend's
port to make it fast.
- Discovery probes localhost ports and fingerprints each server by response shape (e.g. Ollama's
GET /banner, LM Studio's/api/v0/modelsstate, vLLM's/version+owned_by), preferring the most specific match. The generic adapter is the low-confidence fallback. - Registration maps discovered models onto Pi's built-in
openai-completions/anthropic-messagesproviders viapi.registerProvider— Crossbar writes no streaming code for OpenAI-compatible servers. - Two-phase startup: the async extension factory runs before Pi resolves models and preloads
any enabled servers that have a persisted
lastKnownModelscatalogue (seesrc/preload.ts+registerCachedServer). This makes saved models available to--list-models, print/JSON/RPC, CLI--modelselection, and--offlineruns with zero network or UI.session_startstill performs live refresh, auto-discovery, polling, and widget installation. - Persistence keeps non-secret server metadata (including
lastKnownModels) in~/.pi/agent/crossbar.json; API keys live only in Pi'sauth.json(mode0600), keyed by the server's provider id. A brand-new server with no cached catalogue cannot be selected programmatically until an interactive/crossbaradd or discovery persists its models (inherent cold-start limitation).
- API keys are never written to
crossbar.json, never logged, and never inlined into a provider config — Pi resolves them fromauth.jsonat request time. - Discovery is localhost-only by default.
- Crossbar adds no telemetry.
npm install
npm run check # tsc --noEmit
npm test # vitest (conformance + unit + live-socket integration)The BackendAdapter contract (src/core/) is the frozen boundary every adapter implements; the
conformance suite (tests/conformance/) validates every adapter against it, and
tests/integration/ exercises the real discovery path over live sockets.
CI (.github/workflows/ci.yml) runs tsc --noEmit + the full test suite on every push and PR
(Node 22 & 24).
MIT © Hypabolic
