Olace Bridge
The Olace Bridge is a local model endpoint served on your machine at http://127.0.0.1:5578. It speaks three APIs at once, on one port and one key, with nothing to switch between: OpenAI Chat Completions, the OpenAI Responses API, and the Anthropic Messages API. Point any tool that speaks one of them at it, from Claude Code and Codex CLI to editors and chat apps, and that tool can use your whole Olace network: local models through Ollama, LM Studio and llama.cpp, plus the models on every paired host, reached over an end-to-end encrypted connection. Olace's servers never see the prompts or responses of local and paired requests.
This is how your other tools ride the network. The model id decides where inference happens, so a coding agent on your laptop can run on the big GPU at home just by naming it: ollama/qwen3.5:4b runs here, home-pc/ollama/qwen3.6:27b runs on your paired host.
Turn it on
In the desktop app: Settings › Local AI › Olace Bridge. Or:
olace bridge on
It is off by default and listens on loopback only. It serves this computer's models without an Olace account; models on your other computers appear once you sign in. Check it any time with olace bridge or curl http://127.0.0.1:5578/.
Model names
Models are provider-qualified, and paired hosts get a prefix from their pairing label:
ollama/qwen3.5:4b local Ollama
lmstudio/google/gemma-4-e4b local LM Studio
llamacpp/qwen3.5-4b local llama.cpp
home-pc/ollama/qwen3.6:27b paired host "Home PC"
Unambiguous shorthand is accepted; an ambiguous name returns a 404 with the candidates. GET /v1/models lists everything, including models on hosts that are currently offline.
Endpoints
Three API contracts share the port. OpenAI-style tools use http://127.0.0.1:5578/v1 as their base URL; Anthropic-style tools use http://127.0.0.1:5578 (their SDKs add /v1 themselves).
| Route | API | Notes |
|---|---|---|
POST /v1/chat/completions | OpenAI Chat Completions | Streaming and non-streaming. |
POST /v1/responses | OpenAI Responses | The API Codex CLI and the newer OpenAI SDK calls use. |
POST /v1/messages | Anthropic Messages | The API Claude Code and the Anthropic SDKs use. |
POST /v1/messages/count_tokens | Anthropic Messages | Token count for a request. |
POST /v1/completions | OpenAI | Legacy text completions. |
POST /v1/embeddings | OpenAI | Local and paired models. |
GET /v1/models | Both | One list across local and paired providers, in a shape both the OpenAI and Anthropic SDKs read. |
GET /v1/models/{id} | Both | Accepts canonical ids and unambiguous shorthand. |
Claude Code and Codex CLI
Claude Code talks to the Bridge through the Anthropic Messages API. Set three variables and start it; the model id decides which computer runs it:
export ANTHROPIC_BASE_URL=http://127.0.0.1:5578
export ANTHROPIC_API_KEY=unused # or your Bridge key
export ANTHROPIC_MODEL=home-pc/ollama/qwen3.6:27b
export ANTHROPIC_SMALL_FAST_MODEL=ollama/qwen3.5:4b
claude
ANTHROPIC_SMALL_FAST_MODEL is optional; it names the model Claude Code uses for its quick background tasks, so a small local model keeps those off the big GPU.
Codex CLI talks to the Bridge through the Responses API. Add the Bridge as a provider in ~/.codex/config.toml:
model = "home-pc/ollama/qwen3.6:27b"
model_provider = "olace"
[model_providers.olace]
name = "Olace Bridge"
base_url = "http://127.0.0.1:5578/v1"
env_key = "OLACE_BRIDGE_KEY"
wire_api = "responses"
Then start it with your Bridge key (any text works when no key is set):
OLACE_BRIDGE_KEY=unused codex
Examples
curl http://127.0.0.1:5578/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "ollama/qwen3.5:4b",
"messages": [{"role": "user", "content": "Hello from the Bridge"}]
}'
from openai import OpenAI
client = OpenAI(base_url="http://127.0.0.1:5578/v1", api_key="unused")
reply = client.chat.completions.create(
model="home-pc/ollama/qwen3.6:27b",
messages=[{"role": "user", "content": "Hello from the Bridge"}],
)
print(reply.choices[0].message.content)
The Responses API, from curl and from the OpenAI SDK:
curl http://127.0.0.1:5578/v1/responses \
-H "Content-Type: application/json" \
-d '{"model": "ollama/qwen3.5:4b", "input": "Hello from the Bridge"}'
from openai import OpenAI
client = OpenAI(base_url="http://127.0.0.1:5578/v1", api_key="unused")
resp = client.responses.create(
model="home-pc/ollama/qwen3.6:27b",
instructions="Answer briefly.",
input="Hello from the Bridge",
)
print(resp.output_text)
The Anthropic Messages API, from curl and from the Anthropic SDK:
curl http://127.0.0.1:5578/v1/messages \
-H "Content-Type: application/json" \
-H "anthropic-version: 2023-06-01" \
-d '{
"model": "ollama/qwen3.5:4b",
"max_tokens": 512,
"messages": [{"role": "user", "content": "Hello from the Bridge"}]
}'
from anthropic import Anthropic
client = Anthropic(base_url="http://127.0.0.1:5578", api_key="unused")
msg = client.messages.create(
model="home-pc/ollama/qwen3.6:27b",
max_tokens=512,
messages=[{"role": "user", "content": "Hello from the Bridge"}],
)
print(msg.content[0].text)
Any tool that speaks one of these APIs works the same way: set the base URL (http://127.0.0.1:5578/v1 for OpenAI-style tools, http://127.0.0.1:5578 for Anthropic-style ones), set the API key to anything (or your Bridge key, below), and pick a model id from GET /v1/models.
Works with your tools
Most coding agents, editors, and chat apps accept a custom OpenAI-compatible or Anthropic-compatible endpoint. Where to point them:
| Tool | Kind | Where to set it |
|---|---|---|
| Claude Code | Terminal coding agent | ANTHROPIC_BASE_URL, ANTHROPIC_API_KEY, ANTHROPIC_MODEL env vars (above) |
| Codex CLI | Terminal coding agent | A ~/.codex/config.toml provider (above) |
| Continue | Coding assistant (VS Code, JetBrains) | ~/.continue/config.yaml, apiBase |
| Cline | Coding agent (VS Code) | Settings › API Provider › OpenAI Compatible |
| Zed | Editor with agent panel | settings.json, openai_compatible provider |
| OpenCode | Terminal coding agent | opencode.json, provider baseURL |
| Aider | Terminal pair programmer | OPENAI_API_BASE + OPENAI_API_KEY env vars |
| Droid (Factory) | Coding agent | ~/.factory/settings.json, customModels |
| Open WebUI | Self-hosted chat UI | Admin Settings › Connections › OpenAI |
| Jan | Desktop chat app | Settings › Model Providers › Add Provider |
| Chatbox, Cherry Studio | Desktop chat apps | Add provider, type "OpenAI API Compatible" |
| Copilot for Obsidian | Notes plugin | Custom model, "3rd party (openai format)" |
One worked example, Continue:
# ~/.continue/config.yaml
models:
- name: Home GPU
provider: openai
model: home-pc/ollama/qwen3.6:27b
apiBase: http://127.0.0.1:5578/v1
Practical notes that save a few minutes:
- Most tools require a non-empty API key even when the Bridge has none set; any string works.
- Tools with a "fetch models" button read
GET /v1/modelsand will list your whole network, paired hosts included. - Desktop apps built on Tauri or Electron (Jan and many others), editor webviews, and browser extensions send an origin. The Bridge allows those out of the box, along with any page served from your own computer. A web app on a real domain needs one command:
olace bridge cors add https://app.example.com. - Open WebUI in Docker should use
host.docker.internalinstead of127.0.0.1. - A few tools route model calls through their vendor's servers (Cursor's base-URL override, for example); those cannot reach an endpoint on your machine. The Bridge is local-first by design.
Authentication
By default there is no key and the Bridge accepts connections from this machine only. If you want a key anyway, or you plan to front the Bridge with a reverse proxy:
olace bridge key --require-key
The key is shown once and then required on every API, as Authorization: Bearer <key> or as x-api-key: <key> (the header the Anthropic SDKs and Claude Code send). Rotate with --regenerate, remove with --no-key. A web app hosted on a real domain also needs its origin allowed: olace bridge cors add <origin>, or bridge_cors_origins in daemon.json.
Behavior worth knowing
- Streaming.
stream: trueis supported on all three APIs, each with its standard event stream (chat completion chunks,response.createdthroughresponse.completed,message_startthroughmessage_stop). While a cold model loads, the stream sends keep-alive lines so clients do not time out. - Reasoning models think only when asked: send
reasoning_efforton Chat Completions,reasoning.efforton Responses (low,medium,high, ormax;minimalcounts aslow,nonekeeps it off), orthinking: {"type": "enabled", "budget_tokens": n}on Messages, where the budget maps onto the model's thinking level. The level is capped at what the model supports. Models that always think still do. Thinking streams asdelta.reasoning_contenton the OpenAI APIs and asthinkingblocks (with an empty signature) on Messages. - Tool calls work on all three APIs (function
toolson the OpenAI APIs,toolswithinput_schemaandtool_choiceon Messages). A tool call's arguments arrive whole at the end of the turn rather than token by token, because the model runtimes deliver them that way. - Responses API scope.
inputas a string or as message,function_callandfunction_call_outputitems,instructions,max_output_tokens,text.format(text, JSON mode, JSON schema). The Bridge stores nothing, soprevious_response_idis not supported (resend the full input each turn), nor arebackgroundandconversation;store,metadata,truncation,include,parallel_tool_callsand OpenAI's built-in tools (web search, image generation) are accepted and ignored. Function tools grouped in anamespacework like any other function tool. - Messages API scope.
system, text, base64 image,tool_useandtool_resultblocks,max_tokens(required),stop_sequences,temperature,top_p. Not supported: image URLs (inline base64 instead) anddocumentblocks.top_k,metadata,service_tier,cache_controland Anthropic's server tools (web search, bash, computer use, text editor) are accepted and ignored, so the request runs with your own tools only. Errors on these routes use the Anthropic error shape. - Images are accepted as base64 data URIs and downscaled on your device before sending; remote image URLs are rejected.
- Honored parameters include tools,
tool_choice,temperature,top_p,stop,max_tokens,response_format(JSON mode and JSON schema). Unsupported OpenAI extras are accepted and ignored;n > 1and audio are rejected. - Paired hosts. Requests prefer a direct LAN connection and fall back to the encrypted relay when you are away. Sessions stay warm between requests, so bursts of agent calls skip the handshake. An offline host fails fast with
503 host_offline. - Errors use the standard OpenAI envelope, with meaningful codes like
model_not_found,host_offline,host_busy,context_length_exceeded, andunsupported_message_role(asystemordevelopermessage that is not the first message, on a llama.cpp model).
A note on scope
The Bridge serves your local and paired models. Requests never route to Olace Cloud models, so a misconfigured tool can never quietly spend your credits.