Bots that live on your own machine. Each one gets a memory, a schedule and a computer of its own. Shut the lid and they carry on.
Download · What a bot gets · Get started · Phone app · Develop
Warning
botato is alpha software, provided as is and without warranty of any kind. Every release is a pre-release. Bots run commands, drive a browser, use accounts you connect to them, spend money against your own API keys and act on a schedule while nobody is watching. Language models are unpredictable and can be manipulated by content they read. What your bots do is your responsibility. Do not give one access to anything you cannot afford to lose, break or expose, and keep your own backups. Sections 7 and 8 of Apache 2.0 say the same thing in the usual words.
- It runs on your computer. No account to make, no server of ours, no telemetry. Your bots, files, keys and conversations never leave the machine.
- A bot is somewhere, not something. Each one owns a session and a workspace on disk and remembers across restarts, rather than being a box you type into and close.
- They share rooms. A channel holds several bots and you. They read what the others said and answer each other, which is the difference between a set of assistants and colleagues.
- They work while you are away. Routines run on a schedule and report back. botato holds the machine awake for them and on a Mac it can keep the lid from stopping them.
- Your phone reaches them. Directly, from anywhere, with nothing in between.
- Bring your own model. Claude Code by default, or the Gemini CLI, or any of 5,559 hosted models, or Ollama on your own machine for nothing.
| A memory | A session and workspace on disk that survives restarts, plus a memory file it maintains itself, seeded from its name and role |
| A face | Head, eyes, brows, a resting smile and a mark. 7,776 combinations before colour, derived from the bot's own id so no two look alike. It blinks, thinks with a cloud overhead, jumps when a turn lands and slumps when one fails |
| A voice | One of the machine's own, or Kyutai's Pocket TTS: 24 recorded people rather than a synthesiser, fetched on the first call, about a second a sentence on the processor. Nothing said leaves the machine |
| A computer | Optional. A Linux desktop in a container with Firefox or Chromium, a terminal and a screen you can watch or take over. Each has its own filesystem, network policy and machine fingerprint, so ten bots do not look like one machine wearing ten hats |
| Routines | Work it does on a schedule, reported into its own chat or into a channel |
| Connectors | GitHub, Gmail, Calendar, Notion, Stripe and others, connected once and scoped per bot. botato runs its own OAuth flows and keeps the tokens in your system keychain |
| An engine | Which tool answers for it, chosen per bot and changeable mid-conversation |
- Say who you mean. Type
@and it offers whoever is in the room.@everyoneis yours alone: a bot cannot summon the room. A message naming nobody is addressed to the room, which works out who should take it. - Threads, pins and unread marks, with a brighter mark when a bot used your name.
- Call the room. Faces side by side, whoever has the floor lit, one voice at a time. Every word is written into the channel as it is said, so the meeting is minuted before it ends.
- Stand-ups. A routine can be a meeting rather than an instruction. Every bot in the channel takes a turn and none is asked how its week went: each is handed what actually ran, what it said, what broke and what is next on its own calendar. A bot with nothing to report says so.
| Engine | What it needs | Notes |
|---|---|---|
| Claude Code (default) | The CLI, signed in | A Claude Pro or Max subscription covers it. Setup installs the CLI if it is missing |
| Gemini CLI | The CLI and an API key | Google has retired the free personal login for this client |
| Any hosted model | A base URL and a key you hold | 166 providers and 5,559 models, by way of models.dev |
| Ollama | Nothing at all | On your own machine, no key and no cost |
The seam is inference.rs: an engine says how to run a turn, how to read its output, how it takes a bot's connectors and which models it can be asked for. Everything else, from the roster to the sandbox to the phone, speaks botato's own vocabulary and never learns which tool answered.
The difference that is not cosmetic is memory. Claude Code keeps a conversation on disk and resumes it by id. The Gemini CLI cannot, so botato keeps a transcript of every bot itself and replays what fits. That is also why a bot can change engine mid-conversation and carry the thread across: the transcript belongs to botato rather than to whatever last answered.
- Nothing runs on anyone else's computer. The API is bound to loopback, so no port is open on any network the machine joins.
- Connectors are botato's own. It disables claude.ai's connectors and runs its own OAuth flows, so a flow you completed once is not repeated because you changed model.
- Backups are one encrypted file, written on a schedule to a folder you name. Point it at iCloud Drive, Dropbox or a disk you plug in. It carries no API keys, no OAuth tokens and no phone pairing, so it is not a credential store.
- The format is written down. Argon2id to XChaCha20-Poly1305, the cost parameters travelling in the header and authenticated with it.
scripts/open-backup.pyrecovers a backup with nothing but Python andcryptography, on a machine that has never seen botato.
- Download the latest release for macOS or Linux. macOS builds are signed and notarised, so they open without warnings.
- Pick an engine. Setup installs the Claude Code CLI for you, or point a bot at Ollama and pay nothing.
- Make a bot. Give it a name and a line about what it is for. Everything after that happens on your machine.
- Optionally give it a computer. botato downloads and manages a container engine itself: lima and the docker CLI on macOS, rootless podman on Linux. Docker Desktop is not required.
- Optionally pair your phone. Scan the QR code the laptop shows.
mobile/ is a React Native app for iOS and Android. It holds no state of its own: every request is answered by the desktop window using the same code its own UI calls, so the phone gets whatever the desktop can do rather than a second implementation that drifts. Calls are the one thing it cannot do yet.
How it reaches your laptop. The only way in is a QUIC connection made directly between the two devices, in which the laptop's identity is its public key (iroh). Same guarantees at home and on mobile data:
- Encrypted end to end. When a direct path cannot be punched through a NAT, packets fall back to public relays that forward ciphertext they cannot read.
- The laptop cannot be impersonated without its private key and neither can your phone: the token it is given is bound to the phone's own key, so a copy is refused from any other device.
- No account, no tailnet, no port forwarding, nothing of ours in the middle.
Pairing is a QR code the laptop shows and the phone scans, carrying the laptop's address and a six-character code that lasts five minutes, works once and is burned after five wrong guesses.
Speaking QUIC needs native code, so the app needs a development build rather than Expo Go. See mobile/README.md.
Requirements
- pnpm and a Rust toolchain.
- On Linux,
cmake,clangandlibclang-devon top of the usual webkit development packages: whisper.cpp is compiled in and bindgen reads its headers. - On ARM Linux, build with
CC=clang CXX=clang++. gcc refuses ggml's half-precision NEON intrinsics with "target specific option mismatch" and clang does not. - For calls on Linux, espeak-ng to speak with and one of paplay, aplay or ffplay to play with. GStreamer's base and good plugin sets, which a desktop will already have, are what let the webview record.
Commands
| Command | What it does |
|---|---|
pnpm install |
Install dependencies |
pnpm tauri dev |
Run the desktop app |
pnpm dev:app |
The same dev build as a bundle, with its own scratch roster |
pnpm dev:app exists because of one macOS rule: the microphone is granted against an app bundle's stated reason for wanting it and tauri dev runs a bare executable with nowhere to state one. Calls can speak but not listen under tauri dev.
Custom speech. Point BOTATO_TTS at a command to use Kokoro, Piper or whatever comes next, without botato shipping a model:
BOTATO_TTS='pocket-tts generate --voice {voice} --output - --text -'
BOTATO_TTS_VOICES='Alba,Giovanni,Estelle,Charles'The command reads the text on stdin and may either play the audio or write it to stdout. botato works out which by whether anything came out.
Builds are produced by tagging a release. See .github/RELEASING.md.
| Path | What it is |
|---|---|
src/ |
The desktop UI. Vanilla TypeScript, no framework |
src-tauri/src/ |
The Rust side: turns, sandboxes, connectors, plugins, the phone server |
sandbox/ |
The Linux desktop image a bot's computer runs |
mobile/ |
The phone app and the Rust crate that gives it QUIC |
website/ |
The marketing site |
Worth knowing about the Rust: engine.rs is the container engine botato installs and inference.rs is what answers for a bot. Different things, unfortunately similar words.
Version 0.6.0 and honest about what that means.
| Desktop and sandboxes | Used daily |
| iOS | Pairs, streams replies, survives restarts and has reached a laptop at home from a phone on mobile data |
| Android | Builds and runs, but only exercised against a stand-in desktop |
| Hosted engines | Answered for real through Ollama over the same API a paid provider speaks, with tools. That test is in the repository |
| Gemini CLI | Wired up and its flags checked against a real install. Its stream mapping is written from documentation rather than from output anyone has watched |
Small local models are the honest weak point. llama3.2:3b calls a tool correctly from a clean conversation and then, once its own history contains a tool call it wrote out as prose, will happily imitate itself instead of calling anything. Bigger models do not do this and nothing in botato can stop a model that does. The bound on that loop is twelve rounds.
The desktop binary is about 11 MB because it uses the system webview instead of bundling a browser. Most of that is QUIC and whisper.cpp. The models it speaks and listens with are fetched on first use rather than shipped, which is why adding them cost a megabyte here rather than four hundred.
Issues and pull requests are welcome. The codebase is small and the seams are documented at the top of each Rust module, so start there.
Apache-2.0. Use it, fork it, build on it, ship it in something you sell. The licence asks only that you keep the notice and say what you changed.
The name is not part of that grant: LICENSE covers the code and the Apache licence explicitly does not hand over trademarks. Fork it and call it something of your own.