Self-hosting

Develop Oatmilk locally

Run Oatmilk from source with hot reload, local data services and, if you like, local AI models.

15 minutes · Intermediate

To change Oatmilk itself, run it from source with bun run dev. One command starts the data services it needs in Docker, so you don't need any cloud accounts to begin.

1. Install what it needs

  • Node.js 24 and Bun 1.3.14, the versions package.json pins.
  • Docker with Compose 2.20 or newer, for the data services.

2. Start the data services

Shell
git clone https://github.com/AGI-Ventures-Canada/oatmilk.git && cd oatmilk
bun install
bun run self-host dev

self-host dev starts PostgreSQL, Redis, the database API and file storage in Docker, applies every migration, and writes .env.development.local so bun run dev uses them and keeps accounts locally.

  • Anyone can make an account on this install.
  • Your own .env.local is left alone, but .env.development.local wins over it. Delete .env.development.local to go back to your own settings.

3. Add AI models

Add one of these to .env.local:

.env.local, with Ollama
OATMILK_MODEL_PROVIDER=ollama
OATMILK_LOCAL_MODEL=qwen3.5:9b
OATMILK_LOCAL_CLASSIFIER_MODEL=tev1
OATMILK_LOCAL_CLASSIFIER_API=systemone
.env.local, with hosted models
AI_GATEWAY_API_KEY=…

Use local AI models covers LM Studio and other servers. Here Oatmilk runs on your computer itself, so the default addresses, http://localhost:11434/v1 and http://localhost:1234/v1, work as they are.

4. Start Oatmilk

Shell
bun run dev

Open <http://localhost:3000>, make an account and create your company. Changes to the code reload as you save.

5. Use your tools against it

  • API: create a key in Developers › API keys (it starts with oat_test_), and send requests to http://localhost:3000/api/v1/accounting/<action>.
  • Docs: http://localhost:3000/docs uses your local address in every example.
  • MCP: http://localhost:3000/api/mcp.
  • CLI: oatmilk login --host localhost:3000, or from source: bun packages/cli/src/main.ts --host localhost:3000.

Stop

Shell
bun run self-host dev down    # stops the data services; their data stays

bun run dev keeps using them until you delete .env.development.local.

Before you send a change

Shell
bun run test
bun run typecheck
bun run lint

CONTRIBUTING.md in the repository lists the full checks.