AI for your apps
Berth can give any app an LLM: small models running on the Mac itself, cloud models with keys you add once, or both. Apps reach all of them through one gateway in Berth using the OpenAI or Anthropic SDK they'd use anyway, and they never see your provider keys.
Set it up once
berth ai:setup
This installs Ollama with Homebrew and starts it with
the Mac (it asks first), then downloads a model that fits: qwen3:8b with
16 GB of memory or more, qwen3:4b below that. Pick another with
--model gemma3:4b, or skip local models with --cloud-only. Local models
run on the Mac's GPU, outside the app containers, which can't use it.
Add whichever cloud providers you want (the key prompt is hidden):
berth ai:key anthropic # also openai, gemini, openrouter, groq, mistral
berth ai:key together --url https://api.together.xyz/v1 # anything OpenAI-compatible
Give an app access
berth ai:enable myapp
The app gets its own token and the usual variables, and redeploys:
| Variable | Value |
|---|---|
OPENAI_BASE_URL |
http://<gateway>:7790/v1 |
OPENAI_API_KEY |
berth_ai_… (this app's token) |
ANTHROPIC_BASE_URL |
http://<gateway>:7790/anthropic |
ANTHROPIC_API_KEY |
the same token |
The official SDKs read those by themselves, so there's nothing Berth-specific in your code:
import OpenAI from "openai";
const client = new OpenAI(); // reads OPENAI_BASE_URL and OPENAI_API_KEY
const reply = await client.chat.completions.create({
model: "default",
messages: [{ role: "user", content: "Hello!" }],
});
Python's openai and anthropic packages work the same way. Every provider
speaks the OpenAI format (/v1/chat/completions, /v1/embeddings,
/v1/models), and Claude models also speak Anthropic's own API, for tools,
prompt caching and extended thinking.
Choosing models
Apps ask for a model by name, like local/qwen3:8b or
anthropic/claude-sonnet-5-5, or by an alias you set up once for every
app:
berth ai:alias smart anthropic/claude-sonnet-5-5
berth ai:alias fast groq/llama-3.3-70b-versatile
berth ai:models # aliases, local models, providers
berth ai:pull nomic-embed-text # another local model, e.g. for embeddings
ai:setup points default at the local model. I'd write apps against
aliases ("default", "smart") rather than model names: change what an
alias points at and every app picks it up immediately, no redeploy.
Limits and usage
berth ai:enable myapp --models default,smart --monthly-tokens 2000000 --rpm 60
berth ai:usage # requests and tokens per app and model this month
berth ai:status # what's running, what's loaded, each app's usage
berth ai:disable myapp # revoke its token
--models takes aliases, provider/model or provider/*. An app over a
limit gets a 429 that says which limit and how to raise it. Usage records
tokens and timings, never prompts or replies.
Dev versions of an AI app get their own token that only
reaches local models, so an agent testing changes can't run up a cloud bill
(berth ai:enable myapp-dev --models 'local/*,smart' lifts that).
Memory
A loaded local model takes real memory: about 5 GB for an 8B model, 2.5 GB
for a 4B one. Ollama lets go of it after 5 idle minutes. berth status shows
what's loaded, counts it, and warns when apps, databases and the model
together get close to the Mac's RAM. On an 8 GB Mac, use a cloud provider (or
a really small model).
The gateway listens on port 7790 on the containers' network, and only
containers on this Mac can reach it. To change the port, set ai_port in
~/.berth/config.json and run berth reload. To use Ollama on another
machine, set ollama_url in ~/.berth/ai/config.json.