Command line

Sign in and choose a company

Connect the CLI to the hosted Oatmilk or your own, with your browser, another device or an API key.

The CLI signs in the way an AI app does: you approve it in your browser, and it acts as you. Your role in each company still decides what it can see and do. For scripts and CI, an API key works instead.

1. Choose the Oatmilk to connect to

Without --host, the CLI talks to the hosted Oatmilk at https://app.getoatmilk.com. For any other Oatmilk, pass its address once when you sign in; the CLI remembers it for later commands.

OatmilkAddress
The hosted OatmilkNothing to add
Your own, on this computer--host https://oatmilk.localhost
Your own, on a server--host https://books.example.com
A development server from bun run dev--host localhost:3000

The address is read from --host first, then the OATMILK_HOST environment variable, then the last address you signed in to. Addresses must use https; plain http is allowed only for localhost.

2. Sign in with your browser

Shell
oatmilk login
# or, for your own Oatmilk:
oatmilk login --host https://books.example.com
  1. Your browser opens Oatmilk's sign-in page. Sign in if you aren't already.
  2. Oatmilk shows what the CLI asks for. Choose Allow.
  3. The page says you're signed in. Go back to the terminal: it shows your email, company and role.

The browser sends the sign-in back to a one-time address on your own computer (http://localhost:<port>/callback), so nothing to copy. If no browser opens, the CLI prints the address to open; --no-browser or OATMILK_NO_BROWSER=1 always prints it instead.

Sign in on another device

Over SSH, in a container, or on a machine without a browser:

Shell
oatmilk login --device
  1. The CLI prints an address. Open it on any device: your laptop or your phone.
  2. Sign in and choose Allow.
  3. Oatmilk shows a code with a Copy code button. Paste it into the terminal.

The code only works for the terminal that asked for it, and only once.

Sign in with an API key

An API key belongs to one company and keeps exactly the permissions it was given, so it suits scripts, CI and shared machines. Create one in Developers › API keys in Oatmilk, then:

Shell
oatmilk login --api-key                  # asks for the key without showing it
echo "$KEY" | oatmilk login --api-key    # or pipe it in

For a single command or a CI job, skip login and set the key in the environment. OATMILK_API_KEY and OATMILK_TOKEN (an OAuth access token) win over a saved sign-in.

Shell
OATMILK_API_KEY=oat_live_… oatmilk whoami

3. Check who you are

Shell
oatmilk whoami
oatmilk whoami --json

It shows your email, the company, your role, the address and how you signed in. With an API key it also lists the key's permissions.

4. Choose a company

A browser sign-in can open every company you belong to. The CLI works in one at a time, and oatmilk whoami shows which.

Shell
oatmilk orgs                      # the companies you can open; ● marks the current one
oatmilk orgs use "Contoso"        # switch by name or ID
oatmilk api entries.list --org org_2abc…   # one command in another company

OATMILK_ORG sets the company for every command. An API key always works in its own company, so orgs use asks you to sign in with the browser instead.

Your own Oatmilk

A self-hosted Oatmilk signs you in through its own accounts, with the same steps. Two things differ on this computer's *.localhost address:

  • The certificate. Oatmilk's local HTTPS certificate comes from its own certificate authority, which Node.js doesn't trust by default. Point NODE_EXTRA_CA_CERTS at the file bun run self-host cert saves, in every terminal that runs the CLI:
Shell
export NODE_EXTRA_CA_CERTS="$HOME/oatmilk/self-host/oatmilk-local-ca.crt"   # where your Oatmilk checkout is
oatmilk login --host https://oatmilk.localhost
  • The name. *.localhost names always mean this computer. The CLI knows that without an /etc/hosts entry.

A server with a real domain and a Let's Encrypt certificate needs neither.

Sign out

Shell
oatmilk logout                     # this address
oatmilk logout --all               # every address you signed in to

Signing out revokes the browser sign-in, so the saved token stops working everywhere. To stop an API key, delete it in Developers › API keys.

Where sign-ins are saved

Sign-ins live in credentials.json in ~/.config/oatmilk ($XDG_CONFIG_HOME/oatmilk when that is set, %APPDATA%\oatmilk on Windows). Only your user can read it. OATMILK_CONFIG_DIR moves it, for example to keep a separate sign-in per project. Browser sign-ins refresh themselves; run oatmilk login again if one stops working.

When it goes wrong

Message or exit codeWhat to do
Exit code 3, "You're not signed in"Run oatmilk login, or set OATMILK_API_KEY.
"Oatmilk addresses must use https"Use https://…. Only localhost may use http.
"That isn't an Oatmilk API key"Keys start with oat_. Copy the whole key again.
A certificate error on *.localhostSet NODE_EXTRA_CA_CERTS as shown in Your own Oatmilk.
Exit code 4, not allowedYour role, or the key's permissions, don't allow that action. Check with oatmilk whoami.
The browser never comes backCancel with Ctrl+C and use oatmilk login --device.