Documentation

Everything about Mav.

Install your own everyday assistant, and get the most out of it.

Installation

With Docker

On any machine with Docker Compose — a NAS, a home server, a Raspberry Pi 4/5 (images for amd64 and arm64):

git clone https://github.com/SoaOaoS/mav.git && cd mav
cp .env.example .env    # optional: port, password, time zone, model
docker compose up -d

Open http://<your machine>:8787, choose a password, and the welcome screen connects your model and sets up your first routines. Update with docker compose pull && docker compose up -d. Ollama on the same machine is at http://host.docker.internal:11434/v1.

With the installer

On a Linux machine with systemd — Debian, Ubuntu, Arch (Omarchy, Manjaro…) or Fedora. One command:

curl -fsSL https://raw.githubusercontent.com/SoaOaoS/mav/main/get.sh | sudo bash

or, from a clone:

git clone https://github.com/SoaOaoS/mav.git && cd mav && sudo ./install.sh

The setup asks only what it must:

  1. Your model provider (arrow keys), your API key — checked on the spot — and the model, picked from the provider's own list. Or Set it up later from the web app.
  2. Optionally, a contact email for push notifications.

Everything else gets sensible defaults; answer yes to Advanced settings? to change the system user, the ports or the quiet hours. Each step shows a spinner; the details go to /var/log/mav-install.log. At the end, open the address it prints.

Installer options

sudo ./install.sh --update     # update, keep the settings
sudo ./install.sh --dry-run    # show what would happen, change nothing
sudo ./install.sh --uninstall  # remove the services (data is kept)
sudo ./install.sh --yes        # unattended, see below

Unattended: MAV_PROVIDER (anthropic, openai, ollama, ollama-cloud-api, openrouter), MAV_PROVIDER_APIKEY, MAV_OPENCODE_MODEL, optionally MAV_PROVIDER_BASEURL and MAV_VAPID_EMAIL. Without a provider, the model is left to set up in the web app.

Updating

When a new version is out, the web app shows Update to vX.Y.Z in the sidebar (and in Settings → General): it shows what's new and installs it for you. From a terminal:

mav update            # install the latest release, keep everything
mav update --check    # only tell whether one is available
mav update --local    # reinstall the local copy (offline)
mav status            # what's running, the address, the model
mav doctor            # check everything, with a hint for each problem
mav restart [engine|worker|web]
mav logs [engine|worker|web|install] [-n 50]
mav backup            # memory, routines, settings → /var/backups/mav/
mav password          # set or reset the web app password
mav reconfigure       # Update / Change the model / Reconfigure / Uninstall

Versions follow semantic versioning: every change merged into main is released automatically, as a major (breaking change), minor (new feature) or patch version, depending on its commit messages. What changed in each version is on the releases page (latest: see releases).

Coming from the Telegram version? Telegram support was removed. Older versions of mav update did not download anything, so run the one-line installer once and choose Update. It replaces the mav-bot service with mav-worker and keeps your memory (now in Postgres — the old memory.json is imported automatically), your routines, your model and your settings. Your existing agent files are left untouched; the new everyday helpers are added next to them.

Backup & restore

Settings → General → Backup → Download saves everything in one .tar.gz: memory (every table), routines, chats, helpers, connections, settings, API keys and the password. It works the same with Docker and with the installer, and is how you move Mav to another machine.

