Storage & privacy
Loach is local-first. Your content lives on your machine, and nothing goes over the network unless you set up something that needs it - a remote provider, web fetch, a Library link, an MCP server, the update check. Here’s exactly what is stored, where, and what leaves your machine and when.
Where things live
| What | Where |
|---|---|
| Chats and messages (with their tool calls and results), folders, labels, pinned responses, Spaces with their sources and memories, the Library (texts, files, links and datasets) and its search index, global memories, Snippets with their variables and saved fill-ins, MCP servers, app settings | SQLite at <app-data-dir>/loach.db, plus its -wal and -shm files |
| Attached files | Inside their message in loach.db - images and other files as base64, text and documents as their extracted text. There is no separate file store. |
| OpenAI-compatible API key | OS credential manager (Windows Credential Manager / Linux Secret Service / macOS Keychain) |
| App-lock hash + hint | OS credential manager - same store, separate entry |
| App-lock marker (whether a lock is set, its method, the PIN length and whether it has a hint - no hashes) and the failed-unlock count | app_lock.json and app_lock_attempts.json next to loach.db |
| MCP server headers and environment variables | In loach.db as plain text, with the rest of the server’s settings - not in the credential manager |
| A chat’s working folder | Only its path, on the chat. The files stay where they are; Loach doesn’t copy them. |
| Code-canvas snippets opened in VS Code | Scratch files in <app-cache-dir>/canvas |
| Layout preferences (canvas width, open sidebar folders, the parameters panel’s view, the Library’s last tab), each model’s Thinking default, and turns waiting for memory extraction (chat and message IDs only, no text) | The app window’s local storage |
| Local models | Stored by Ollama, outside Loach’s folders |
| App data dir on Windows | %APPDATA%\dev.loach.app\ |
| App data dir on Linux | ~/.local/share/dev.loach.app/ |
| App data dir on macOS | ~/Library/Application Support/dev.loach.app/ |
| App cache dir | %LOCALAPPDATA%\dev.loach.app\ on Windows, ~/.cache/dev.loach.app/ on Linux, ~/Library/Caches/dev.loach.app/ on macOS |
The database isn’t encrypted: anyone who can read your app-data folder can read your chats, your Library, and any MCP credentials stored with your servers. Loach writes no log files.
Offline by default
With a local Ollama, Loach launches and works completely offline. All of these need no network access:
- The Models library
- Spaces, Snippets and memory
- The Library and its search - by keyword, and by meaning with an embedding model on your Ollama
- Search across chats, messages, Spaces, Snippets and the Library
- The parameters panel
- The app lock
- Full chat history, and Private Chat
- Built-in tools, working folders and LaTeX math rendering - KaTeX ships inside the app
Only chats with a remote endpoint (OpenAI, Groq, OpenRouter, …), web fetch and Library links, an embedding model on a remote endpoint, remote MCP servers (and the first start of an npx or uvx one, which downloads its package), the update check and model downloads need an internet connection. An Ollama or OpenAI-compatible server elsewhere on your network needs that network, not the internet.
No telemetry
Loach does not phone home. There is no account, no usage tracking, no analytics, no crash reporting service. The app window itself can’t reach the internet: its content security policy allows no remote scripts, images or connections, and no inline scripts or eval, so every request goes through Loach’s backend - and only for the reasons below. Nothing else happens in the background.
The one place inline scripts run is the code canvas’s HTML preview, inside a sandboxed frame with a policy of its own: it loads nothing from outside the page and can’t reach the network or Loach’s commands.
What goes over the network, and when
| Destination | When |
|---|---|
Your Ollama base URL (http:// by default) | At launch, to see whether Ollama is running and list its models; then for every chat, model preload and Models-tab action - and, when the Library’s embedding model runs on Ollama, to embed your sources in the background and every message that searches them. Pulling a model makes Ollama download it from its library - that connection is Ollama’s, not Loach’s. So is a chat with an Ollama cloud model (a tag ending in cloud, such as gpt-oss:120b-cloud): Ollama runs it on ollama.com. |
| Your OpenAI-compatible endpoint | Its model list at launch and when the provider settings change - but only once you’ve saved an API key or pointed the base URL away from the OpenAI default. Then every chat you run on it, and Test connection. When the Library’s embedding model runs there, also your sources’ text, embedded in the background, and every message that searches them - in chats with a local model too. |
| URLs in your prompt | Only with Web fetch switched on (it’s off by default), plus a page you fetch with /fetch. Addresses on your own machine or private network are refused. |
| Library links | A web page when you add it to the Library or refresh it - never on its own. Addresses on your own machine or private network are refused, and a user name or password in the link is removed before it’s fetched or stored. |
| Your MCP servers | An HTTP server whenever a chat needs its tool list or calls one of its tools. A local (stdio) server is a program on your machine; what it connects to is up to that program. |
| GitHub releases | When you press Check for updates in Settings → Updates, or once per launch if you switched on Auto-check for updates (off by default). An update is downloaded only when you confirm. |
| Your web browser | Links you click in a reply, the model-library links in onboarding and the share buttons open in your default browser, which makes those requests itself. |
Web fetch, Library links and HTTP MCP servers always connect directly, never through a proxy: a proxy looks addresses up itself, which would slip past Loach’s check for private ones. Requests to Ollama and your OpenAI-compatible endpoint go through a proxy when your environment or system settings name one.
What a remote provider receives
A chat on a remote endpoint sends that provider everything the model needs for the turn:
- The system prompt - the instructions that apply (the Space’s, the chat’s or your Custom instructions), the persona and tone, the date, weekday and timezone while Temporal awareness is on, your name wherever
{{USER_NAME}}appears, the sources that go in full - a Space’s uploads and the Library items linked to the Space or the chat - and your memories. - The conversation - your messages and its replies (a compacted chat sends its summary instead of the older turns), with attachments inlined, the text of any pages Web fetch downloaded, and the excerpts searched from your sources for each message. Images, attached or from your sources, are scaled down first unless you chose otherwise.
- Tools - the definitions of the tools that are on, and every tool result: what MCP servers return, and the contents of files the model reads from the chat’s working folder. The folder’s full path and its
LOACHFILE.mdgo in the system prompt.
Two background requests go to the same provider and model: memory extraction after each reply while Space memory or global memories are on, and the summary when you compact a chat or export its context compacted. Global memories are sent with every chat, whichever provider it uses - a fact learned talking to a local model also reaches a cloud one. The extractor is told never to save a password, key or other credential, and Loach drops a new fact that looks like one; facts you add yourself are kept as you typed them. Private Chat talks to Ollama only and never uses memory, tools or the Library.
An embedding model for the Library is a separate destination: with one on an OpenAI-compatible endpoint, your sources’ text and every message that searches them go there, whichever provider the chat itself uses.
The API key is sent only over https://, or over http:// to this computer (localhost, 127.0.0.1, ::1). An http:// server elsewhere on your network gets no key.
Secrets handling
The API key and the app-lock credentials are stored in your operating system’s credential manager via the keyring crate, under the service name dev.loach.app:
- On Windows - the Credential Manager.
- On Linux - the Secret Service (GNOME Keyring / KWallet / equivalent). One has to be running and unlocked, or the key won’t save; one that starts after Loach is picked up on the next try.
- On macOS - the Keychain.
The key never reaches the database or the app window, and Settings never shows it back. App-lock secrets are hashed with Argon2id before they’re stored; the plaintext is never written anywhere. The optional lock hint is stored as you typed it, in the same entry, because the lock screen shows it.
MCP credentials are the exception: a server’s HTTP headers (an Authorization token, say) and a local server’s environment variables are kept in loach.db as plain text. Exports leave them out.
Files and programs
- File access goes through Loach’s backend. Saving an export or an attachment, importing a backup and picking a working folder all use native dialogs, and the backend does the reading and writing, so the app window can’t read or overwrite a file you didn’t pick.
- Working folders are sandboxed. The model reaches only the files inside the folder you picked for a chat - absolute paths,
..and links pointing elsewhere are refused, a whole drive and Loach’s own data folder can’t be picked, and there is no shell. Before a file is written, edited, moved or deleted, Loach shows you the change and asks, unless you’ve allowed that tool for the chat. See Work in folders. - Local MCP servers need your consent. Testing, switching on or changing a local (stdio) MCP server raises a native system dialog that shows exactly what will run, with Cancel as the default button. Imported local servers arrive switched off.
- MCP tool calls ask first. By default every call pauses the reply and shows the server, the tool and its arguments: Allow once, Always allow that tool, or Deny. Turn Ask before each tool call off only for a server you trust. See MCP support.
Backup, restore and wipe
From Settings → Data you can:
- Export data - save your full content (chats, folders, Spaces with their sources and memories, the Library, global memories, Snippets and variables, MCP servers, settings) to a single JSON file, tagged
loach/v2- Loach 1.5 and older can’t restore it. MCP headers and environment variables are left out, and so are secrets in a server’s arguments (a password or token in a URL, a--tokenvalue, aGITHUB_TOKEN=…setting, anAuthorization:header) and the credentials and query values in an HTTP server’s address; chats leave out their working folder. The Library’s search index isn’t exported either - it’s rebuilt after a restore. - Import data - restore a previously exported file. It replaces everything in the database, the Library included, but keeps the stored API key - and, while a key is stored, your current OpenAI-compatible base URL, so a backup can’t send the key somewhere else. Local MCP servers come in switched off.
- Erase & Reset → Remove my data - delete chats, folders, Spaces, the Library, memories, Snippets and MCP servers, but keep settings, the API key and the app lock.
- Erase & Reset → Factory reset - the same, plus all settings, and remove the API key and the app lock from the credential store. Loach then starts over with onboarding.
Both erase options ask you to type YES; importing and erasing also ask for your current app-lock credentials when a lock is set. A storage breakdown above those controls shows what chats, attachments, Spaces, the Library with its search index and everything else weigh in the database, and what your local Ollama models take on disk. The API key and the app lock are never part of an export - they live in the OS credential manager and stay there until you remove them. See Data management.