The Phone-Sized Companion
Wolffish runs on your machine — which has always meant being at your machine. The mobile app puts the desktop experience on a phone: the chat feed with its tool cards and delivered files, the conversation history, the usage ledger, and every settings page — Model, Channels, Services, MCP, Variables, Capabilities, Knowledge, Projects, Automations, Procedures, Customization, Usage, Data, Updates, Preferences, Appearance — laid out as the desktop’s settings sidebar turned into a navigation list. Since v1.0.235 it does that against your desktop. A phone pairs with this machine and carries the same conversations, the same settings, the same usage with it — over a link only the two devices can read. Since v1.0.236 it also carries everything that shapes those conversations: projects, procedures, automations and the three documents behind every reply are edited from either device, against the very same files. And since v1.0.239 the machine on the other end doesn’t need a screen at all — a phone pairs with a headless server exactly as it pairs with a desktop.Pairing
Everything lives in Settings → Channels → Mobile on the desktop. Pairing happens once, and there is no token to paste: the desktop offers a pairing and the phone claims it.Pairing QR
Generate a QR and scan it with your phone’s camera. The secret travels screen to camera — it never crosses the network. The QR also carries the relay address, so a custom relay needs no extra typing.
Pairing code
Generate a short code — eight characters, printed as
K7M9-2QXR — and type it on the phone when the camera can’t see the screen. Case, spaces and dashes don’t matter, and look-alike characters (O/0, I/1) are folded for you.The typed code carries only the secret. If you point the desktop at a custom relay, the phone must be told that address by hand — its pairing screen has a field for it, and the desktop’s offer screen shows the exact URL to type. The QR does this for you.
The Encrypted Tunnel
Once paired, the two devices talk end to end encrypted — X25519 key agreement, ChaCha20-Poly1305 for the frames. Everything is sealed on your devices before anything is sent, and only this desktop and your phone hold the keys. Each device keeps its own key and pins the other’s: no account, no password, nothing to sign into. The paired panel shows the link’s whole state — the tunnel status, the phone’s name, model and OS, when it paired and when it was last seen, the relay and rendezvous, both key fingerprints, the session, and the frame counters. Matching fingerprints on both devices mean nothing sits in between. Pairing keys are stored on the desktop through the OS key store — Keychain on macOS, DPAPI on Windows, the secret service on Linux — and the panel names the backend actually in use.The blind relay
The two devices are rarely on the same network, so something has to carry the bytes. That something is a blind relay, and its ignorance is the point:- It helps the two find each other at a rendezvous id derived independently on both devices — the only fact about a pairing it ever learns.
- It passes sealed frames along. It cannot read, alter or replay them.
- It stores nothing at all — no database, no logs, no accounts, no message history.
Disconnect vs. unpair
Two exits sit at the foot of the panel and the difference between them is the whole point. Disconnect drops the live link; the pairing survives and the phone reconnects when it comes back to the foreground. Unpair forgets the device — its keys are cleared and the phone has to pair again from scratch. Leaving from the phone’s side leaves nothing behind anywhere: badges are cleared — buckets, tray, app icon — the relay is told to zero its copy and forget the device’s push registration, and only then does the phone drop its keys and wipe everything it synced, back to a fresh install. Your desktop keeps the originals, so pairing again restores them.The desktop is the host: it parks on the relay and waits. The phone dials in when it is in the foreground and disappears when iOS suspends it, so every reconnect re-handshakes and nothing assumes continuity. A phone that has been in your pocket for an hour comes back to a freshly secured link.
What Crosses the Link
The phone is a second view of the whole app, not a message stream — so the desktop answers for far more than chat, and pushes changes as they happen instead of leaving the phone to poll:
Because a turn started on the phone is a real turn, it gets its own channel badge: conversations that began there wear a phone glyph in the desktop’s History list and conversations rail, next to the Telegram, WhatsApp, terminal, automation and procedure badges.
Credential fields on the phone stay placeholders — secrets are never entered on the phone. Keys are pasted on the desktop, where they live.
The Workspace, Editable
Pairing brought your conversations across; until v1.0.236 everything that shapes them stayed at the machine. Projects, procedures and automations were things the phone could show and only the desktop could change. All three are now edited from either screen.Projects
A project gathers the standing instructions and files that fresh conversations start from. Create one, give it an emoji from the picker, edit its instructions, add files from the phone itself, and file an existing conversation under it. A chat opened inside a project carries its briefing from the very first turn rather than picking it up a moment later.
Procedures
A saved prompt you run on demand — created, edited, deleted and run from the phone, with the run reporting back what the scheduler actually did.
Automations
A prompt that runs on a schedule, edited here as the same
heartbeat.md the desktop’s own editor writes — with the time of its next run and a play button beside it.Customization
Soul, User and Agents — who Wolffish is, what it should always know about you, and the procedures of yours that outrank the built-in ones — open as editors and save straight into the desktop workspace. These are the files that shape every reply on every surface, chat and Telegram and WhatsApp alike.
Turns you can score
Every finished answer carries a 0–10 rating bar. A score cast on the phone lands on the desktop exactly as the desktop’s own does, and a score cast anywhere else — the desktop’s bar, a bare number replied to Telegram — appears here without waiting for anything to reload. It is the same signal the nightly reflection learns from; it simply stopped requiring the desktop.Every conversation, without leaving the one you’re in
A sheet slides over the chat carrying the whole conversation list, grouped by recency, showing which project each one belongs to, which one is running right now, and where each one came from — the origin glyph rides the very first live update, so a conversation the phone has only ever seen running still wears its Telegram plane or terminal prompt from the first instant, instead of sitting blank until the metadata catches up. Switching is a tap, and the turn you were watching keeps streaming while you look. Its five destinations — Settings, Projects, Automations, Procedures and Customization — stay pinned at the top while the conversations scroll underneath them.What the desktop is busy with
Work that takes the desktop’s whole screen shows on the phone as a card in a stack over whatever screen you are on, with the prompt behind each one a tap away: an automation mid-run, a compaction, the nightly reflection, a memory index being rebuilt. They appear the moment the phone connects — including for a run that started while it was asleep — and they go when the connection goes, because a card claiming something is running on a machine the phone can no longer see is a card that lies. The phone stays usable while they happen instead of looking broken.Diagnostics from the phone
Collecting a conversation’s diagnostic bundle — logs, tasks, memory, context, settings, attachments, and the model’s own account of what went wrong — is something the phone can start, watch step by step, and hand to the system share sheet when it finishes. It runs behind the same single-flight guard as the desktop’s own button, so a run started here and one started there can never fight over the same files.A turn you are watching from the phone shows the question above the answer: the prompt travels with every live update, so a phone that pairs — or opens a conversation — mid-turn is no longer reading a reply to nothing. And a tunnel that comes up mid-run knows the run exists: on every connect the phone asks the desktop what is running right now, so a busy conversation shows its stop button and its streaming pulse instead of an idle composer, a parked approval card comes back to be answered, and the rating bar appears only once the desktop has actually said the turn ended — never over an answer still being written.
Phone Notifications
With Phone notifications on, the agent can reach you through itsnotify_phone tool when a run finishes, fails, or needs you. Nothing is ever sent automatically — the agent has to deliberately call the tool, and Off makes the tool refuse outright by removing it from the agent’s hands entirely. A tap lands where the notification points — including this run’s own conversation, via wolffish://chat?id=current — and if the phone is connected, the notification rides the live tunnel; if it isn’t, it goes out as a platform push instead.
The whole system now has its own page: the phases and how long each stays relevant, what the desktop stamps on every send and what the model is never trusted with, the fixed list of screens a tap can open, how unread badges stay honest, and exactly what the relay can and cannot see along the way.
Unread badges
Every notification that names a conversation feeds a per-conversation unread count — on the conversation rows here and in History, summed on the floating menu button, and as the number on the app icon, correct even before the app has woken. Clearing is reading: open the conversation and its count is gone, tray notifications included; there is no mark-as-read chore. The notifications page has the full mechanics.Task results
One switch decides how much of a run the phone’s feed relays. Off — the default — keeps it clean: assistant messages, file-bearing results, and errors. On relays every tool call and activity. Connection logging is separate and always on.The Chat Feed
The feed renders what the desktop renders — markdown replies, tool activity, delivered files — plus two cards worth knowing:- Reasoning — when a reply carried model thinking, a collapsed card sits at the end of the turn; tap to unfold the raw thinking text. The desktop app shows the same card, so both surfaces tell the same story about how an answer came to be.
- Status pills — a turn that stopped at the response limit or hit a connection error says so in place.
File Viewers
Tap any attachment to expand it full screen (sharing hands off to the system share sheet): images with pinch-to-zoom and pan, SVG with a lightbox, video and audio players, PDF, Word documents, spreadsheets — with CSV/TSV rendered as tables — Markdown, plain text, HTML with a preview/source toggle, and code files as line-numbered cards. PDFs render in the card on both platforms. Android’s WebView has never shipped a PDF engine, so the card used to hand the document off to whatever viewer the phone happened to have. The reader is now vendored into the app — a self-contained pdf.js page composed around the file’s own bytes — so the preview and the expanded document are the same on Android as on iPhone: a real first page, scrollable and pinch-zoomable. Nothing is handed to another app, the sandbox stays shut, and the page drawing the document can reach no file but the one you opened. Very large PDFs still go to the system viewer, which is where they belong.Usage On the Go
The Usage screen is the desktop’s Usage panel on one column: an Activity month grid, a day card that’s always visible (it opens on today and moves when you tap a day — tokens, cost, messages, per-model rows, Brave Search queries), six ranges from Today to All Time, overview stats (conversations, messages, total tokens, active days, longest streak, favourite model), a Costs section (total spend, top day, daily average), and per-provider cards. Each range reports its own window: every total is closed at today as well as opened at its start, so a figure labelled Today can never quietly carry tomorrow, and stepping from 3 Months to 6 Months to Year to Date moves the numbers instead of repeating them. The closing bound applies to the range totals only — the activity calendar and its day card still draw every row the ledger holds, since a month rendering blank because the clock hasn’t reached it is indistinguishable from a month with no usage. The range switch fills its row as one control, splitting the width evenly between the six.Browser Extension Rows
Settings → Services mirrors the desktop’s multi-browser extension roster: one row per connected browser profile — browser name with the profile email, version, and OS — with the screenshot settings editable from the phone. The pairing port stays desktop-managed: moving it restarts the desktop’s pairing server, which is the desktop’s own act. A snapshot from an older desktop that predates multi-browser support falls back to a single “Chrome extension” row with its port. Installing and pairing the extension itself always happens on the desktop.Updates
Two cards in Settings → Updates keep the surfaces distinct: This app (the mobile version and build, whether you’re on a store build or an over-the-air update, and an automatic-updates switch that genuinely governs update checks) and Desktop app (the mirrored desktop version, platform, and its own auto-update setting).Paired to a Server
The phone doesn’t care what answers the tunnel. Pair it with the desktop app on your laptop, or with a headless Wolffish on a VPS — the same feed, the same workspace, the same settings pages, over the same sealed link. For a server deployment this is the recommended interface: the terminal CLI administers the box, and the phone is the surface you actually live in — conversations streaming live, automations watchable as they run, notifications when something finishes or needs you, and projects, procedures, automations and the customization documents all editable against the server’s own files. Pairing works from the terminal —wolffish pair phone draws a scanner-friendly QR when the window fits it, and falls back to the typed code by itself when it doesn’t. And the phone reports the server’s terminal state right back: the Settings → Channels → CLI card says whether the wolffish command resolves on the desktop’s own PATH, whether autostart is registered, and which mechanism holds it — systemd, launchd, or schtasks. Registering with the operating system is the desktop’s own act, so this device reports it rather than changing it.
On a self-hosted relay, the typed code carries only the secret — enter the relay’s address in the Relay card on the phone’s pairing screen. The QR carries it for you.