Command line

Run Oatmilk on this computer

Keep your books, files and AI models on your own computer with oatmilk setup --local, then run it day to day.

20 minutes · Beginner

The CLI can set up a whole Oatmilk on your own computer and look after it for you. You choose Keep everything on this computer once. After that, oatmilk local, oatmilk status and oatmilk models do the rest.

To set it up by hand from a copy of Oatmilk's source instead, follow Run it on your computer.

What you get

  • All of Oatmilk on this computer. The web app, Ask AI and its 16 agents, your books, your files and the five-minute background jobs all run here, in Docker.
  • Oatmilk in your browser at https://oatmilk.localhost. It uses the usual web ports, 443 and 80, so the address has no port number. oatmilk local open opens it.
  • The terminal app on the same books. oatmilk opens them, already signed in.
  • No account anywhere else. Your account lives on this computer. Its email is your computer's user name at oatmilk.localhost, such as ada@oatmilk.localhost. The terminal signs itself in, and setup makes you a password for the browser.
  • It works with the Wi-Fi off. After the first setup, it needs no internet. See Working offline.

What it needs

  • Docker. Docker Desktop on macOS and Windows, or Docker Engine with the Compose plugin on Linux, with Compose 2.20 or newer. Give Docker at least 4 GB of memory.
  • Bun, which runs Oatmilk's own setup commands: curl -fsSL https://bun.sh/install | bash.
  • Git, to download Oatmilk's source. If you already have a copy, oatmilk setup --source <folder> uses it instead.
  • Ollama or LM Studio, to run the AI models.
  • Memory. About 4 GB for Oatmilk, and more for the models. 16 GB is good for real books. With less than 14 GB, setup picks smaller models, which are slower and less accurate.
  • Disk. About 15 GB for Oatmilk, and a few GB for each model.
  • The internet, the first time, to download Oatmilk's source, build it and download the models.

The setup screens check for Docker, Bun and git before they ask anything, and say how to get what's missing. They don't check memory or disk.

Set it up

Run oatmilk. The first time, it asks how you want to use Oatmilk. Choose Keep everything on this computer, then:

  1. It checks this computer. If something is missing, get it and press ⏎ to check again.
  2. Choose the model server: Ollama or LM Studio. If one is installed but not running, s starts it.
  3. Check the models. Setup picks them for you. ← → changes one, and t checks that the chat model answers.
  4. Type your name, then your company's name. That's all it asks about you.
  5. Take a last look. ⏎ sets it up.

Each question shows where you are, like 2/5. oatmilk setup opens these screens again later.

Without the screens

Shell
oatmilk setup --local                                               # asks only before it downloads
oatmilk setup --local --name "Ada Lovelace" --company "Acme" --yes  # asks nothing

oatmilk setup --local uses the first model server it finds running, or the one --models names. In a terminal, it asks before it downloads Oatmilk's source or any models; --yes downloads them without asking. Without --name and --company, it uses your computer's user name and "My company".

What setup does

Setup shows each step as it goes:

StepWhat happens
Check Docker and BunDocker is running, and Bun is installed
Find OatmilkIt uses a copy of Oatmilk's source on this computer, or downloads the newest one with git
Prepare the modelsThe model server answers, and Ollama downloads any models it's missing
Write the settingsIt writes Oatmilk's settings, and keeps any secrets from before
Install packagesOnly when Oatmilk runs from source
Start OatmilkDocker builds Oatmilk and starts it
Wait until it answersIt waits until https://oatmilk.localhost answers
Let Oatmilk reach the modelsOatmilk, inside Docker, can reach your model server
Make your accountIt makes your account, with a password it makes up
Sign this terminal inIt signs the terminal in with that password
Open your companyIt opens your company, or makes it

The first start takes about 10 minutes, while Docker builds Oatmilk. Then setup says Oatmilk is ready and shows your password for the browser. ⏎ opens the app. oatmilk local password shows the password again.

If Oatmilk can't reach your model server, setup still finishes, and AI waits until you fix it (see If something goes wrong).

In the setup screens, ⌃C stops setup and everything it started, such as Docker's build. What finished stays done. Press r to run it again with your answers kept; the finished steps go fast.

