npm.io
0.6.3 • Published yesterdayCLI

@sunbeam-za/lantern

Licence
Version
0.6.3
Deps
5
Size
474 kB
Vulns
0
Weekly
0

Lantern

Lantern lets a Next.js app use the Codex or Claude account already signed in on each user's Mac.

The user installs Lantern, approves your site, and keeps Lantern running while they use your app. Your AI SDK route sends supported requests to their Mac, where Lantern starts the signed-in CLI. The CLI calls its online service and streams the answer back to your interface.

Your app does not collect the user's provider login or model API key. Requests use the user's existing account and its normal limits. Prompts, attached images, and replies still pass through your app, Lantern's relay, and the provider.

Lantern is a good fit for interactive features where the user and their Mac are present. It is not an always-on backend for scheduled or unattended work.

Add Lantern to your app

The integration has three pieces: a server helper, a connection route, and a Connect Lantern button. Your existing AI route keeps its prompt and interface but uses Lantern's provider for the request. The user supplies the account and must keep their Mac awake, Lantern running, and the CLI used for the request signed in.

To let a coding agent add the integration for you, install Lantern's open Agent Skill:

npx skills add sunbeam-za/lantern --skill add-lantern

Then ask your agent: Add Lantern to this Next.js app. Reuse its existing AI route and put the connection control next to the feature. The skill works with Agent Skills-compatible tools including Codex, Claude Code, Cursor, and GitHub Copilot.

Install Lantern and the Vercel AI SDK:

npm install @sunbeam-za/lantern ai @ai-sdk/react

Generate a stable server secret:

openssl rand -base64 32

Save the output in your app's environment:

# .env.local
LANTERN_APP_SECRET=paste-the-generated-value-here

Create one server-only helper:

// lib/lantern.ts
import { createLanternApp } from "@sunbeam-za/lantern/next";

export const lantern = createLanternApp({
  appName: "Tiny Weather",
  secret: process.env.LANTERN_APP_SECRET!,
});

Expose its connection route:

// app/api/lantern/route.ts
import { lantern } from "@/lib/lantern";

export const { GET, POST, DELETE } = lantern;

Render the connect button:

import { LanternConnect, LanternProvider } from "@sunbeam-za/lantern/react";

<LanternProvider>
  <LanternConnect appName="Tiny Weather" />
  {children}
</LanternProvider>

On a public marketing page, you can show the integration without setting up a provider or connection state:

import {
  WorksWithLanternBadge,
  WorksWithLanternSection,
} from "@sunbeam-za/lantern/react";

<WorksWithLanternBadge />

<WorksWithLanternSection tone="dark" />

Both components include portable inline styles. Use className and style for the surrounding layout, replace the section copy and actions through props, or set href={null} on the badge when it should not link to Lantern.

Setup can make Codex, Claude, or both available. The button uses text support by default, chooses preferredModel when that CLI is available, and otherwise uses the first compatible CLI Lantern reports.

Then use Lantern in your AI SDK route:

// app/api/chat/route.ts
import { streamText } from "ai";
import { lantern } from "@/lib/lantern";

export async function POST(request: Request) {
  const local = lantern.server(request);
  const { prompt } = await request.json();

  return streamText({
    model: local.provider(local.model),
    prompt,
  }).toTextStreamResponse();
}

lantern.server(request) reads the browser's signed connection cookie and returns a Vercel AI SDK provider for the Lantern that user approved.

Supported today: text, streaming text, cancellation, and Codex-backed image generation and edits. Client-defined tools and structured response formats are not supported.

See the Vercel AI SDK guide for text, streaming, and image examples.

What each user does

Each user needs macOS 14+, Node.js 22+, and a signed-in Codex or Claude CLI. The Mac app guides them through setup, or they can run:

npx @sunbeam-za/lantern setup

Setup finds Codex and Claude, saves the user's choices, and asks whether to start Lantern.

When your app renders Connect Lantern, Lantern shows the app name and exact site address before the user approves it. Approval allows future supported requests from that address while Lantern is running and online; it is not a new prompt for every request.

Start Lantern again later with:

npx @sunbeam-za/lantern start

How a request travels

  1. The user approves your app in Lantern on their Mac.
  2. Your app stores the selected model and relay destination in an HttpOnly cookie signed by your server.
  3. lantern.server(request) sends each AI SDK call to the Mac stored in that cookie, where Lantern verifies the app and starts Codex or Claude.
  4. The reply comes back over the same path.

lantern.hiltonbarber.com is the relay. It uses the browser's saved connection to route each request to the user's Lantern and returns the response along the same path. Provider credentials stay in the CLI on the user's Mac; prompts, attached images, and responses pass through your app, the relay, and the provider service.

The browser keeps this connection for up to 30 days by default. Deleting it in one browser does not revoke the site's approval on the Mac. Stopping Lantern pauses every approved site. Running setup again and restarting Lantern clears all approvals.

Pairing and tunnel identity

The app has one Ed25519 signing identity derived from LANTERN_APP_SECRET. The user approves its public key for the app's exact origin.

Lantern on the Mac has a separate persisted Ed25519 identity in ~/.lantern/tunnel.json. It uses that identity when opening its outbound WebSocket. Pairing returns an opaque relay ticket for this identity, and your app places the ticket inside its HMAC-signed HttpOnly session.

The server provider gets its destination from that authenticated session. Request input contains the AI operation and model rather than a tunnel URL. Each execution opens a short-lived app-side WebSocket to the relay; only the local Lantern keeps a persistent outbound connection. The relay joins those two connections by ticket, while the local gateway—not the relay—verifies the app's signed execution envelope.

Supported CLIs

Lantern starts signed-in CLIs on the user's computer:

  • Codex App Server through codex app-server --stdio
  • Codex CLI through codex exec --json
  • Claude CLI through claude -p --output-format stream-json

Setup publishes one or both CLI connections as model names such as codex and claude. Lantern normalizes their process and event formats behind the provider used by your app.

Standard app sessions run in fresh temporary directories. Codex uses its read-only sandbox, while Claude starts in safe mode with an empty tool list. The CLIs still call their normal online services; Lantern does not run either model offline.

Lower-level interfaces

The server-side Vercel AI SDK provider is the main web-app interface. Lantern also exposes APIs for tools on the same Mac:

  • OpenAI-compatible GET /v1/models and POST /v1/chat/completions
  • Anthropic-compatible POST /v1/messages
  • OpenAI-compatible POST /v1/images/generations and POST /v1/images/edits
  • Streaming multi-turn sessions at WS /v1/socket
  • GET /v1/catalog for providers, model names, and availability
  • GET /health to check whether Lantern is running

Local scripts authenticate with the token in ~/.lantern/token. See the REST and WebSocket reference.

Configuration

Guided setup writes the local configuration and credentials with owner-only file permissions:

  • ~/.lantern/config.json: Codex and Claude connections, approved apps, and session settings
  • ~/.lantern/token: local REST and WebSocket credential
  • ~/.lantern/tunnel.json: stable outbound tunnel identity

The committed sunbeam.config.example.json documents the service and provider settings.

Develop

git clone https://github.com/sunbeam-za/lantern.git
cd lantern
npm install
cp sunbeam.config.example.json sunbeam.config.json
export SUNBEAM_TOKEN="$(openssl rand -base64 32)"
npm run dev

The hosted relay needs LANTERN_RELAY_SECRET and REDIS_URL. Local Lantern processes can point at a development relay with LANTERN_RELAY_URL.

npm test
npm run typecheck
npm run build
npm run site:dev
npm run site:build

npm run check runs backend types, tests, the gateway build, and the Next.js production build.

Keywords