STDLIB-ONLY · ONE GPU, THE WHOLE TEAM · ZERO EGRESS

A chat for your local LLM, in ~230 lines of stdlib.

A clean chat UI backed by a small HTTP server that proxies to an Ollama instance on a remote GPU (over a private VPN). The browser never talks to the GPU directly: the gateway is the only thing that knows where the model lives. A single entry point a whole team shares, the GPU off the public network, and nothing going to any cloud provider. All in Python stdlib — no framework, no build, no pip install.

~230 lines
Python stdlib + 3 static files, auditable in one sitting
1 entry point
only the gateway knows OLLAMA_URL; the GPU stays private
stream real
Ollama's NDJSON relayed as chunked HTTP, token by token
0 egress
inference never leaves your hardware
How it works

The gateway is the only door.

🚪

The only thing that knows where the GPU is

Clients hit the gateway; the gateway holds OLLAMA_URL. The model host stays on a private network — one shared, auditable entry point instead of N browsers each configured with the GPU's address.

🌊

Real streaming, end to end

/api/chat relays Ollama's NDJSON as chunked HTTP transfer, and the browser reads the incremental stream — tokens show up as they're generated. Streaming is preserved even against the demo's mock.

🏷️

Readable model catalog

/api/models enriches Ollama's /api/tags with plain-language notes about quantization (Q4_K_M…) and capabilities (vision, tools, thinking), so a non-expert can pick well. The context window is exposed and configurable per conversation.

🛡️

Failures handled

Static file serving is hardened against path-traversal; if Ollama is unreachable, it returns a clear 502 with the target URL instead of hanging or leaking a stack trace; mid-stream disconnects are swallowed cleanly.

Why stdlib-only

Small and boring is a feature.

THE DECISION

No framework, no build

Runs on any box with a Python 3 interpreter and nothing else: python gateway/server.py. A trivially auditable codebase, no dependency supply chain, no version drift, and a Docker image that's just python:3.12-slim + a few files.

THE DEMO

Runs without a GPU

docker compose up brings up a mock Ollama that streams a canned but coherent response, so the whole path (browser → gateway → Ollama) works without a GPU or a real model. Point OLLAMA_URL at your host and you're talking to the real model.

TESTS

Four end-to-end tests, and what they do not prove.

The test suite is stdlib-only, the same constraint as the gateway itself. Each run boots the real gateway and a mock Ollama as separate subprocesses on ephemeral ports, waits for both to come up, then drives them over HTTP like a browser would. Nothing is stubbed in-process: if the wiring is broken, the test fails.

01

test_health

/api/health answers. Local liveness, independent of the model host.

02

test_models_proxied

The mock catalog arrives through the gateway — the proxy path is real, not a fixture.

03

test_chat_streams

A reply streams end to end: client → gateway → mock. This is the one that matters; streaming is where a proxy usually breaks.

04

test_index_served

The UI is served from static/.

What this does not prove

There is no coverage measurement, no load benchmark and no security suite in this repository — so this page will not quote you one. These four tests prove the path is wired end to end; they do not prove the gateway is hard against a hostile client. For 216 lines of standard library whose deployment assumption is a private network, that is a deliberate ceiling rather than an oversight — but it is a ceiling, and a number nobody measured would be worth less than saying so.

API

Four endpoints.

MethodPathPurpose
GET/Serves the chat UI
GET/api/healthLiveness + the configured OLLAMA_URL
GET/api/modelsModel catalog enriched with readable metadata
POST/api/chatProxies chat to Ollama; streams NDJSON back
The request path

One POST, four ways it can go.

The browser only ever sends POST /api/chat. The gateway is the single component that knows where the GPU host lives — and it has to handle a bad request, a dead upstream, and a user who closes the tab mid-answer without ever hanging.

BrowserPOST /api/chat Gateway_proxy_chat() · stdlib only Ollamaon-prem GPU host