From source. To work on Oatmilk itself, run it with bun run dev from a copy of its source instead of Docker: oatmilk setup --local --runtime source, or How it runs under More options › Choose for each part. It's then at http://localhost:3000, and it needs Node.js 24.

Open it in your browser

oatmilk local open opens https://oatmilk.localhost. Sign in with your email and the password setup showed you.

The first time, your browser warns about the certificate. Oatmilk makes its own, and your computer doesn't know it yet. Trust it once:

Shell
cd "$(oatmilk local path)"
bun run self-host cert      # saves the certificate and prints the command that trusts it

Run the command it prints, then restart your browser. Trust the local certificate has the command for each system, and Firefox's own list. The terminal doesn't need this: it trusts Oatmilk's certificate by itself.

Choose what goes online

Everything stays on this computer until you say otherwise. Oatmilk has eight parts, and each one can stay here, use a cloud service of your own, or be off:

PartThis computerYour cloudOff
Sign-in: who can open your booksAn account kept on this computerClerk, a hosted sign-in service—
Books: transactions, invoices, people, historyPostgreSQL and Redis on this computerA PostgreSQL you own: Supabase, Neon, RDS…—
Files: statements, receipts and documentsKept on this computerAn S3-compatible bucket: S3, R2, B2, MinIO…—
Ask AI & agents: chat, the 16 agents and their toolsOllama or LM StudioVercel AI GatewayNo Ask AI
Classifiers: categories, matching, mail routingA small model on this computerTypeSafe's Jev, through Vercel AI GatewayYou sort everything yourself
Reading documents: receipts, statements and PDFsA vision model on this computerVercel AI GatewayDocuments are stored, not read
Email: invoices, invitations, reminders—Resend, with an API key and a domainShare links yourself
Web research: looking things up for you—Tavily, with an API keyOff

Email and web research start off, and the rest start on this computer. Your cloud means services you own, not Oatmilk Cloud.

In the setup screens, choose More options, then Choose for each part. ← → changes a part, and the top of the screen says how local it is.

From a command line, setup starts from everything here. --cloud-for moves parts to your cloud, and --off-for turns them off. In commands, the parts are account, database, files, agents, classifiers, documents, email and web, in the same order; separate several with commas.

Shell
oatmilk setup --local --cloud-for agents --yes      # Ask AI and the agents in your cloud: 85% local
oatmilk setup --local --off-for classifiers --yes   # you sort everything yourself: still 100% local

A part in your cloud needs its keys. The setup screens ask for them. oatmilk setup --local reads them from the environment, and keeps the ones it saved before when you leave them out:

PartSettings
Sign-inNEXT_PUBLIC_CLERK_PUBLISHABLE_KEY, CLERK_SECRET_KEY
BooksOATMILK_DATABASE_URL
FilesOATMILK_S3_BUCKET, OATMILK_S3_REGION, OATMILK_S3_ACCESS_KEY_ID, OATMILK_S3_SECRET_ACCESS_KEY, and OATMILK_S3_ENDPOINT outside AWS
Ask AI, classifiers and reading documentsAI_GATEWAY_API_KEY
EmailRESEND_API_KEY, OATMILK_EMAIL_DOMAIN
Web researchTAVILY_API_KEY

In Docker, OATMILK_REDIS_URL uses your own Redis instead of the one on this computer. Keys are kept only in the local Oatmilk's own settings file.

Changing where your books or files go doesn't move what's already there. Back them up first with oatmilk local backup.

See how local it is

oatmilk status shows where you stand. It starts with how local it is, like 100% local and "Everything stays on this computer". Then it lists where each part runs, whether Oatmilk answers, the models, where Ask AI thinks and who's signed in. --json prints the same for scripts, and the app shows it in Settings › Privacy.

Each part counts for a share: books 25%; sign-in, files and Ask AI 15% each; classifiers and reading documents 10% each; email and web research 5% each. A part that's off counts as local, because it sends nothing anywhere.

Your AI models

Setup picks these models for your computer:

JobOllamaLM Studio
Ask AI, the agents and reading documentsqwen3.5:9b, or qwen3.5:4b with less than 14 GB of memoryqwen/qwen3.5-9b, or qwen/qwen3.5-4b with less than 14 GB
Classifierstev1, a decision model, on Ollama 0.35 or newer; before that, qwen3.5:4bqwen/qwen3.5-4b