Restore… asks for your password again, checks the file (only Mav's own folders, no unsafe path), keeps a copy of the current state on the server (bot/backups/, the last three), replaces the memory in one transaction, then the files, and restarts the engine.

A backup holds your API keys and password hash: keep it somewhere private. From a terminal, mav backup still works on an installer install.

Moving to Docker

Installed with the installer and want Docker instead? One script moves everything: chats, memory, routines, helpers, connections, your model and API keys, your password and the notification keys. Run it on the same machine, from a clone:

git clone https://github.com/SoaOaoS/mav.git && cd mav
sudo ./scripts/migrate-to-docker.sh            # asks before changing anything
sudo ./scripts/migrate-to-docker.sh --dry-run  # only show what it would move

What it does

  1. Saves a backup of the memory database to /var/backups/mav/pre-docker-….sql.gz.
  2. Copies the engine settings and chat history (~/.config/opencode, ~/.local/share/opencode), the files Mav shared with you, your routines and keys into the Docker data volume. Paths are rewritten for the container, and services on the machine itself (localhost, like Ollama) become host.docker.internal.
  3. Writes .env so the stack reuses the same database (the mav_pgdata volume, with its password). Your memory is not copied: it is the same one.
  4. Stops and disables the systemd services, then starts the Docker stack on the same port. Sign in with your usual password.
Nothing is deleted. The old folders, services and /etc/mav*.env stay in place, and the script prints the three commands to go back. Once you are happy, you can remove the old install folder by hand. Do not run mav uninstall after the move: use docker compose down instead.

Push notifications

The installer serves the app over HTTPS itself; the Docker stack serves plain HTTP on port 8787. Phones only allow push notifications over HTTPS, so put a reverse proxy in front (Caddy, Traefik, Nginx Proxy Manager or tailscale serve), then allow notifications again on each device.

By hand

If your database user, name or volume is not the default, the script stops and points here. The pieces to move are the same:

Installer installDocker volume mav-data
~/.config/opencode/data/home/.config/opencode
~/.local/share/opencode/data/home/.local/share/opencode
~/workspace/mav-files/data/home/workspace/mav-files
~/bot (data files, not the .py)/data/bot
/etc/mav-server.env/data/config/server.env
OPENCODE_MODEL from /etc/mav.env/data/config/mav.env
The databasemav backup, then restore into the postgres service

Requirements

  • Docker: any 64-bit Linux machine, NAS or Raspberry Pi 4/5 with Docker Compose v2.
  • Installer: Debian 12+, Ubuntu 22.04+, Arch-based systems (Omarchy, Manjaro, EndeavourOS…) or Fedora, with systemd and root access. The installer uses apt, pacman or dnf accordingly.
  • About 400 MB of RAM for Mav itself (measured at rest: engine 258 MB, Postgres 43 MB, web app 35 MB, worker 29 MB) and 1.2 GB of disk for the images — more if you run models locally with Ollama.
  • An API key from a model provider, or an Ollama server.

The installer brings the rest: Python, Docker (for Postgres) and the opencode agent engine.

Raspberry Pi & ARM

Mav runs on 64-bit ARM: every change is tested on a native arm64 machine (the whole Docker stack, and the installer), and the release images are published for arm64. A Raspberry Pi 4 or 5 runs it comfortably: at rest the four containers use about 365 MB of memory together.

  • Use a 64-bit system (Raspberry Pi OS Lite 64-bit, Ubuntu Server arm64).
  • Put the data on an SSD rather than the SD card: Postgres writes often.
  • Install with Docker (above); docker compose pull fetches the arm64 images.

Which model?

MachineRecommended
Pi 4 / Pi 5, 4 GB A cloud model (Anthropic, OpenAI, OpenRouter…). The Pi only runs Mav; answers are as fast as on a big server.
Pi 5, 8–16 GB A cloud model for chats, or a small local model with tool calling through Ollama (a 1.5B–3B model such as Qwen 2.5 or Llama 3.2) for privacy, accepting slow answers: on a CPU, the first word can take tens of seconds. Use it as the Model for background work (titles, memory) to keep that work at home.
Pi + a PC with a GPU on the network Run Ollama on the PC and point Mav at it (http://<pc>:11434/v1): local and quick.

Each helper only receives the tools it uses (see Speed), which keeps prompts small: that matters most on slow hardware. The Speed card shows what your machine actually does.

On your phone

Mav is a web app you can install like a native one, with push notifications. Browsers only allow that over HTTPS, so Mav serves itself over HTTPS with a private certificate:

  1. On the phone, open https://<your-mav>/certs/ca.cer and trust the certificate.
  2. Open https://<your-mav>/, then Add to Home Screen.
  3. Turn on notifications (the bell, or Settings → General).

On your first visit Mav asks you to choose a password; every device then signs in once (for 30 days). Forgot it? Run sudo mav password on the machine. To reach Mav away from home, prefer a VPN such as Tailscale or WireGuard.

Family accounts

One Mav can serve a whole household. In Settings → General → Family, the owner adds a person with a name and a password. From then on, the sign-in screen asks for a name too; the owner can leave it empty.

  • Each person has their own Mav: chats, memory, routines, watched pages, notifications and phones. Nobody sees anyone else's, and Mav's memory of one person never reaches another.
  • The owner keeps the keys: the model, connections, helpers, email, calendars, channels, usage, backup and updates. Members don't see those settings at all.
  • Removing a person signs them out and erases their data. Files the assistant creates live in one shared folder.

Chat

The chat is the main screen. A new chat shows a greeting, the message box, four everyday suggestions and For you — your latest routine reports and alerts. Chats get a short title on their own after the first answer and are grouped by day; click a title to rename it, or pin, summarise, download or delete a chat from its header. You can attach files, dictate, and have answers read aloud.

Commands

/remember <fact> Save something about you to memory
/routine <what, when> Create a routine (pre-filled from your words)
/watch <url or topic> Keep an eye on a page, a price or a topic
/helper <name> Switch who you talk to
/new · /rename · /summary · /export · /help Chat actions

Shortcuts: ⌘K search and commands, Alt N new chat, / focus the message box, Esc stop an answer.

Helpers

You talk to the Assistant by default. It answers directly, and calls in a specialist when that helps:

Researcher looks things up on the web, checks facts, compares options — with sources
Writer emails, messages, posts and letters in the right tone
Planner days, trips, projects, to-do lists
Money budgets, purchases, subscriptions, comparing offers

You can also talk to one directly: pick it on the message box or in the chat header. Who answers is always shown — on the message box, in the header and on each answer — and each chat remembers its helper. Create your own (a coach, a tutor…) in Settings → Helpers. Each helper is a Markdown file in ~/.config/opencode/agent/.

Memory

Mav keeps two kinds of memory, stored in Postgres on your machine:

  • About you — facts like "vegetarian, lives in Lyon". Always recalled when a chat starts. Add them on the Memory page or with /remember.
  • From past chats — every question and answer, recalled when relevant to a new chat (full-text search with a gentle preference for recent ones).

Answers that used memory say so ("Used 3 things from memory"). You can delete any item, or clear chat memory entirely, from the Memory page.

Daily briefing

One short message to start the day: the weather where you live, what happened since yesterday (alerts and routine reports), what needs you (drafts waiting for approval) and something from your interests. Turn it on in Settings → General → Daily briefing and pick the time; it arrives as a notification and in its own chat, where you can ask follow-up questions. Anytime: Brief me on the new-chat screen, or /brief.

Usage & budget

Settings → Usage shows what Mav cost this month (as your provider bills it), how many answers and tokens, a 30-day chart, and the split between chats, routines and background work.

  • Monthly budget — Warn notifies you at 80 % and 100 %; Stop also pauses new answers once it is reached, until you raise it or the month ends.
  • Model for background work — titles, memory and summaries run on this model (a small "mini" or "haiku" model is plenty), so they cost a fraction of your main one.

A local model (Ollama) costs nothing here.

Speed

Every answer shows how long it took next to its buttons: time to the first word, the whole answer, the number of steps and how much prompt the model read (and how much of it came from the provider's cache). Settings → Usage → Speed gives the typical answer over 30 days (medians, so one slow web search does not hide that most answers got quicker).

To keep answers quick, each helper only receives the tools it uses: the Writer, Planner and Money helpers get a closed list, and no helper can run shell commands. The prompt each turn sends is 47–69 % smaller than before (measured with dashboard/tools/fake_openai.py).

Calendar

In Settings → General → Calendars, connect a CalDAV account (Nextcloud, iCloud, Fastmail, Radicale…; an app password is best) or paste a calendar's private iCal link (Google Calendar: Settings → your calendar → Secret address in iCal format; Outlook: Publish → ICS). Mav only reads it. It is tested when you add it, and the next event is shown.

  • The briefing lists today's events, in order, and points out a tight gap or an early start.
  • Before a meeting is a new kind of routine: 15 minutes before each event, or only events whose title or place mentions a word. Mav gets the event's details with the routine's prompt (“What do I need for it? How long is the drive?”). Each one runs once, even across a restart.

Recurring events, moved and cancelled occurrences and time zones are handled. Passwords and iCal links are stored on your server only (calendar.json) and never shown again.

Routines

Things Mav does on its own: "every morning at 7, tell me if I need an umbrella", "every Sunday, plan 5 dinners and a shopping list". Four ways to create one:

  • Templates — the Routines page has ready-made ones (morning brief, evening recap, weekly review, monthly review, weekly planning…). Two clicks and it's yours.
  • the form on the Routines page — what to do, when, and which helper;
  • /routine in a chat;
  • just say it — when a message sounds recurring, Mav offers Make this a routine? with a Create routine button. Recurrence is understood in English, French and Spanish ("every monday", "tous les matins", "cada día").

When creating one, the schedule can be:

Every day at a time you pick
Some days the weekdays you choose, at a time
Once a month fixed day(s) of the month, or the last day
Every few hours an interval, in hours
On an event when something arrives from another service (see Proactivity)

Each routine runs in its own chat (Routine · name), with what Mav remembers about you, so you can open it and follow up. When there is something to report, you get a push notification and an entry in For you; an answer like "nothing to report" stays silent. Failed runs are retried once. You can snooze a routine without deleting it; it keeps its schedule and resumes on its own.

Proactivity

More proactivity is only useful if Mav can rank what it finds — otherwise it just sends more. Three rules keep it in hand.

Priority — what deserves a push

Every alert is classified, locally and instantly, as one of:

Critical money, security, a missed deadline — always interrupts you
Important a decision, an appointment, something to answer today
Useful a report, a change worth knowing
FYI background — kept in history, not pushed

How far Mav can go

Settings → General → How proactive is Mav?:

Quiet only what's critical reaches you
Normal critical and important (the default)
Chatty everything — even the smallest alert
Anything below your bar is not lost: it is recorded and collected, then delivered as one daily recap (at DIGEST_HOUR, 19:00 by default). So "more proactive" never means "more noise".

Conditions — "only if…"

A routine can carry a condition. When it isn't met, the run is skipped before Mav is even asked — nothing is spent, and nothing is sent. Conditions are: text contains / matches, a number comparison, a weekday, or "not empty". A routine can also simply be written so it replies RAS when there's nothing to say — that stays silent too.

A condition without a source does not block a run: the live data sources (weather, a price, an inbox marker) are not wired into the worker yet. The evaluator is ready; for now the "only if" is driven by what a routine can put in its own message.

Events — waking Mav from outside

A routine can be triggered by an incoming event instead of a clock. Post to the webhook:

curl -X POST https://<your-mav>/api/hooks/event \
-H 'Content-Type: application/json' \
-d '{"kind":"github","token":"<your token>","payload":{"action":"opened"}}'

Any routine with a matching on_event (a kind, and optionally a contains substring) runs on the worker's next tick. Requests from outside need the webhook's token: create it in Settings → General → Webhook and send it as "token" in the body. Event kinds offered in the form: github, calendar, form, payment, iot — or custom for anything else.

Drafts & background actions

Two ways Mav does more than talk:

  • Drafts — when Mav spots something that needs an action (a mail to answer, a follow-up), it writes it into the Drafts tab of the Routines page. You review, copy, send to your phone, or discard. Mav never sends anything by itself.
  • Background actions — ask for something long and it runs on its own (its own chat, Action · name) while your conversation stays free. A notification brings the result when it's done.

Keep an eye on

A page alerts when the readable text of the page changes
A price reads the price on a product page; alerts on any change, or only below your target
News new headlines about a topic (Google News)
A feed new items in any RSS or Atom feed: a blog, a podcast, a forum
Releases each new release of a GitHub repository (owner/repo or its address)

News, feeds and releases take an optional Only if it mentions…: a few words, separated by commas. Mav then only tells you about items whose title or summary contains one of them. Several new items at once arrive as one grouped alert, never one per item.

Items are checked about every 15 minutes (WATCH_INTERVAL). The first check only records the current state; after that, you are notified only on a change. News language and country follow NEWS_LANG / NEWS_COUNTRY in /etc/mav.env (default en-US / US).

Notifications

Web Push, on any device where you turned them on — even when Mav is closed. Tapping a routine report opens its chat; tapping an alert opens a chat that explains it. Quiet hours (NOTIFY_QUIET, default 23–7) hold pushes back; the item still lands in For you. The same alert is never sent twice within 6 hours.

What actually gets pushed depends on your proactivity level (see Proactivity): below your bar, an alert is collected into the daily recap instead. The recap runs at DIGEST_HOUR (19:00; set 0 to disable).

ntfy, Gotify, Discord and Slack

In Settings → General → Other channels, add as many as you like: an ntfy topic (on ntfy.sh or your own server, with an optional token), a Gotify application token, or a Discord or Slack webhook. Each one is tested as soon as you add it, and has its own Test button and on/off switch. Tokens and webhooks are stored on your server only (channels.json, readable by Mav alone) and never shown again in full.

Alerts go to Web Push and every enabled channel, with the same rules: quiet hours, proactivity level, no duplicates. A routine can pick its own: open it, then Send reports to…. Fill in Address of this Mav so the notification links back to the right chat.

Model

Settings → Model: pick a provider, paste a key, press Check & list models to verify it and fill the model list, then Save. Mav restarts for a few seconds and uses the new model.

Anthropic Claude models · API key
OpenAI GPT models · API key
Ollama models on your own machine or network · no key
Ollama Cloud hosted open models · Ollama API key
OpenRouter many models behind one key
Custom any OpenAI-compatible API (LM Studio, vLLM, Groq, Mistral…)

Keys are stored in /etc/mav-server.env (readable by root only) and referenced from the engine config — never sent to the browser. The same logic is used by the installer (dashboard/server/mav_provider.py).

Custom instructions

Settings → Custom instructions: what Mav should know and how it should answer — language, tone, your situation. They apply to every chat and every helper (stored as ~/.config/opencode/AGENTS.md).

Connections

Settings → Connections lets Mav use other apps and services through the MCP standard. Pick one from the catalog — read web pages, a web browser, Brave search, time zones, your files, Notion, Home Assistant, GitHub — fill in its key, and press Restart assistant in the bar that appears. Or add any MCP server with Custom…. Tokens are masked once saved; the raw configuration is in Settings → General → Advanced. Some connections need Node.js or uv on the server — Mav tells you which, and how to install them.

// online service
{ "type": "remote", "url": "https://…/mcp", "enabled": true }
// program on the server — command is an array, settings go in "environment"
{ "type": "local", "command": ["npx", "-y", "pkg"], "enabled": true }

How it works

Browser / phone (PWA)
      │
      ▼
mav-dashboard (web app + API) ──▶ mav-server (opencode engine, 127.0.0.1:4096)
      │                                  ▲
      ▼                                  │
Postgres (Docker, 127.0.0.1) ◀── mav-worker (routines, keep an eye on, push)
mav-dashboard the web app and its API (HTTP + HTTPS)
mav-server the opencode agent engine, local only
mav-worker runs routines and checks, sends notifications

Chats are engine sessions; memory, alerts, notification history, incoming events, drafts and background actions live in Postgres; routines in ~/bot/jobs.json. Everything the worker needs degrades gracefully: without Postgres, events, drafts and actions fall back to JSON files in ~/bot/.

Configuration files

/etc/mav-dashboard.env web app: address, ports, HTTPS, database, default helper
/etc/mav.env worker: model, quiet hours (NOTIFY_QUIET), watch interval, digest hour (DIGEST_HOUR), database
/etc/mav-server.env engine: API keys (written by Settings → Model)
~/.config/opencode/ engine config, custom instructions, helpers

Edit, then mav restart.

Web app API

The web app talks to a small JSON API on the same address. It needs the session cookie set by /api/auth/login (except /api/auth/*, /api/health and webhooks). Highlights:

GET /api/stream?prompt=&session=&agent= answer as Server-Sent Events: start, delta, done, error
GET /api/sessions · /api/session?id= chats, and one chat's messages
GET /api/jobs · POST /api/job/save|delete|toggle|run|snooze routines (schedules, events, conditions)
GET /api/job-templates · POST /api/job/template · POST /api/routine/detect ready-made routines, and turning a sentence into a draft
GET|POST /api/proactivity the quiet / normal / chatty level and what's pending
GET /api/drafts · POST /api/drafts/add|status|delete|notify drafts Mav prepared for you
GET /api/actions · POST /api/actions/start background actions
POST /api/hooks/event · GET /api/events incoming events that wake routines up
GET /api/watch · POST /api/watch/add|remove keep an eye on (web, price, news)
GET /api/memory · POST /api/memory/fact/add|fact/delete|exchange/delete|forget memory
GET /api/notifications the For you inbox
GET|POST /api/config/provider · POST /api/config/provider/test model provider

The full list is in dashboard/README.md.

Troubleshooting

"Assistant offline"

mav status
journalctl -u mav-server -n 50

Most often the model key or address is wrong: fix it in Settings → Model (Check & list models tells you what is wrong).

status=203/EXEC

The engine binary is missing. Install it and restart:

curl -fsSL https://opencode.ai/install | bash
sudo systemctl restart mav-server

Installed elsewhere? Set MAV_OPENCODE_BIN in /etc/mav-server.env.

The installer stopped without a message

Version 1.0.0 stopped silently right after the advanced settings on Arch-based systems. Fixed in 1.0.1 — simply run the one-line installer again. Since 1.0.1, any unexpected error shows the line that failed; send it with the end of /var/log/mav-install.log when reporting a problem.

Check everything at once

mav doctor

It checks the services, the assistant, the model, the web app, the database, disk space, file permissions, the HTTPS certificate and available updates, and says what to do for each problem.

A connection broke the assistant

Settings validates connections before saving, but a server that fails at start can still block the engine. Turn it off in Settings → Connections, then Apply.

Routines or alerts don't arrive

journalctl -u mav-worker -n 50

Check that notifications are on for this device (Settings → General → Send a test) and that you are not in quiet hours.

The web app doesn't load

journalctl -u mav-dashboard -n 50
curl -k https://<your-mav>/api/status

Start over cleanly

mav uninstall
docker volume ls | grep pgdata    # usually mav_mav_pgdata
docker volume rm mav_mav_pgdata  # also erases the memory