{"slug": "lotti-your-memories-only-on-your-devices-end-to-end-encrypted", "title": "Lotti – Your memories, only on your devices, end-to-end encrypted", "summary": "Lotti, a GPL-3.0 personal memory system built with Flutter and Dart since 2016, stores all user data in local SQLite databases on each device and syncs between paired devices through a zero-trust Matrix (Synapse) relay using Megolm encryption and AES-256-CTR attachments, with no Lotti cloud, account, or server holding a readable copy. The developer, Matthias Nehlsen, says he has tracked around 11,000 hours of his own work in Lotti since 2022, and the app runs on macOS, Linux, Windows, iOS, and Android. Keys are shared only with devices verified through emoji comparison, so an unverified device joining the account receives ciphertext it cannot read.", "body_md": "Come say hi on [Discord](https://discord.gg/uuSaa8NpY) — questions, support,\nideas, or just what you are using Lotti for.\n\n**A distributed system of record for your memories — kept on your devices,\nand nowhere else.**\n\nEverything you capture in Lotti is a memory: a voice note, a screenshot, a conversation, a photo from a birthday party, an hour of focused work, the journal entry you spoke into your phone last night. Lotti keeps those memories on your own devices and syncs them between those devices with end-to-end encryption; no cloud ever holds a readable copy. On top of that record sit applications — tasks, relationships, goals, events, projects, a daily journal — most of them looked after by a personal AI agent that reads what you recorded and proposes what to do next. Agents propose; you decide. Your memories are not rewritten behind your back, not even by the agents that work for you.\n\nmacOS · Linux · Windows · iOS · Android. Flutter and Dart, GPL-3.0, in development since 2016.\n\nI have tracked around 11,000 hours of my own work in it since 2022.\n\n[Read the manual](https://matthiasn.github.io/lotti/manual/development/) ·\n[Install](#install) ·\n[Blog series](https://matthiasnehlsen.substack.com/p/meet-lotti)\n\nMost personal software treats your life as content to be stored on someone\nelse's computer and mined. Lotti starts from the opposite premise: your\nmemories are a *record*, and a record is only worth something if it is\ncomplete, unaltered, and yours. Four principles follow from that.\n\nThere is no Lotti cloud, no Lotti account, and no server that stores your memories. Each device holds the full record in a local SQLite database, with audio, images and other attachments beside it on the filesystem. No telemetry, no analytics, and nothing uploaded to Lotti — you can confirm that by reading the source or watching the traffic.\n\nThe record is *distributed*, not centralised: every device you pair is a full\npeer. Pairing gives a new device everything written from then on; once you send\nit your history from a device that has it, a phone, a laptop and a desktop each\ncarry the whole record, and losing one costs you nothing as long as another\nsurvives. Your data is a file you\nalready have, with a documented schema, so there is no export wizard and\nnothing to unlock.\n\nDevices talk to each other through a relay rather than a storage service: a\n[Matrix](https://matrix.org) homeserver (Synapse). The relay is a zero-trust\ncomponent. Whoever operates it — you, a friend, a hosting company — never holds\na key, so they cannot read your memories, and they cannot slip changes into\nyour record either. You do not have to trust the operator with your data; you\nonly rely on them to keep the relay running.\n\n```\nflowchart LR\n    subgraph D1[\"Your laptop\"]\n        L1[(Local SQLite<br/>+ attachments)]\n    end\n    subgraph D2[\"Your phone\"]\n        L2[(Local SQLite<br/>+ attachments)]\n    end\n    R{{\"Matrix homeserver<br/>zero-trust relay<br/>(ciphertext only)\"}}\n    L1 -- \"Megolm-encrypted events<br/>AES-256-CTR attachments\" --> R\n    R -- \"ciphertext delivered;<br/>keys only to verified devices\" --> L2\n    L2 -- \"the same, in reverse\" --> R\n    R --> L1\n```\n\nHow it works:\n\n- **Encryption.** Each change is sent as an event in a private, non-federated\nsync room created with Matrix's`m.megolm.v1.aes-sha2` encryption. Room\nmessages are encrypted with Megolm, and the Megolm session keys are exchanged\nbetween devices over Olm, using the[Vodozemac](https://github.com/matrix-org/vodozemac) implementation of both. Audio and images are uploaded as Matrix encrypted\nattachments: AES-256-CTR with a per-file key, IV and SHA-256 hash that travel\nonly inside the encrypted event.\n- **Only verified devices get keys.** Keys are shared only with devices you\nhave verified yourself through an emoji comparison. A device that joins the\naccount without completing verification receives ciphertext it cannot read,\nand incoming events from unverified devices — or anything sent in plaintext —\nare dropped rather than applied, so whoever operates the server cannot inject\nchanges into your record.\n- **Trust comes from verification, not from the server.** The emoji\ncomparison is what stops a relay from posing as one of your devices: verify\nonly devices you are holding, and the operator never gets a key.\n- **What zero trust does not cover.** The operator never sees plaintext, but\ncan see metadata: the account ID and room name, which device synced and when,\nIP addresses, device display names, and the size of events and files. They\nalso control availability — they can delay, withhold or delete ciphertext,\nbut not read or alter it, and your devices still hold the full record.\n- **The relay is not an archive.** Sync rooms carry a 30-day`m.room.retention` policy. Synapse only enforces that when the operator turns\nretention on (and media retention separately); the optional[provisioning service](https://github.com/matthiasn/lotti/blob/main/services/matrix-provisioning-service/README.md) runs\nits own purge by default. Either way, the durable copy of your record is on\nyour devices, not on the relay.\n- **Conflicts are resolved, not overwritten.** Every entry carries a vector\nclock keyed by device, so a device that was offline for a week rejoins\nwithout losing writes, and genuinely concurrent edits surface as conflicts\nfor you to resolve. Devices also track each other's counters and ask a peer\nto re-send anything missing.\n\nThe full runtime picture — pairing, the sync log, backfill and failure handling —\nis in the [sync concept](https://github.com/matthiasn/lotti/blob/main/knowledge/features/sync/overview.md) and\n[security and privacy](https://github.com/matthiasn/lotti/blob/main/knowledge/architecture/security-and-privacy.md).\n\nA system of record is worthless if it can be quietly edited. Lotti keeps *what\nyou said and did* and *what an agent thinks* in separate databases on disk, and\nagent-authored changes reach your record through a code path that requires\nyour approval: an agent suggests, and nothing happens until you confirm. A\nconfirmed checklist change keeps an approval receipt, and the writes an agent\nmakes without asking are logged in its audit trail.\n\nA small, named class of writes is pre-approved rather than proposed, because\nasking every time would add friction without telling you anything new — for\nexample transcribing a recording, saving an AI summary as a *new* entry beside\nyour own, or titling a task that has none. The exact set is defined in\n[ADR 0102](https://github.com/matthiasn/lotti/blob/main/docs/adr/0102-pre-approved-agent-changes.md) and can only grow by\nanother decision record. Some things are human-only by construction: an event\nagent has no tool that can set an event's rating or cover photo.\n\n**Record provenance is work in progress.** The goal is that every entry carries\na verifiable record of who authored it — you, an agent acting under a consent\nyou gave, or an agent proposal you approved — signed and chained per device so\nthat the record can prove it was not altered. The cryptographic building\nblocks are [in the codebase](https://github.com/matthiasn/lotti/blob/main/knowledge/features/provenance.md) and modelled in\nTLA+, but entries are not signed yet, and the design will keep moving as this\nlands.\n\nSee [Two databases](#two-databases-human-in-the-loop-by-construction) for how\nthe separation is enforced.\n\nAgents need a model, and today the most capable models mostly run in a\ndatacenter. Lotti has no inference backend of its own: every request goes to a\nprovider you configured, under your own key, routed per category. Ideally that\nis a provider with a **zero-data-retention** policy, one that processes the\nrequest and keeps neither the prompt nor the response, so that inference leaves\nno copy of your memories behind. Lotti cannot verify a provider's retention\nterms; choosing one is your due diligence, covered under\n[Your inference is a routing decision](#your-inference-is-a-routing-decision).\n\nThe long-term direction is inference on your own devices, as they become\npowerful enough to run capable models. The record and the reasoning over it\nwould then both stay at home. Part of that is already here: speech recognition\nruns fully offline with Whisper or Voxtral, and lighter jobs run on a local\nmodel. For the agents, today's answer is the cloud with zero data retention,\nbecause they need a larger class of model than personal hardware runs fast\nenough yet — see\n[Local models and the sweet spot for agents](#local-models-and-the-sweet-spot-for-agents).\n\nThe storage layer is the product's foundation; the applications are what you\nuse every day. Each one reads from the same record, and all of them except the\njournal can be given a persistent AI agent with its own report, memory, wake\nschedule and proposal history. Tasks and the journal are on by default; the other applications are\n**Sections** you switch on under Settings → Sections. Turning a section off\nonly hides it — nothing you recorded is deleted.\n\nEvery screenshot and audio recording is a memory, attached to the work it belongs to. A rambling voice note comes back as a task with a checklist.\n\nA **task agent** reads everything linked to a task and keeps a living report.\nIt proposes changes rather than making them: a title, an estimate, a due date,\npriority or status, new or ticked-off checklist items, labels, follow-up tasks,\nlinks to related tasks, time entries. Each proposal waits for you to confirm or\ndismiss it. Automatic updates decide when the agent wakes, not what it may\nchange.\n\n**Pull request tracking** closes the loop between what you planned and what\nactually shipped. Turn it on for a task from its \"+\" menu, link one or more\nGitHub pull requests, and Lotti keeps a summary of each — a one-liner and a\nTL;DR — refreshed when you open the task or ask it to. The pull requests become\npart of the task agent's context, so it can propose ticking off the checklist\nitems a merged PR actually covers, naming the PR as its evidence. You still\nconfirm each one. A personal access token, kept in the device keystore and\nsynced end-to-end encrypted, is only ever sent to `api.github.com`.\n\n**Coding prompts** and other briefs are a skill you trigger: they turn a task\nplus your notes into a coding, design, image or research prompt you can paste\ninto the tool of your choice.\n\nThe People section is for the relationships you want to look after. Record a conversation, or dictate afterwards who you spoke to and what you talked about; a check-in holds the recordings, transcripts, notes and photos.\n\nMark someone as important and they get a **relationship agent**. Before you\nmeet again it gives you a briefing: what was discussed last time, how things\nhave been going, suggested talking points, and what to pay attention to or\nsteer clear of. It reminds you when it has been too long, and it can propose up\nto three tasks arising from a conversation — each waiting for your\nconfirmation.\n\nDefine a goal — hours on a category or label, a measurement you track — and a\n**goal agent** watches your actual record against it. A deterministic evaluation runs\nevery day at no inference cost. When you drift off track, the agent reminds\nyou, with an OS notification and a banner explaining what slipped; when you are\non track, it stays out of your way, its report records the progress, and you\ncan ask it for an encouraging nudge. If the goal itself no longer fits, it can\npropose a revision, which you approve.\n\nTrack the events that matter — a trip, a birthday party, a gathering — with the\nphotos, recordings and notes that belong to them. An **event agent** narrates\nwhat you captured into a short living recap. The star rating and cover photo\nstay yours alone: the agent has no tool that can set them.\n\nA project groups the tasks that serve one outcome. A **project agent** keeps a\nreport on what is going on: current status, a health verdict, what is still\nmissing, and recommended next steps. It can propose a status change or a new\ntask for your approval. The project's summary also flows into every task\nagent's context, so work on a single task is informed by the project it\nbelongs to.\n\nSpeak or type a journal entry, attach photos, or let a day's recordings stand as they are. Transcription runs locally with Whisper or Voxtral if you want it to, and your journal can be routed to a local model — or to no model at all. The journal is the purest form of the record: your words, kept as you said them, on your devices — read by no model unless you route it to one.\n\nLotti has no inference backend. Route each category of your life to the compute you are willing to stand behind: a cloud provider with zero data retention, the European option Lotti recommends, or a local model as personal hardware catches up. The usage view reports tokens and requests for every cloud call, and spend, energy and CO₂e for the providers that report them — today that means Melious. Local inference is not measured at all, because the cost moves onto your own hardware and grid.\n\nKeeping several devices consistent without a server in charge is a\ndistributed-systems problem, and it is treated as one. The parts where\nconcurrency and crashes could lose or duplicate your data — the sync log, how\nagents are woken and recover after a crash, how a confirmed suggestion is\napplied when two devices race, how synced agent state converges, the agents'\nmessage log, pull request tracking, and the Daily OS jobs — are written down as\n[50 TLA+ models](https://github.com/matthiasn/lotti/blob/main/specs/tla/README.md) and model-checked with TLC every night\nacross 177 configurations, under crashes, injected failures, clock skew and\nmessages arriving in any order ([the ledger](https://github.com/matthiasn/lotti/blob/main/specs/tla/LEDGER.md) keeps the\nrunning totals). No saved change is ever declared lost, and as long as devices\nkeep reconnecting and a failed send is retried, every saved change reaches every\ndevice. A double tap never applies a confirmed change twice. Checking the models\nfound and closed dozens of real bugs. These are statements about the design, not\na proof that every line of code matches it; [the specs](https://github.com/matthiasn/lotti/blob/main/specs/tla/README.md) say\nexactly what is covered and which cases remain open, and generated traces drive\nthe real code through the same scenarios. The code is held to them the ordinary\nway, too: over 35,000 tests at 99.9% line coverage, including more than 900\nproperty-based tests.\n\n| Platform | Where to get it | \n|---|---|\n| **Linux** | [Flathub](https://flathub.org/en/apps/com.matthiasn.lotti) (recommended), or AppImage or`tar.gz` on[Releases](https://github.com/matthiasn/lotti/releases) | \n| **Android** | APK on [Releases](https://github.com/matthiasn/lotti/releases) , or Play Store internal testing (limited; invitation only) | \n| **macOS** | Signed and notarized DMG on [Releases](https://github.com/matthiasn/lotti/releases) | \n| **iOS / iPadOS / macOS** | TestFlight (limited; invitation only), with broader availability planned | \n| **Windows** | Build from [source](https://github.com/matthiasn/lotti/blob/main/docs/DEVELOPMENT.md) for now | \n\n**AppImage (Linux, no app store):** download `Lotti-<version>-x86_64.AppImage`\nfrom [Releases](https://github.com/matthiasn/lotti/releases), mark the\ndownloaded file executable (`chmod +x` on it, or your file manager's\npermissions dialog) and start it. It brings its own media, keychain and\nrecording libraries and runs on distributions from 2022 on\n(glibc 2.35 or newer: Ubuntu 22.04, Debian 12, Fedora 36 and later) that have\nGTK 3 and Mesa's OpenGL ES, as any GNOME or KDE desktop does. It mounts itself\nwith FUSE, which desktops ship by default; where FUSE is missing, run it with\n`--appimage-extract-and-run`. Unlike Flathub, it does not update itself.\n\n- **Audio recording** anywhere in the app, transcribed locally with Whisper\n(99 languages) or Voxtral, or through a cloud provider with audio support.\n- **Entries** : notes, images, screenshots, measurements, and surveys, attached\nto the work, person, event or day they belong to.\n\n- **Tasks** with full lifecycle (open, groomed, in progress, blocked, on hold,\ndone, rejected), checklists, estimates, priorities, due dates, labels, linked\ncontext, optional generated cover art, and linked GitHub pull requests.\n- **Time tracking** recorded against the plan rather than instead of it, with\nfocus ratings. A task describes the outcome you want; a time record describes\nwhat actually happened. Lotti keeps them as separate facts, so the record\nstays honest when the week gets noisy.\n- **Time analysis** over categories, habits, and measurements.\n\n- **Categories and labels** to make the boundaries that your decisions\nactually use.\n- **Habits, measurables, and health data** imported from Apple Health and\nother sources.\n- **Sections** you switch on under Settings → Sections: Daily OS, Projects,\nGoals, Habits, Dashboards, People and Events. They are in daily use and ship\nswitched off, so you choose which parts of Lotti you use.\n\n- **Agents for every application** : task, project, goal, relationship and event\nagents, plus a day planner. Each keeps its own report, memory and proposal\nhistory.\n- **Providers, models, and inference profiles** as three separate layers, so\nrouting is explicit and the blast radius of a change is visible before you\nmake it.\n- **A European route, offered rather than imposed.** Onboarding highlights[Melious.ai](https://melious.ai) , an OpenAI-compatible EU endpoint serving\nopen-weight models. You bring your own key and hold your own contract with\nwhoever you pick.\n- Works with everything else too: OpenAI, Anthropic, Mistral, Google, Alibaba, Nebius, OpenRouter, Ollama, or any OpenAI-compatible endpoint, including a custom base URL pointed at your own gateway.\n- **Agent templates and souls** : a template defines a responsibility, a soul\ndefines voice, tone bounds, coaching style, and an anti-sycophancy policy.\nBoth are versioned, both are improved through reviewable 1-on-1 sessions, and\nboth can be rolled back.\n- **Grievances and 1-on-1s.** When an agent annoys you, say so — no form and no\nmagic phrase required. It records the grievance and brings it up in the next\n1-on-1, where the two of you reconcile what changes. The result is an\nassistant that evolves rather than one you configure once.\n- **Contextual skills** for work that does not need a durable agent, including\nthe prompt generators described above.\n- **Usage and impact** : tokens and requests by period, category and model for\nevery cloud call, plus cost, energy and CO₂e wherever the provider reports\nthem — currently Melious. Other providers return token counts only, so those\ncolumns stay empty rather than being estimated.\n- Turn all of it off. Lotti is useful without any inference configured.\n\n- End-to-end encrypted sync across your devices, relayed by a Synapse\nhomeserver whose operator never holds a key — see\n[the vision](#2-end-to-end-encrypted-sync-through-a-zero-trust-relay) for how it works.\n- The first device is set up against a homeserver with the included\n[`tools/matrix_provisioner`](https://github.com/matthiasn/lotti/blob/main/tools/matrix_provisioner) CLI or the optional[provisioning service](https://github.com/matthiasn/lotti/blob/main/services/matrix-provisioning-service/README.md) , which\ncreate the sync account and encrypted room and produce a single-use pairing\nbundle. On Linux you can also enter an existing Matrix account directly.\n- Every device after that pairs from one you already use: scan a QR code, compare a check code shown on both screens, then complete emoji verification. The pairing QR carries the sync account's credentials, so treat it like a password. Until verification finishes, the new device receives ciphertext it cannot read.\n- **Your data is a file you already have.** Local SQLite with a documented\nschema, plus attachments on the filesystem.\n\nLotti keeps *what you said and did* and *what an agent thinks* in different\ndatabases on disk.\n\nThe **user database** is the system of record: tasks, notes, audio, photos,\ntime recordings, journal entries, people, events. It is treated with care, and\nagents do not write into it freely.\n\nThe **agentic database** is agent working memory: definitions, memories, wake\nhistory, reasoning traces, reports, proposals. It may grow and it may be\npruned. It can be thrown away and rebuilt without losing anything that matters\nabout *you*.\n\n```\nflowchart LR\n    subgraph Agentic[\"Agentic DB (prunable, recreatable)\"]\n        A[Agent state & memories]\n        W[Wake cycle reports]\n        S[Proposals]\n    end\n    subgraph User[\"User DB (system of record)\"]\n        T[Tasks & projects]\n        J[Journal, audio & photos]\n        P[People & events]\n        M[Metrics, habits & goals]\n    end\n    A --> W --> S\n    S -->|requires your approval| T\n    S -->|requires your approval| P\n    S -.->|pre-approved class only, ADR 0102| J\n```\n\nThe rule matters because of how it is enforced. Agent-authored content sits in\na different file on disk and reaches the user database only through a code path\nthat requires your approval, or through one of the pre-approved paths\n[described above](#3-memories-stay-unaltered-with-clear-provenance) and defined by\n[ADR 0102](https://github.com/matthiasn/lotti/blob/main/docs/adr/0102-pre-approved-agent-changes.md). Every other change an\nagent wants to make to your record is a proposal you confirm or dismiss. Both\ndatabases sync between your devices the same way.\n\nThree different claims get flattened into the word \"private.\" Lotti makes all three. They are worth separating, because they fail in different ways.\n\nLotti collects nothing — the record stays on your devices, as described in\n[the vision](#1-your-memories-live-only-on-your-devices). Two things do leave,\nboth because you configured them: ciphertext to the homeserver you chose, and\ninference requests to the provider you chose (plus, if you turn on pull request\ntracking, requests to the GitHub API).\n\n*The other side of that:* there is no server-side backup and no account\nrecovery, because no server holds a readable or lasting copy of your data.\nSync is the redundancy story — but it is not automatic history. Pairing a\ndevice gives it everything written *from then on*; your existing settings and\nback catalogue arrive only when you run *Send settings* and *Send message\nhistory* from the device that already has them. Until you do, the new device is\na live peer, not a backup. Do that early, and a second device means losing one\ncosts you nothing.\n\nKeep an ordinary backup as well, since replication covers hardware loss and a\nbackup covers everything else. Your record is a SQLite database sitting on your\nown disk with a documented schema, so reading it takes a query rather than\npermission. Take a consistent copy with `VACUUM INTO` while the app is running,\nand bring the attachments directory along with it, because audio and images\nlive on the filesystem rather than in the database.\n\nOn a phone the database sits inside the app sandbox, so the practical route there is to pair a desktop and take the copy from that peer.\n\nDeleting works the other way round, and the order matters: delete entries *in\nthe app* rather than deleting the database files. Purging removes an attachment\nby walking the deleted rows that still point at it, so a database removed first\nleaves its audio and images orphaned on disk. Paired devices and ordinary\nbackups keep their own copies either way, and anything already sent to a\nprovider is subject to that provider's retention, not yours.\n\n*What this does not protect against:* a compromised device. The on-device\nSQLite files live inside your OS user account and are not separately encrypted\nby Lotti today. That includes the sync session: its access and refresh tokens,\nand its Olm identity and Megolm session keys, which the Matrix SDK stores\npickled under a key derived from the account ID rather than from a secret.\nAnyone who can read your files can read your record and impersonate that\ndevice. The sync password, AI provider keys and GitHub token are the exception:\nthey sit in the OS keystore. App-level at-rest encryption is a candidate for\nthe roadmap; until it lands, rely on your operating system's full-disk\nencryption, give Lotti's on-device data the same care you would give any\npersonal app on the same machine, and weigh that before putting your most\nsensitive categories in it.\n\nSync runs over Matrix with Vodozemac for end-to-end encryption, through a\nSynapse homeserver you can run yourself or rent from anyone. Its operator does\nnot need to be trusted with your data: the relay only ever handles ciphertext,\nkeys go only to devices you verified, and events from anything else are\ndropped. Both databases sync this way. The details are in\n[the vision](#2-end-to-end-encrypted-sync-through-a-zero-trust-relay).\n\n*What this does not protect against:* metadata and availability. Whoever runs\nthe homeserver can observe your account, which devices synced and under what\ndevice names, from which IP addresses, when, and roughly how much. Not what.\nThey can also stop relaying, and how long the relay keeps ciphertext depends on\nwhether its operator enables retention.\n\nLotti has no inference backend. Every AI call goes to a provider you configured, under your own account and API key, and you choose per category which provider that is. Work can go to one provider while your journal goes to another, or to none at all. That granularity is the entire point.\n\n**Prefer zero data retention.** The provider you route a category to sees what\nthat category sends it. The safest cloud choice is a provider whose terms\ncommit to zero data retention — no prompts or responses kept after the request,\nno training on them. Many providers offer that only on request or on specific\nplans, so read the terms rather than the marketing page.\n\n**Onboarding highlights a European route.** [Melious.ai](https://melious.ai) is\na German company routing open-weight models across a network of EU\ninfrastructure providers. They state that requests are not used for training\nand that data stays under European jurisdiction. Those are their claims, on\ntheir terms, and worth reading in full before you rely on them. Directories\nsuch as [staysin.eu](https://staysin.eu/api.melious.ai) list Melious, but they\nare compiled from providers' own published material, not from an audit.\n\nMistral, Google, Alibaba, OpenAI, Anthropic, OpenRouter, and any other OpenAI-compatible endpoint work equally well. Lotti does not rank them, does not summarise their terms, and cannot verify anyone's claims about jurisdiction, retention, or training. Picking a provider is your decision and the due diligence is yours.\n\nWhat Lotti does instead is refuse to let the decision be invisible:\n\n- Routing is configured per category, ahead of time, rather than negotiated in the moment — so which provider a given piece of work goes to is a setting you chose, not a prompt you clicked past. The flip side is that there is no just-in-time notice at the point an agent or a transcription fires; the onboarding and settings screens are where that decision is made and shown.\n- A friendly display name is not the security boundary. The provider detail view shows the actual base URL, the models attached to it, and every profile that depends on them.\n- Usage & Impact logs every request that left the machine and which model served it, with token counts throughout and cost, energy and CO₂e wherever the provider reports them.\n\nA LAN endpoint is worth the same scrutiny. \"Local\" means it did not go to a hosted provider, not that no network hop occurred.\n\n*What this does not protect against:* a provider that does not do what its\nterms say. Nothing in Lotti can verify that, and neither can anyone else from\nthe outside. What Lotti can do is show you every request it made, where it\nwent, and what it cost.\n\nSome of Lotti runs well on your own machine today. Speech is fully offline via Whisper or Voxtral, and a local inference server handles lighter jobs. Lotti connects to:\n\n- [Ollama](https://ollama.com) and[oMLX](https://github.com/jundot/omlx) (MLX\non Apple Silicon), which have their own provider types in Lotti's settings;\n- anything else that serves an OpenAI-compatible API, through the\n*OpenAI Compatible* provider: Python-based servers such as[vLLM](https://github.com/vllm-project/vllm) ,[SGLang](https://github.com/sgl-project/sglang) and[mlx-lm](https://github.com/ml-explore/mlx-lm) , as well as[llama.cpp](https://github.com/ggml-org/llama.cpp) 's`llama-server` and[LM Studio](https://lmstudio.ai) .\n\nThe agents are a different matter. Their sweet spot right now is models of the\nsize and capability of **DeepSeek V4.1 Flash** and **GLM 5.3 Flash**, both of\nwhich perform particularly well on Lotti's agent workloads. The models people\ntypically run locally are not that far behind on correctness, but they are slow:\nQwen 3.8 27B, for example, lands only a few points below them, yet is far slower\neven on cloud inference, occasionally stalls, and misses the day planner's\n30-second budget ([the evaluation](https://github.com/matthiasn/lotti/blob/main/docs/evaluations/lotti-gym-2026-09-21.md)).\nOn a personal machine that gap only widens: even an M4 Max with 128 GB of RAM\ndoes not yet run the agents fast enough to keep up with daily use. Personal\nhardware is improving quickly, and closing that gap is the long-term direction.\n\n**LottiGym is how new models are judged.** Models enter the market every few\nweeks, and a benchmark score says little about whether one can run a task\nagent. [LottiGym](https://github.com/matthiasn/lotti/blob/main/knowledge/features/ai/model-evaluation.md) runs a candidate\nthrough Lotti's real agent harnesses — task, goal, relationship, Daily OS\nplanning and query exercises, several samples each — grades the results, and\nrecords correctness, cost and latency side by side\n([recent results](https://github.com/matthiasn/lotti/blob/main/docs/evaluations)). A new model earns a recommendation by\npassing it:\n\n```\npython3 tool/lotti_gym.py assess --model MODEL_ID\n```\n\n**The practical answer today is the cloud, with zero data retention:** run\nthe agents on a sweet-spot-class model from a provider whose terms commit to\nkeeping nothing, and keep speech fully offline with Whisper or Voxtral if you\nlike. Image generation has no local path yet — cover art goes through Gemini or\nAlibaba. As personal hardware gets faster, models of that class are expected to\nmove onto your own devices, until a cloud provider is a choice rather than a\nnecessity.\n\n**Input on running Lotti locally is very welcome.** If you have a model,\nquantisation, runtime or hardware setup that keeps up with the agents, please\nshare it in a [GitHub issue](https://github.com/matthiasn/lotti/issues) or on\n[Discord](https://discord.gg/uuSaa8NpY).\n\nInference runs in a physical building on a specific grid. The **Usage & Impact**\nview reports tokens and requests for every cloud call, broken down by category\nand by model, so \"what did my thinking cost\" has an answer rather than a vibe.\n\nHow complete that answer is depends on the provider. Cost, energy, CO₂e and water are recorded when the provider returns them with the response, which today means Melious; every other provider reports token counts only, and those columns stay empty rather than being filled with an estimate. That is a real limit on the dashboard: route your work through a provider that discloses nothing, and the impact of that work is not something Lotti can show you.\n\nThe route highlighted in onboarding publishes power usage effectiveness per datacenter and carries Green Web Foundation verification, which is more than most disclose. Running a model locally moves the cost onto your own hardware and your own grid, which is a different trade rather than a free one, and the dashboard does not measure it.\n\nChoosing a renewable-powered route avoids outsourcing the health and climate cost of fossil-powered compute, gas turbine generation in particular, to communities with less power to refuse it. That is a reason to care where your tokens get processed even if you do not care who reads them.\n\nTurn AI off. Configure no provider at all, or point every category at Ollama with local Whisper for speech. Lotti is a complete task manager, time tracker, and journal without a single inference call leaving the machine.\n\nBuilt and documented, but not enabled in a default build. Turn it on under Settings → Sections, and expect it to change.\n\n- **Daily OS** turns a spoken or typed check-in into a plan for one day. It\nreconciles what you said against your real tasks, drafts an agenda against\nyour actual capacity, and presents every proposed change with its old time,\nits new time, and the planner's reason. Nothing is committed until you hold\nthe confirm control. Wrap-up at the end of the day separates what you\nfinished from what carries forward.[Documentation](https://matthiasn.github.io/lotti/manual/development/plan-and-capture/daily-os)\n\nAlso under way, with no switch to flip yet: **record provenance**, so that\nevery entry is signed by its author and the record can prove who wrote what —\nsee [the vision](#3-memories-stay-unaltered-with-clear-provenance).\n\nNext agent types on the roadmap: week planners, long-term commitment monitors,\nand effort-against-goals balancers — same building blocks, different jobs.\nDesigned but not yet built: learning quizzes. See the\n[roadmap](https://matthiasn.github.io/lotti/manual/development/roadmap).\n\n**Linux is and will always be free, with maximum functionality.** No paywalls,\nno upsells. The same promise extends to any future fully open-source mobile\noperating system. The one thing it does not include is hosted sync\ninfrastructure — running a homeserver is a real cost, so you either self-host\nMatrix or bring your own.\n\n**On other platforms, the basics stay free too.** Task and journal capture, the\ntask agent, voice transcription, the everyday loop.\n\n**More advanced agent features may eventually be in-app purchases on platforms\nwhere IAP is the norm** (iOS/macOS, Android, Windows). The candidates: day- and\nweek-planner agents, overarching project-management agents, longer-horizon\ncommitment monitors. The exact split is not set yet.\n\n- **[Manual](https://matthiasn.github.io/lotti/manual/development/)** — the\nfull guide, available in 11 languages. Start with[the mental model](https://matthiasn.github.io/lotti/manual/development/getting-started/mental-model) if you want to understand the shape of the thing before installing it.\n- [Connect an AI provider](https://matthiasn.github.io/lotti/manual/development/ai-and-automation/provider-setup/) — local Ollama or cloud Gemini, and the models and profiles around them\n- [Task management and voice capture](https://matthiasn.github.io/lotti/manual/development/getting-started/first-task/) — the everyday voice-to-checklist workflow\n- [Architecture](https://github.com/matthiasn/lotti/blob/main/docs/ARCHITECTURE.md) — the two databases, vector clock sync,\non-device inference\n- [Knowledge bundle](https://github.com/matthiasn/lotti/blob/main/knowledge/index.md) — how the app actually works at\nruntime, subsystem by subsystem, written for contributors and coding agents\nalike; start with[security and privacy](https://github.com/matthiasn/lotti/blob/main/knowledge/architecture/security-and-privacy.md) and[sync](https://github.com/matthiasn/lotti/blob/main/knowledge/features/sync/overview.md) for the details behind this\npage\n- [Background](https://github.com/matthiasn/lotti/blob/main/docs/BACKGROUND.md) — why this exists\n- [Privacy policy](https://github.com/matthiasn/lotti/blob/main/PRIVACY.md) ·[Security policy](https://github.com/matthiasn/lotti/blob/main/SECURITY.md)\n- [Roadmap](https://matthiasn.github.io/lotti/manual/development/roadmap)\n\nBuilding it yourself: install Flutter via [FVM](https://fvm.app/) (the repo\nincludes `.fvmrc`), then `make deps`, `make analyze`, `make test`,\n`fvm flutter run -d <device>`. Full setup, including the Linux audio-codec and\nemoji-font packages, is in [docs/DEVELOPMENT.md](https://github.com/matthiasn/lotti/blob/main/docs/DEVELOPMENT.md).\n\nThe application is in active daily use and the agentic layer is real, working,\nand shipping. Development happens in the open, and the [changelog](https://github.com/matthiasn/lotti/blob/main/CHANGELOG.md)\nis the honest version of what changed.\n\nThe agentic layer moves fastest: soul and template ergonomics, grievance handling, and pruning strategies are all under active development, and feedback there is especially useful. Local image generation, at-rest database encryption, and signed provenance do not exist yet.\n\nThe manual, including every screenshot in all 11 languages, is generated from a deterministic fixture workspace, so the documentation cannot quietly drift from the build it documents.\n\n**Stack**: Flutter and Dart across five platforms, local SQLite via Drift with\nObjectBox for embeddings, Whisper and Voxtral for on-device speech recognition,\nMatrix and Vodozemac (Olm/Megolm) for the encrypted sync transport, Glados for\nproperty-based tests, TLA+ and TLC for the formally verified sync protocol and\nagent runtime.\n\nThe easiest way in is to say hi on [Discord](https://discord.gg/uuSaa8NpY).\nBeyond that, two things genuinely help, and one thing to know up front.\n\n**Welcome:**\n\n- **Issues and bug reports** — the best place to start. Tell me what broke and\nhow to reproduce it.\n- **Translations** — new languages and corrections to existing ones.\nAI-assisted translation is fine**provided you contribute from a real-name,\nestablished GitHub profile** . Translation PRs are the one kind that gets\nmerged.\n\n**Not accepted: code pull requests.** Review capacity is the binding\nconstraint, Lotti holds people's personal data on their own devices, and\nAI-generated code now arrives far faster than it can be reviewed carefully. An\nunsolicited code PR will be closed unmerged, with thanks and without review —\nso please open an issue instead of writing the patch. It is more useful to me\nand cheaper for you.\n\n[CONTRIBUTING.md](https://github.com/matthiasn/lotti/blob/main/CONTRIBUTING.md) has the details, including what makes a\ntranslation PR mergeable.\n\nGPL-3.0. See [LICENSE](https://github.com/matthiasn/lotti/blob/main/LICENSE).\n\nThanks to the [Flutter](https://flutter.dev) team, the\n[Qwen](https://github.com/QwenLM) and [Mistral](https://mistral.ai) teams for\ntheir open-weights models, [OpenAI](https://openai.com) for the\n[Whisper](https://github.com/openai/whisper) weights, the\n[Ollama](https://ollama.com) project, the [Matrix.org](https://matrix.org)\ncommunity, the [Vodozemac](https://github.com/matrix-org/vodozemac) authors, and\neveryone contributing translations, issues, and ideas.", "url": "https://wpnews.pro/news/lotti-your-memories-only-on-your-devices-end-to-end-encrypted", "canonical_source": "https://github.com/matthiasn/lotti", "published_at": "2026-10-16 09:53:41+00:00", "updated_at": "2026-10-16 10:09:37.209798+00:00", "lang": "en", "topics": ["ai-agents", "ai-products", "developer-tools"], "entities": ["Lotti", "Matthias Nehlsen", "Matrix", "Synapse", "Megolm", "Olm", "Vodozemac", "Flutter"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/lotti-your-memories-only-on-your-devices-end-to-end-encrypted", "markdown": "https://wpnews.pro/news/lotti-your-memories-only-on-your-devices-end-to-end-encrypted.md", "text": "https://wpnews.pro/news/lotti-your-memories-only-on-your-devices-end-to-end-encrypted.txt", "jsonld": "https://wpnews.pro/news/lotti-your-memories-only-on-your-devices-end-to-end-encrypted.jsonld"}}