If you don't have the chat model but have another one that calls tools, setup uses yours. On Ollama, setup downloads the models you don't have yet. On LM Studio, download them yourself first, with lms get or LM Studio's Discover tab.

Shell
oatmilk models                                   # Ollama and LM Studio here, their models, and what Oatmilk uses
oatmilk models test                              # asks each model to answer
oatmilk models pull qwen3.5:4b                   # downloads a model into Ollama
oatmilk models start                             # starts the model server Oatmilk uses; or name one: ollama, lmstudio
oatmilk models use --model qwen3.5:4b --restart  # uses another model, then restarts Oatmilk
  • models test waits for each model's first answer. That loads the model into memory, which can take minutes on a laptop.
  • When models start starts Ollama, it gives it room for long statements, and on Linux lets Docker reach it.
  • models use checks that the models are on the server first. --models lmstudio moves to LM Studio. Without --restart, Oatmilk uses the new models after oatmilk local restart.

models test only checks that each model answers. To see how well your models do Oatmilk's own work, run oatmilk models eval; Check your models explains it.

Every day

Run oatmilk to open the app. If your local Oatmilk is stopped, it starts it and signs you in first; --no-start leaves it stopped. oatmilk local looks after it:

CommandDoes
oatmilk local startStarts it, waits until it answers, and signs the terminal in
oatmilk local stopStops it. Your data stays.
oatmilk local restartStops it and starts it again, for example after oatmilk models use
oatmilk local statusSays whether it's running, its address, and whether it runs in Docker or from source. oatmilk local alone does the same.
oatmilk local logsShows what it's doing. In Docker, the last 200 lines, then it keeps following until ⌃C; add a service, such as app or db, for just that one. From source, the last 200 lines of the dev server's log.
oatmilk local openOpens it in your browser, and says which email to sign in with
oatmilk local passwordShows your email and password for the browser. --reset makes a new password and signs out every browser.
oatmilk local backupSaves the database and files to self-host/backups. Docker only.
oatmilk local wipeDeletes every company, account, transaction and file in it, after you type wipe
oatmilk local pathPrints the folder of Oatmilk's source that runs it, which holds its settings and backups

In Docker, a running Oatmilk starts again by itself when Docker does, for example after you restart your computer. --local makes any command use this Oatmilk, starting it if it's stopped, and --cloud uses Oatmilk Cloud.

Working offline

Once it's set up, Oatmilk runs with the Wi-Fi off. These keep working:

  • Reading and sorting statements, receipts and documents, with your models.
  • Ask AI.
  • The five-minute background jobs.
  • Team members, roles, invitations and outside accountants. With email off, copy an invitation link from Settings › Team and send it yourself.
  • The REST API, API keys, MCP for AI apps on the same computer or network, and the terminal app.
  • These docs, at https://oatmilk.localhost/docs.

These wait for the internet, and stay off until you turn them on:

  • live bank feeds and payouts (Wise), Stripe, and data connections (Notion, Google Drive, Microsoft);
  • email in and out, hosted AI models (Vercel AI Gateway), web research and Discord.

With everything on this computer, the CLI never looks for a new version by itself. --offline, or OATMILK_OFFLINE=1, makes it refuse any Oatmilk on the internet.

Update, back up, move or start over

Update

oatmilk update installs the newest CLI. It doesn't change the Oatmilk it runs. To update Oatmilk itself, back it up, get its newest source and restart it:

Shell
oatmilk local backup
cd "$(oatmilk local path)"
git pull
bun install
oatmilk local restart      # builds the new version; database changes apply on the way

From source, oatmilk local backup doesn't work, so keep a copy with oatmilk export first. Then start its database again yourself before Oatmilk (see the known limits):

From source
oatmilk local stop
cd "$(oatmilk local path)"
git pull
bun install
bun run self-host dev      # starts the database, Redis and file storage, and applies database changes
oatmilk local start

Back up

Shell
oatmilk local backup       # the database and files, into self-host/backups
oatmilk export             # every record and file of your company, into a folder

