Studio
The Studio is the web UI built into the paddock manager binary. Start the manager and it is there, on the same port as the manager API, with nothing extra to install.
Opening the Studio
paddock
# then open http://localhost:11500It is a single-page app with real URLs, so deep links survive a refresh. The UI splits into two areas, and the split is the thing to understand first.
| Area | What lives there |
|---|---|
| Manage | The models you run on this machine: starting and stopping them, downloads, GPU telemetry, logs, hardware readiness |
| Studio | The things you do with a model: chat, transcription, embeddings, connectors, cloud models, prompts |
Manage
Each model runs as its own server on its own port, so several can run side by side and the Manage area is where you control them.
- Models. Start a new endpoint from the catalog or from a GGUF on disk, choosing the weights variant, context window and batch width. Stop, edit, pin, or switch which model a port serves without moving the port.
- Catalog and downloads. Models are grouped by role with a spec sheet each: quantization, parameter count, context length, license and vendor homepage. One click pulls a model with live progress, and the page refuses a download that will not fit the disk.
- Usage. A dashboard of six charts over a window you pick, from the last hour through all recorded history, filterable to one model, with the totals for that window as a strip above them. It charts requests per second, request duration, prefix-cache hit rate, and tokens split into fresh input, cached input and output, so the saving from caching is visible rather than inferred. Failures are broken out by what actually happened: client errors, disconnects, and crashes are different problems and get different lines. Plain scrolling moves the page and Ctrl with the wheel zooms a chart, so a dashboard never traps your scroll.
- Instrument. Activity, GPU telemetry and logs behind the dashboard, with the merged log stream prefixed by source.
- GPUs. What this machine can run: the detected card, whether its generation is one Paddock serves, and what to do about it when it is not. See GPU Support.
- Trust. The machine's certificate: its fingerprint, the names it covers, and the root to install on a device you open the Studio from. Installing it stops the browser warnings; not installing it still works. This matters because a browser withholds the microphone entirely from an insecure origin, so dictation and live transcription only exist off-box over HTTPS. See Server Configuration.
Will It Fit
Starting a model asks one real question, and the Studio answers it to scale rather than with a traffic light. The card is drawn as a single bar, segmented into what other applications already hold, the model's resident floor of weights and serving state, what the workload you selected costs in KV cache, and the pool the engine would still take for longer or more numerous conversations. A model that does not fit simply overflows the edge of the card.
The split is the point. Resident is the floor that has to fit for the model to load at all, and it does not include the KV cache. The cache is a shared pool that takes whatever is left, so it never decides whether a model fits, only how much context you get.
Which is why the one thing you choose is how many requests should run at once. Context is then derived per model from what the card can actually back at that concurrency, capped by that model's own trained window. A fixed list of context sizes was wrong in both directions: it offered 128K to models that cap at 32K and hid the full 256K of models that have it.
Making Room
A start that will not fit does not fail with a number and leave you to work it out. The server answers with a concrete plan naming which running models would free enough VRAM, and the Studio turns that into a dialog you either accept or decline. Nothing is stopped without your explicit yes, and any start path can raise the offer: a stopped row's start button, the start page, or a redeploy after an edit.
Updates
The manager checks whether a newer Paddock has been published and surfaces it in the UI with its release notes, so an update is something you read before you take rather than a version number that appears. The download runs in the background against the size the release reports, and it can be cancelled.
What arrives is verified rather than trusted. The release API computes a SHA-256 while the upload streams through it, so the hash describes what the API stored and will serve rather than what a publisher claimed to send, and the manager checks the bytes against it before replacing anything. Releases published before that hash existed report none, and in that case the manager says so plainly in its log instead of quietly accepting the download. This is the one download that replaces the program itself, and TLS protects the transport rather than the contents.
Nothing about this needs an account. The read path on the release API is public, which is what keeps the local product account-free.
Where Your Data Lives
The manager owns one SQLite database, and it is the only database on the machine. Model servers are stateless: a runner holds a model and answers requests, and stores nothing. That split is worth knowing before you plan a backup or wonder what a bare server keeps about you, which is nothing.
The file is ~/paddock/paddock.db, alongside models/, logs/ and servers/. SQLite is compiled into the binary, so there is no database to install and no service to run. Back up that one file and you have taken everything except the model weights.
| What it holds | Details |
|---|---|
| Conversations and attachments | Every chat, plus the image, document and audio bytes you attached, stored server-side and streamed back on demand |
| Artifacts and their versions | Bodies live here rather than in the message thread, which is what keeps an edited document out of the context window |
| Prompts and presets | The saved system-prompt library |
| Connectors and MCP servers | The servers you registered or tried, and their credentials |
| Cloud endpoints and usage | Provider accounts, and per-model input, output and reasoning token counts with cost |
| Activity | One record per request served, with endpoint, status, model and timings |
| API keys and settings | Keys you minted for the manager API, and app settings |
Because it is server-side rather than browser storage, chats survive a cache clear and any browser pointed at the same manager sees the same history.
Knowing What You Spent
Cloud usage is recorded per call: which endpoint, which model, input, output and reasoning tokens, and cost where the provider reports one. Since cloud and local models sit in the same picker and can answer the same compare turn, this is how you find out what a habit of reaching for a hosted model is costing you, rather than discovering it on an invoice.
Local requests are recorded too, in the activity log, though there is nothing to bill: the interesting part there is which endpoint served what, with what status and how fast.
Export
Settings has a one-click export that downloads a sanitized copy of the database as a SQLite file. Stored API keys and connector credentials are stripped from it, so an export can be moved or shared without carrying secrets with it. It is an ordinary SQLite file, so anything that reads SQLite can read your history.
Chat
Chat streams over a model server's OpenAI Responses API (/v1/responses), the same endpoint external clients use.
- Reasoning. Thinking models stream their reasoning into a collapsible fold that shows how long the model thought. The control adapts to the model: GPT-OSS takes a low, medium or high effort setting, Qwen takes an on/off thinking toggle.
- Rendering. Replies render as Markdown with syntax-highlighted code blocks, KaTeX math, and Mermaid diagrams.
- Turn control. Stop a reply mid-stream, regenerate the last answer, or continue a reply that hit the length cap from exactly where it stopped.
- Sampling. A per-chat sampler menu exposes the decode settings, so a turn's record says what produced it rather than leaving you to guess.
- System prompts. Each chat has its own system prompt, edited in a panel that can load a preset from the saved-prompt library or save the current text as a new preset.
- Context handling. A meter shows how much of the context window the conversation uses. When a chat outgrows the window, older messages are summarized in the background so the model keeps the thread; turn that off in Settings to drop the oldest messages instead.
- History. The sidebar searches chats by title and supports pin, rename, delete, and multi-select delete. Titles are set automatically from the first message.
Comparing Models Side by Side
A turn can fan out to several models at once, and the thread shows their answers side by side under the one question that produced them. Because every model server is separate, a compare can put a local model next to a hosted one on your own key, or two local models against each other, or the same model at two different sampling settings.
Each answer keeps its own run details, so a comparison is decided on time to first token, tokens per second and GPU load rather than on impressions.
Speech models compare too, and that case needed one specific thing to be useful. The same audio appears in every column, and only the segmentation differs between them, so the Studio drives them all from a single player and a single clock. You hear a passage once and watch each column light its own span, instead of playing the same eight seconds once per model to check two readings of it.
Artifacts
An artifact is substantial standalone content a model wrote and you keep: a page, a chart, a document. It lives in the side panel rather than in the message flow, and it is versioned. Ask for "make the header blue" three turns later and you get v2 of the same artifact rather than a fresh copy pasted into the conversation.
| Kind | Shown as |
|---|---|
html | Rendered live in a sandboxed frame, with the source a tab away |
svg, mermaid | Drawn |
markdown | Formatted |
code | A full editor, syntax-highlighted for the artifact's language |
csv, text | Plain |
Why Artifacts Do Not Fill The Context Window
The conversation carries the operations; the body stays in the store. When a model edits an artifact it is told "replaced 4 lines with 6" rather than being handed the new content, because echoing the result would put the whole document back into the prompt and defeat the point. A model that genuinely needs to see a body again asks for it deliberately.
Edits are exact-string replacements that must match once, with a full rewrite as the escape hatch for changes too broad to express that way. That is the design that has held up in practice; patching by regular expression is the branch that did not.
Why This Is A Studio Feature
The artifact tools are attached to each Studio request rather than configured on a model endpoint, and that is on purpose. If a model server advertised them to everyone, a coding agent or a curl client would have the model call one, the content would land in the store, and the caller would get back an identifier for something it has no panel to display. That is a silent failure, and it would also make a standalone model server depend on the manager being up. The capability stays where the surface to show it exists.
Comparing Generated Pages Side by Side
Artifacts group by the model that wrote them, so a compare turn is exactly two named groups. Each gets its own pane with its own tabs, and both render at once: ask two models for a landing page and you watch both pages, not two blocks of HTML you have to imagine. Local against hosted works the same way, since a cloud model reaches the same store.
How Generated HTML Is Contained
Rendering content a model wrote is the point, and it is also the risk, so the preview frame is locked down rather than trusted. It runs with scripts allowed but no same-origin access, which puts it at an opaque origin where it can touch nothing of the Studio's. Its content policy permits computing and drawing and nothing else: connect-src is none, so a script cannot reach the network at all.
Two details are deliberate. The frame is served over HTTP rather than injected inline, because the sandbox and frame-ancestors rules only work as real headers and are ignored in a meta tag. And the frame arrives empty: the panel posts the body in afterwards, so the shell itself carries no data and needs no credentials, which is what lets it sit outside the authenticated API where an iframe cannot send a header anyway.
Remote images are refused by default, because an image URL is a way to send data out and the artifact was written by a model that may have read untrusted input. Models reach for placeholder image services constantly, so when that leaves a page visibly wrong you can allow pictures for that one preview. It widens exactly that: scripts still cannot talk to anything, and the sandbox is unchanged.
Choosing Tools
Each chat is either on "all tools", meaning every tool the endpoint supplies plus the connectors you switched on for that chat, or a custom pick. The custom pick is searchable across every tool that every source exposes, down to a single one, and a single-tool pick travels with the request as an explicit allowed-tools filter rather than as a hint the model may ignore.
The picker is a builder rather than a set of switches. Under "all tools" only that row shows as checked, and clicking any row starts a new subset containing it, because someone who searched for a tool by name means "give me this one", not "everything except this one". All-but-one is still reachable: take the whole server, then uncheck the one you do not want.
Tool inventories load lazily. Opening the picker kicks off a listing probe per source and caches the result for the session, so the first open costs a round trip and the rest are instant. A server whose listing fails is a state rather than an error, and it stays pickable as a whole server, since a listing that did not answer is not evidence the tools are gone.
Where an MCP server publishes its own instructions, the Studio shows them read-only. The server folds those into the system prompt, and text that reaches the model should not be invisible to the person responsible for the conversation.
What The Model Reads
Any attachment can be opened to see exactly what the model will receive: the header note, the metadata block with title, author and dates or a photo's capture time, camera and coordinates, and the extracted content itself, verbatim as the prompt carries it. Documents get it as a tab next to the rendered file; photos get it from an eye button on the tile.
Refusals show the same way. An encrypted PDF or a file that turned out to be binary displays the message a real send would produce, so a preview never implies a request will work when it will not. See Documents and Images for the pipeline behind it.
Speech
Transcription is a conversation rather than a separate tool. Start a speech model like any other, and the composer switches to audio: the turn persists with its clip, its timings and its tokens, so a transcript is a record you can return to rather than text that scrolls away.
Dictation works while you type. The session finalizes an utterance each time you pause, so speech arrives as a stream of small commits at the end of the document while your cursor stays where you left it; you can go back and fix a word three sentences up without the next utterance landing on top of the edit. The open utterance is drawn as a decoration until it settles.
A transcript can mark the words the model was least sure of. This is one mark rather than a scale, and it is behind a toggle, because the underlying number is not a probability of being correct: raw confidence from an end-to-end speech model is known to run high. It is useful for finding the handful of words worth listening back to, and it is not a quality score.
Transcripts export as SRT or WebVTT, computed from the turn you already have. The endpoint can return subtitles directly, but asking it to would re-run the whole transcription, which on a forty-minute recording means a second full decode to get a file the Studio can already write. See Speech to Text for the API underneath.
Attachments
Attach a document and the server turns it into something the active model can read: rendered pages for a vision model, extracted text and metadata for any model. Spreadsheets arrive as tables, photos bring their capture details, and the composer tells you which route your attachment took rather than leaving you to infer it from the answer. A preview shows exactly what the model will receive before you send. See Documents and Images for the whole pipeline.
Run Details
Every answer records exactly what produced it: the model, the system prompt, the sampling parameters, the enabled tools, and the GPU it ran on. Expanding a turn's run details shows time to first token, tokens per second, reasoning time and tokens, and the peak GPU load sampled during the turn. Regenerate a reply under different settings and the two turns keep their own records, so you can compare runs on facts instead of impressions. For engine-versus-engine comparisons, see Benchmarking.
Connectors
Connectors are your personal library of MCP servers, tried per chat and carried inside the request. They are a separate tier from a model endpoint's own tools, which are configured on that endpoint and are part of the contract every API client sees.
The find tab is a searchable, sortable table of the public directory at registry.truespar.com, queried straight from your browser with no key and with the manager never in the path. That catalog is discovered rather than vetted, and the UI says so: a liveness check tells you an endpoint answered, which is not an endorsement of what it does.
- Transports. Local servers over stdio (command, arguments, environment) and remote servers over HTTP (URL, headers), with OAuth 2.1 sign-in for remote servers that require it. Tokens and secrets stay on the server.
- Approval. A per-server "require approval" mode routes every tool call through an approve or deny prompt in the chat thread before it runs.
- Per-chat toggle. Each chat has one tools switch; on lets the model use any enabled server, off gives a tool-free chat.
Tool execution happens server-side, so API clients get tools through /v1/responses too. See the MCP page for the API side.
Cloud Models
Cloud models are external provider endpoints you bring your own key for. Once added they join the model pickers next to the models running on your machine, which is what makes "is my local model good enough for this?" a single turn rather than an afternoon.
| Provider | How it connects |
|---|---|
| OpenAI | Native, passed through |
| Anthropic | Messages API |
| OpenRouter | Its full catalog, with the per-provider breakdown |
| Any OpenAI-compatible endpoint | Give it a base URL and a key |
- Browse before you commit a key. OpenRouter's model list is public, so the catalog is searchable before you have pasted anything. The default view is sorted by recent popularity. Other providers answer a keyless browse with their own sign-in error rather than a message we invented.
- Pick the provider behind the model. An OpenRouter row expands into the providers actually serving that model, and adding from that view pins your choice to one of them instead of leaving the routing open.
- One key per provider. Every model from that provider shares it. Keys live in the manager's database and travel only from the manager to the provider; the browser is told whether a key exists and never receives one.
The Studio works in one format throughout: the OpenAI Responses event stream it already uses for local models. The manager translates each request into the provider's native call and translates the provider's stream back, so a cloud model and a local one are the same kind of thing to everything upstream, including a compare turn.
This seam is private to the Studio. It lives under the manager's authenticated /api, and the manager port does not serve /v1 at all, so Paddock does not become an open proxy to your paid accounts.
Embeddings
A running embedding or reranker model can be tried directly in the Studio, so a non-chat model is something you can exercise rather than only point a client at.
Web Search
Chat can search the web through a provider you bring your own key for: Exa or Tavily. Pick the provider and paste the key in Settings; the key is stored write-only on the server and never sent back to the browser, and a test button checks it works before you rely on it. Each chat has a globe toggle, off by default. Search calls appear in the thread as cards showing the query and the sources the provider returned.
The search itself runs on the model server, not in the browser, and the same tool is available to any API client on both the OpenAI and Anthropic dialects. What the Studio adds is storage: it keeps your provider choice and key and hands them to each model server as it starts, so you configure it once instead of per endpoint. A server you launch yourself takes the same settings as flags. See Setting Up Web Search.
GPU Telemetry
A live hardware dock streams GPU telemetry over a WebSocket: utilization, VRAM used and total, temperature, power draw against the limit, clocks, and fan speed, alongside engine counters such as current tokens per second, prefill or decode phase, and KV cache usage. Telemetry is sampled through NVML and degrades gracefully on machines without an NVIDIA GPU.
For scraping rather than watching, each model server exposes the same engine counters in Prometheus format on its own port. See Metrics.
Settings
| Setting | What it controls |
|---|---|
| Max reply length | The longest a single reply can be; thinking and answer share the budget, capped by the model server's context window |
| Context length | Shown read-only; change it by restarting the endpoint with a different --max-ctx |
| Summarize older messages | Background compaction when a chat outgrows the context window |
| Web search | Provider choice (Exa or Tavily), API key, and a connection test |
| Appearance | Light or dark theme |
| Export | Download a sanitized SQLite copy of the server store |