This reference is for code running on the same Mac as Lantern or for server code using local.fetch() through an approved connection. A normal Next.js app should start with the Vercel AI SDK guide.
REST quick start
Web apps should usually use the Lantern Vercel AI SDK provider, which handles connecting, routing, signing, and streaming. The server helper also exposes local.fetch(path, init) for supported AI calls through the same connection: chat completions, messages, image generations, and image edits. Tools on the Mac can call the local endpoint with the token created during setup.
const local = lantern.server(request);
const response = await local.fetch("/v1/chat/completions", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
model: local.model,
messages: [{ role: "user", content: "Explain why the sky looks blue." }],
}),
});curl http://127.0.0.1:4319/v1/chat/completions \
-H "Authorization: Bearer $(tr -d '\n' < ~/.lantern/token)" \
-H "Content-Type: application/json" \
-d '{
"model": "codex",
"messages": [{ "role": "user", "content": "Explain why the sky looks blue." }]
}'The response puts generated text in choices[0].message.content and includes token usage plus Lantern metadata from the CLI.
Chat requests support text messages only. Client-defined tools and structured response formats are not supported.
HTTP endpoints
GET /healthReturns the running Lantern version so a local tool can check that the process is on.
GET /v1/catalogLists configured providers, their provider-named model IDs, and current CLI availability.
GET /v1/modelsLists available providers in OpenAI's model-list format.
POST /v1/chat/completionsOpenAI-compatible text generation with standard JSON or server-sent event responses.
POST /v1/messagesAnthropic-compatible text generation with Anthropic's named streaming events.
POST /v1/images/generationsOpenAI-compatible image generation through a signed-in Codex setup with working image generation. Returns one PNG.
POST /v1/images/editsAccepts up to eight GIF, JPEG, PNG, or WebP files, 20 MB each and 64 MB total. Returns one PNG.
POST /v1/agent/runsA trusted local workspace task with an explicit directory and read or write access level, streamed as newline-delimited events.
WS /v1/socketThe persistent multi-turn session interface described below.
AI endpoints accept Authorization: Bearer …. Anthropic clients can use x-api-key. The health endpoint is open so local process managers can check whether Lantern is running. CLI availability means the command was found when Lantern started; it does not re-check sign-in.
HTTP streaming
Add "stream": true to an OpenAI-compatible request to receive server-sent events as the CLI generates output.
{
"model": "claude",
"stream": true,
"messages": [
{ "role": "user", "content": "Give me three names for a weather app." }
]
}Lantern sends standard chat-completion chunks and finishes the stream with [DONE]. Provider diagnostics and local usage remain available as Lantern metadata.
WebSocket sessions
The lantern.v1 WebSocket protocol keeps one CLI conversation open for follow-up prompts. Browsers send the token as a WebSocket subprotocol because they cannot set an Authorization header.
Treat the token below like a password: it grants access to Lantern's local REST and WebSocket APIs. A browser receives it only through the older pairLocalLantern() flow. New websites should use createLanternApp so the token never enters the page.
const encoded = btoa(token)
.replaceAll("+", "-")
.replaceAll("/", "_")
.replaceAll("=", "");
const socket = new WebSocket(
"ws://127.0.0.1:4319/v1/socket",
["lantern.v1", `lantern.auth.${encoded}`],
);Scripts and server processes can send the token in a normal Authorization header when opening the WebSocket. After authentication, Lantern sends a hello message with the available providers and model names.
{
"type": "session.start",
"requestId": "start-1",
"provider": "codex",
"prompt": "Explain why the sky looks blue."
}Lantern creates a fresh CLI session and keeps it associated with this connection.
Session events
{ "type": "session.started", "session": { "id": "…", "state": "running" } }
{ "type": "turn.started", "sessionId": "…" }
{ "type": "output.delta", "sessionId": "…", "text": "Blue light…" }
{ "type": "turn.completed", "sessionId": "…", "status": "completed" }
{ "type": "session.state", "sessionId": "…", "state": "idle" }Build the application UI from these shared fields. Provider-specific messages remain available under raw for diagnostics and advanced integrations.
Continue and cancel
{ "type": "session.prompt", "sessionId": "…", "prompt": "Explain that more simply." }
{ "type": "session.cancel", "sessionId": "…" }
{ "type": "session.close", "sessionId": "…" }The creating connection owns its sessions. Closing the socket closes those provider processes as well, giving each WebSocket a clear conversation lifetime.
See the standalone WebSocket client example for a complete browser implementation.