Overview
Alice is a personal assistant that runs on a home server and lives in Telegram: she keeps to-dos and reminders in Google Calendar, tracks who owes money, and answers questions. Alice Watch is her Android app. It started as a single trick — talk to Alice from a cheap smartwatch — and grew into the place where everything she keeps can be seen and edited: today's to-dos, the agenda, a back log of things to play, watch and read, a wishlist, a physical collection, debts and a chat.
A watch that can only make phone calls
The watch is a Redmi Watch 3 Active. Its firmware is closed, it runs no third-party apps, and its official companion only shows notifications. It can, however, place a phone call through the paired phone with its own microphone and speaker.
So Alice got a phone number. Calling her from the watch's contacts is intercepted
on the phone by a CallRedirectionService: the call never reaches the cellular
network. It is redirected to a self-managed ConnectionService that belongs to the
app, which answers at once, plays a short tone and records the watch's microphone
over the Bluetooth hands-free (SCO) link until the call is hung up. The recording is
uploaded to the home server, transcribed with Whisper and handed to Alice as a voice
note; her answer arrives on Telegram, which the phone forwards to the watch.
Getting there meant learning a few things the hard way. A freshly installed or force-stopped app cannot be bound by Telecom, so the redirection times out until the app is opened once. The phone's MediaTek DuraSpeed optimiser force-stops any app swiped out of Recents, which silently broke the call path until the app was allowed in it. Failed uploads wait in an outbox and retry on the next call, and error notices wait until the screen is off so they never interrupt.
The watch itself talks to the phone through Gadgetbridge instead of the official app, which is what lets the assistant's to-dos appear on the wrist: every pending item is mirrored to the calendar the watch already syncs.
Everything else, in one app
The phone app is a client of the assistant's HTTP API, reached over a Tailscale Funnel with a bearer token, so the phone itself needs no VPN. The same functions the assistant uses back every endpoint, so a to-do created from the app lands in the calendar and on the watch exactly like one dictated to Alice.
- Today — the day as a sentence, the agenda, the to-dos without a time, what people owe, and what the assistant has spent on API calls today.
- Agenda — to-dos and events from tomorrow on, grouped by day. Today lives only in Today, so nothing appears twice.
- Lists — the back log (games, films, series, anime, anime films, manga and books, moved off Notion), a wishlist with prices, the money owed and a collection of what is physically on the shelf, each copy with its platform, format, edition, price and photo. The back log marks what is already in the collection.
- Alice — a chat with the same assistant, by text or by holding a button to talk.
Every list can be edited from the app: tap to edit, swipe right to complete, swipe left to delete, and an undo that only reaches the server once the notice closes. Writes are logged on the server, so "who deleted this?" has an answer.
Covers without typing
Anything added to the back log gets its cover on its own. The server looks up the title in the source that fits the category — AniList for anime and manga, Open Library for books, TMDB for films and series, IGDB for games — and stores only the image URL; the phone downloads and caches the pictures with Coil. When a guess is wrong, "Change cover" shows the best five candidates. The 170 items migrated from Notion found 160 covers in one pass, with AniList's rate limit respected by waiting and retrying instead of failing.
Design
The look follows iOS more than Material: Inter in place of SF Pro (which cannot be shipped outside Apple platforms) using its optical-size axis for large titles, grouped inset lists over a grey background, a tab bar without the Material pill, form sheets with Cancel and Save at the top, segmented controls, and chat bubbles in the style of iMessage. The palette is black and white with a light and a dark mode switch; notices drop from the top as compact capsules that can be swiped away, and the undo notice shows a bar with the time left.
Stack
Kotlin, Jetpack Compose with Material 3 as the base, Coil for images and a Glance widget for the home screen; the call path is plain Android Telecom and AudioRecord. On the server, Node.js scripts with a shared JSON store (file lock plus atomic rename), the assistant runtime for the agent turns, Groq's Whisper for speech, and a hermetic test that runs the whole HTTP API against a fake calendar before every deploy.








