Android app · self-hosted server
The web, over SMS.
A phone with unlimited texts and no data can still search and read the web. textwire sends your request as a text to a number your own server owns. The server fetches the page, strips it to readable text, compresses it, and texts it back. The app puts the pieces together and shows a clean page you can tap through.
phone › 00 s bbc weather london
server 4 texts, 160 characters each
app 1. London - BBC Weather[1]
Sunny intervals, 17° ...
2. London forecast - Met Office[2]
phone › 01 l 00 1 tap [1]
server 12 texts text 7 lost
phone › 02 r 01 7 asks again
app page 1 of 3, ready to read
How it works
A request is one short text. A page is a dozen.
Two halves and a wire format: an Android app, a server on a machine that has internet, and a protocol small enough to read in one sitting.
The phone asks
A request is plain text a person could type: s weather london to search, g bbc.co.uk/news to open a page, l 00 3 to follow link 3. It leaves as an ordinary SMS on the phone's own plan.
The server fetches and shrinks
It loads the page on the real internet, keeps the article and drops the rest, turns links into numbered chips, compresses the text, and cuts it into frames that each fit exactly one 160-character SMS.
The app rebuilds the page
Frames arrive in any order. Each carries its number and a checksum, so the app knows what is missing, asks for only those texts again, and shows the page when the last one lands.
What you get
Built for a slow, paid, lossy wire.
Every design choice follows from one fact: each text the server sends costs money and may not arrive.
Search and browse
Search results come back as a numbered list. Tap a result, tap a link inside the article, turn to the next page. Each tap is a seven-character text.
Reader mode by default
Navigation, adverts and scripts never leave the server. What arrives is the title, the headings and the words.
Pages on demand
A long article is split into pages of twelve texts. You pay for page two only if you turn to it.
Works without the app
Add ! to any request and the reply is readable plain text, so any phone's messaging app can use the server.
An operator dashboard
The server shows today's spend against the budget, every request it answered, and a one-button probe of the SMS route.
A simulator for developers
The whole system runs in a terminal against recorded pages: no phone, no account, no texts sent.
Only your phones
The server answers numbers on its allowlist and nobody else, and refuses to fetch private or local addresses.
One wire format, two languages
Python generates golden test vectors; Kotlin must decode every one. The two halves cannot drift apart unnoticed.
Tested like it matters
100% branch coverage on the server and on the app's protocol and state machine, enforced in CI.
The numbers
Measured, not guessed.
The phone's requests ride on its text plan. The server pays for every reply, so the handbook's optimisation notes record what each technique saved, on pages held back from training.
| Reply | Texts | Cost |
|---|---|---|
| Status or help | 1 | $0.06 |
| Search results, five hits | 3 to 5 | $0.17 to $0.28 |
| One page of an article | 12 | $0.67 |
| The number itself | $2.50 a month |
Run it
See it work in a terminal first.
You need uv and make. The simulator runs the real server and a virtual phone against recorded pages, so nothing is sent and nothing is charged.
- Clone the repository and see what the machine is missing.
git clone https://github.com/tochi-mba/textwire.git && cd textwire && make doctor - Install the server's environment.
make install - Browse from the terminal. Type
s bbc weather london, thenl 1.make simulate - For a real phone: put a Twilio number in
server/.env, start the server and its dashboard, and install the app.make runmake android-install
The onboarding guide walks through all of it, and the operations guide covers buying the number, the budget and the dashboard.
Questions
What people ask first.
Is it really free on the phone?
The phone only sends short requests, a few dozen a day, which an unlimited-text plan covers. The server pays for the replies: about $0.67 for a page through Twilio in the UK. The daily budget caps that, and both the app and the dashboard show a running total.
How fast is it?
Twilio releases about ten texts a second, so a page leaves the server in a second or two. How long the mobile network then takes to deliver them has not been measured on a handset yet. Either way it is for reading an article or looking something up, not for video or web apps.
Has it run on a real phone?
The server, the protocol and the app are tested end to end in process, including lost and reordered texts. Results on a real handset are recorded only in the acceptance checklist, one dated line at a time; a line with no date has not been observed yet.
Can anyone text my server?
No. It answers only the numbers on its allowlist, and the daily budget is the ceiling on what a mistake or a spoofed sender could cost. SMS is not encrypted, so treat what you browse as visible to the carrier. The security notes say exactly what is and is not protected.
Why not use carrier multi-part messages?
A single SMS carries 160 characters; a part of a long message carries 153, and Android drops the whole message if one part is lost. textwire numbers its own frames, so one lost text costs one resend. The decision record has the detail.
Handbook
Written so a new engineer is useful on day one.
Onboarding
From a clone to a first change, without a phone or an account.
Architecture
The two halves, the path of a request, and the rules that hold it together.
The protocol
Frames, envelopes, requests and resends, byte by byte.
Operations
The number, the settings, the dashboard, and what to do when texts stop.
Testing
Every layer of tests, what each one proves, and how to run it.
Decisions
Every decision on record: what was chosen, why, and what it costs.