2026-11-07
My second iPhone lives at home. I use it from anywhere.
I have two phone numbers in two countries. For years the second iPhone lived in a drawer, and every time I needed it — a bank's verification code, a WeChat account tied to that number, a call from someone who only has that number — it was in the wrong place. Carrying two phones got old. Leaving it at home meant missing things.
So now the second iPhone stays at home, on its charger, and I use it from the phone in my pocket. When it rings, my phone rings. I answer, and I'm on the call. I can open any app on it, read the code, type a reply in Chinese, swipe through it like it's in my hand.
It's a stock iPhone. No jailbreak, no profile, nothing installed on it. What makes it work is an old laptop sitting next to it.
How it works
The laptop is a 2016 Lenovo with a Core m3 and 4 GB of RAM, running Ubuntu. It's connected to the phone by a USB cable and two Bluetooth adapters, and it pretends to be four things the iPhone already knows how to talk to.
A screen recorder. Over USB, the iPhone sends its own H.264 video — the same stream QuickTime uses for screen recording. The laptop's integrated GPU re-encodes it down to a few Mbit/s so it survives a cellular link, and a fork of Sunshine streams it to TracePort, my fork of the Moonlight iOS client.
A keyboard and a mouse. The first Bluetooth adapter presents itself as a keyboard and a pointer. With AssistiveTouch on, iOS shows a cursor, so taps, swipes and typing all work. For swipes that need to feel native — flicking between home screens — the gateway replays the gesture as a real touch through Apple's UI-testing framework instead.
A Bluetooth headset. The second adapter is a hands-free headset. When a call comes in, the gateway takes the call audio off the Bluetooth link (wideband, 16 kHz), sends it down the stream, and plays my microphone back into it. I've done hour-long WeChat calls this way. The other side had no idea.
A smartwatch. iOS shares notifications with watches through a Bluetooth service called ANCS. The gateway subscribes to it, so it sees a WeChat or WhatsApp call the moment the phone does, and sends a VoIP push to my phone. My phone shows a normal incoming-call screen. I answer, the gateway presses "accept" at home, and the stream opens.
Remote access is over Tailscale. Nothing goes through a server of mine except Apple's push service. The gateway is a little over 12,000 lines of Rust; it started as Python.
It has to run on its own
A demo that works on my desk is easy. A phone that works while I'm on another continent is the real job. The gateway unlocks the phone after a restart, restarts whatever gets stuck, falls back to AirPlay if USB capture dies, and pushes me an alert when it needs a person. Most of the work was here.
Things that were harder than they should have been
- Call audio drifted later and later. Over a few minutes, the other person's voice fell further behind. The cause: a virtual sound card whose clock ran 0.03% slow against the phone, and every small stall left a delay that never drained. The fix was rate matching, not a bigger buffer.
- Swipes needed long drags. Flicks between home screens bounced back. I measured what the phone actually received (a test page logging touch timestamps) and found the testing framework plays touches at 60 Hz: points that don't land on a frame boundary get stretched, so a quick flick arrived as a slow drag. Resampling the gesture onto frame boundaries fixed it.
- iOS Settings won't list a notifications-only Bluetooth accessory. It shows up once it also claims to be a keyboard.
- A GPU decoder held on to the last frame until the next one arrived, so on a still screen the picture lagged the sound by seconds.
- Pretending to be Apple hardware backfires. Advertising Apple's vendor ID on the fake keyboard got cached by iOS per address and silently poisoned keyboard input until the phone was rebooted and re-paired.
- When bluetoothd crashes, everything forgets. Recently the Bluetooth daemon on the laptop crashed and restarted. Calls still rang, but WeChat and WhatsApp calls didn't, and after a phone restart the gateway couldn't type the passcode. The daemon had forgotten the keyboard's service record, the pairing agent and the notification advertisement, and turning address privacy back on had generated a new identity key the phone didn't recognise. Each service now notices the restart and re-registers itself; I tested it by killing the daemon on purpose, and everything was back within 15 seconds.
Why not call forwarding, Google Voice or an eSIM?
They move the number, not the phone. The apps tied to that number — banking, WeChat, government apps, two-factor codes — live on the device, and many refuse a new device or a login from abroad. Here they see the same phone on the same home network as always.
Try it
The iOS client, TracePort, is free and open source (GPL). The gateway isn't — I set it up for people myself, one home at a time: hardware, configuration and support.
If you have a second phone you'd rather leave at home, that's what traceone.io is for.