oatmilk local backup is for Oatmilk in Docker, while it's running. It saves two files, readable only by you, in self-host/backups in the folder oatmilk local path prints. Restoring needs the same self-host/.env from that folder, so keep a copy of it with the backups, off this computer. If your books or files are in your cloud, use that service's backups instead.

oatmilk export is for administrators, and works from source too: a ZIP with every record, and every file. Restore puts a backup back.

Move to another computer

Back up, then copy the backups and self-host/.env to the other computer. There, restore them into an Oatmilk that uses that same self-host/.env, as Restore shows. To move your books to Oatmilk Cloud or a server instead, use oatmilk migrate: see Moving between your computer and the cloud.

Start over

Shell
oatmilk local wipe         # deletes every company, account and file in the local Oatmilk
oatmilk setup --local      # sets it up again, empty

oatmilk local wipe keeps Oatmilk's settings, its certificate and your backups. oatmilk wipe instead removes every sign-in, the setup, Ask AI's message history and the cache from this computer; add --local-data to delete the local Oatmilk's data too. Both ask you to type wipe first. Neither deletes the copy of Oatmilk's source or the backups in it, so run oatmilk local path first to see where they are.

If something goes wrong

ProblemFix
"Start Docker" before setup's questions, or "Oatmilk didn't start"Docker isn't running. Open Docker Desktop, or on Linux run sudo systemctl start docker. Then press ⏎ to check again, or run oatmilk local start.
"Oatmilk didn't start", and Docker says port 443 or 80 is takenAnother program uses that port, and setup always uses 443 and 80. Stop that program, then run oatmilk local start. To use other ports, set Oatmilk up by hand with Run it on your computer.
The browser warns about the certificateTrust Oatmilk's certificate once, as in Open it in your browser.
The terminal shows a certificate error, or never sees Oatmilk answerYour Node.js can't trust Oatmilk's certificate by itself. Update to Node.js 24.5 or newer (or 22.19 or newer on Node.js 22), or set NODE_EXTRA_CA_CERTS to self-host/oatmilk-local-ca.crt in the folder oatmilk local path prints.
"Ollama isn't answering", or "Neither Ollama nor LM Studio is running"Start it with oatmilk models start (or oatmilk models start lmstudio), then check with oatmilk models test.
A model "isn't on your model server yet"On Ollama: oatmilk models pull <name>. On LM Studio: lms get <name>, or its Discover tab. Then try again.
"Oatmilk can't reach your model server from Docker yet"On Linux, Ollama must listen on every address: start it with OLLAMA_HOST=0.0.0.0 ollama serve, or let oatmilk models start start it. In LM Studio, turn on Serve on Local Network. AI waits until then.
Answers are slowA first answer loads the model into memory and can take minutes on a laptop. For faster answers, add OATMILK_LOCAL_REASONING=none to self-host/.env in the folder oatmilk local path prints, then run oatmilk local restart.
Out of memory or diskGive Docker at least 4 GB of memory in Docker Desktop's settings, and keep about 15 GB free for Oatmilk, plus a few GB for each model. On a small computer, use a 4B model: oatmilk models pull qwen3.5:4b, then oatmilk models use --model qwen3.5:4b --restart.
Setup stopped partwayIt says which step stopped and what to do. Fix that, then press r, or run oatmilk setup --local again. What finished stays done.
"Oatmilk didn't answer at https://oatmilk.localhost in time"oatmilk local logs shows what it's doing. Fix what it says, then run oatmilk local start.
"The download of Oatmilk's source failed", or "the download didn't work"Setup downloads Oatmilk's source from GitHub, and the source isn't public yet, so only people with access to it can download it. If you have a copy, use it: oatmilk setup --source <folder>.
You use your own Redis, and oatmilk models use moved Oatmilk to the one on this computerA known limit: in Docker, models use writes the settings again with the Redis on this computer. To change models, run the oatmilk setup --local you set it up with again, with OATMILK_REDIS_URL set and --model for the new model.
From source, Oatmilk can't open your books after oatmilk local restartA known limit: from source, stopping Oatmilk also stops its database, Redis and file storage, and starting it doesn't start them again. oatmilk local stop and then start, and oatmilk models use --restart, do the same. In the folder oatmilk local path prints, run bun run self-host dev, then oatmilk local start. Your data is kept.

Update, back up and troubleshoot has more fixes for Oatmilk in Docker.