Privacy
Brut is built local-first, and privacy isn't a policy bolted on afterward — it's the architecture. Here is, precisely, what stays on your machine and what (very little) leaves it.
What never leaves your machine
- Your prompts, images, renders and video. All of it is written to your disk (or your NAS), inside your project's
outputs/folder. Brut has no server in the generation path — your work is never uploaded to us, and we cannot see it. - Your graphs and projects. Stored locally as files. A
.brutpackor NAS share moves them between your machines; nothing routes through a cloud. - Your API keys. Stored in your OS keychain (Windows Credential Manager). Used only for direct calls from your machine to each provider. Never written into a graph, never sent to us, never in a
.brutpack. - The engine log. The desktop app writes the engine's console output to
%LOCALAPPDATA%\Brut\logsso problems can be diagnosed. It stays on your disk — a feedback report never includes it unless you attach it yourself. And the app never phones home for updates: the beta has no auto-update, so there's no update check leaving your machine either.
Generation calls go from your machine straight to the provider (Google, OpenAI, Kling, Magnific, Topaz, …) on your key. Those providers see the requests you send them, under their own privacy terms — Brut is never in the middle.
To be precise about that promise: there is no aggregator that Brut operates in the call path — no server of ours, ever. If you choose to run a model through a route (an aggregator you subscribe to yourself, when you hold no direct key), your requests go from your machine straight to that service, on your credential, under its privacy terms — and the node, the confirm dialog and the ledger always say so.
One provider sends nothing at all: video upscales through Topaz Video AI (local) run entirely on your own GPU via the Topaz desktop app you installed — the clip never leaves your machine.
One setup step downloads a tool rather than talking to a provider: clicking Install Kling CLI (for the Kling subscription provider) fetches Kling's official command-line client from the npm public registry — a one-time, user-initiated download of about 1 MB, integrity-checked, carrying no data of yours beyond the download request itself. Brut never auto-downloads anything.
Your studio timeline stays local
Brut keeps a studio timeline per project — the running record of runs, results, and your conversations with Marcel, the built-in companion. It lives in a plain text file inside the project (ledger/activity.jsonl), on your disk or your NAS, and is never uploaded — it travels only where the project itself travels. When you export a project to a folder it's included by default (it's a backup); when you make a .brutpack to hand off, it's left out by default — a checkbox lets you decide either way each time.
Chatting with Marcel works like every generation: the conversation goes from your machine straight to the text-model provider you picked (Google, OpenAI or Anthropic), on your own key, under that provider's terms. Brut is never in the middle, and every call is written to your local spend ledger with its token counts and cost. Images you attach to a chat message (the 📎 button) are sent to that same provider as part of that one message — never re-sent on later turns, and only files inside your project's outputs can be attached at all.
When Marcel acts on your canvas, what he reads to do the job — your graph's structure, node prompts and parameters, output file names, journal search results — becomes part of that same conversation, so it reaches the text provider you picked, and nothing else. The actions themselves (placing nodes, wiring, running) happen entirely on your machine, and anything that would bill a key stops at an itemized confirm first.
When Marcel speaks up on his own (the Assist slider at Reactive and above — failure diagnoses, run commentary, the recap when you open a project), the material he reasons over is the same local record: recent timeline lines, the error text, what's still running. That goes to your chosen text provider on your key, exactly like a chat message, and each remark is a ledgered call you can see. Set the slider to Off and nothing is ever sent unprompted.
What Marcel remembers also stays on your disk. He keeps a taste profile — a plain-text note about how you like your images — tied to your account and stored beside your library. It is per-account, private, and never synced or exported: it does not travel in a folder export or a .brutpack. Project notes (a small memory for each project) live inside the project and travel with it, like the timeline. Both are plain text you can open and edit; Marcel proposes additions from your recent work and applies nothing to the profile until you approve it.
The local engine is locked to the app
Brut runs a small engine on your own machine (127.0.0.1). To make sure only the Brut app can drive it — and not some other web page you happen to have open in the same browser — the engine mints a secret token when it starts and requires it on every action that spends money or changes your files. The app receives that token automatically; nothing else on your machine can guess it, so nothing else can make Brut generate, delete, or spend on your behalf.
The only thing Brut ever sends
When you're signed in, the engine sends a small heartbeat — at startup and once a day — so we can count active seats during the beta. That's it. Here is the entire payload, verbatim:
{
"install_id": "a uuid minted once on this machine",
"app_version": "…",
"engine_version": "…",
"os": "Windows",
"os_version": "…",
"arch": "…",
"ts": "…"
}
- No content. No prompts, no images, no filenames, no graph data — ever. By construction: the code only ever assembles those seven fields.
- Nothing while signed out. If you're not signed in, no heartbeat is sent at all.
- You can see this exact JSON any time in ⚙ Settings → Account.
Feedback — only what you type, only when you click send
The 💬 Send feedback button is the one other thing that can send data, and it's entirely user-initiated: nothing is ever sent until you press Send. A report carries your message, your account email (so we can reply), and — only if you leave the checkbox on — a diagnostics block: the same seven heartbeat fields plus the last few error messages from the Activity panel. The modal shows that block byte for byte before you send it ("Show exactly what will be sent"). Never your graphs, images, prompts or keys.
Sign-in
Identity runs through Supabase (magic link or Google/GitHub). It's used only to know who's using a seat — never to store your work. The engine holds your session, not the browser: your refresh token is kept in your OS keychain, and access tokens are verified locally against a cached public key (so it works offline). This is identity only.
The website
getbrut.app and this documentation load nothing from third parties — fonts are self-hosted, and there are no analytics scripts or trackers. The site has its own short notice covering the beta form, sign-in and emails: getbrut.app/privacy. The beta sign-up form is the one place you hand us an email, and only if you choose to. When your seat is approved we send one approval email to that address, and the download page asks you to sign in with the same Supabase account the app uses — that sign-in is checked against the approved list to serve the installer, and nothing else is recorded.
In short
Your keys, your work, your machine. The only thing we ever learn is that a version of Brut is running on some install, on some OS — and only while you're signed in.