iMessage Bluetooth bridge for Linux
BlueFerry brings messages from a paired iPhone to a Linux desktop. It can receive and send SMS and iMessage, use the phone's contacts, and optionally mirror other iPhone notifications. It talks directly to the phone over Bluetooth; there is no Mac relay, Apple login, cloud service, or subscription.
This is experimental software. Development has mostly used an iPhone 16 Pro Max running iOS 26.5, and Apple may change the behavior BlueFerry relies on. Don't make it your only way to receive an important message yet.
BlueFerry is not a reimplementation of Apple's private Messages protocol. It uses the Bluetooth accessory services exposed by the iPhone. On the tested phone, the Message Access Profile carries both SMS and iMessage; iOS still decides how an outgoing message is delivered.
There are native clients for GNOME, KDE, and Quickshell. They share one local backend, so pairing, contacts, preferences, and message history are the same whichever client you open.
New messages appear as they arrive and can be answered from the conversation. You can write to a phone number, an Apple-ID email address registered with iMessage, or a synced contact. BlueFerry only knows about messages it has seen; it is not an iCloud history browser and pairing will not download your complete Messages archive.
Group chats work when BlueFerry can safely reconstruct the participants from the message and its matching iPhone notification. Bluetooth MAP does not send a group identifier or roster, so ambiguous groups remain read-only rather than risk replying to the wrong people.
Attachments, reactions, typing indicators, FaceTime, calls, and a complete sent-message history are not supported. MMS, RCS, and named groups have not been tested well enough to promise anything.
Clone this repository and run:
./build.sh -siThe build uses dependencies from the official Arch repositories—nothing from
the AUR or PyPI—and produces four ordinary pacman packages:
blueferry-backend, blueferry-gtk, blueferry-qt, and
blueferry-quickshell. Running ./build.sh without -i builds them without
installing them. The finished package archives are written to
packaging/arch/.
See packaging/arch/README.md if you want to build individual packages or understand exactly what pacman owns.
Open the client for your desktop:
blueferry-gtk # GNOME
blueferry-qt # KDE
blueferry-quickshell # QuickshellOn first launch it opens the iPhone setup page.
- Let BlueFerry check the Bluetooth controller. If it offers to activate Bluetooth support, approve the Polkit prompt. Bluetooth will restart once, briefly disconnecting other devices.
- Open your Bluetooth settings, click Scan, pick your phone, then hit Pair. When this computer shows up in Other Devices, tap it and approve the prompts. The confirmation code can take around 15 seconds to appear on some controllers.
- Confirm the same code on both devices when prompted.
- On the iPhone, open Settings → Bluetooth → ⓘ beside the computer and enable Show Message Notifications and Sync Contacts.
- Wait for Messages and Contacts to show as connected. For the default encrypted storage, approve the desktop wallet prompt that opens automatically.
BlueFerry keeps a valid existing bond and will not repeatedly re-pair the phone. If you need a truly clean repair, forget the device on both sides and start again with the iPhone's Bluetooth page open.
For a machine without a graphical client, the same setup is available from:
blueferry pair-setupOnce pairing is complete, opening a client starts the backend automatically.
It also reconnects after normal Bluetooth interruptions and restarts itself
after package upgrades; routine use should not require systemctl --user.
The native bar panel lives in omarchy-iphone:
omarchy plugin add https://github.com/erikwb/omarchy-iphone.gitIts popup follows Quattro's own panel controls and shows connection health and recent conversations. The full Quickshell client handles messages, pairing, and preferences.
Enable it from Setup › Plugins. If BlueFerry is not installed, clicking the widget opens a terminal with the source-build instructions. The standalone Quickshell client also follows the active Quattro theme.
The iPhone page can show message notifications only (the default), all iPhone notifications, or none. Ordinary app notifications are shown and discarded; they are not added to message history or exposed as a notification feed. Messages arriving through both MAP and ANCS are deduplicated.
By default, message history and synced contacts are encrypted with a random key stored in GNOME Keyring or KDE Wallet. If the wallet is locked, live messages still work but history and contact lookup remain unavailable until you unlock it. The iPhone settings also offer unencrypted local storage, with an explicit warning, or Do not retain local data, which clears the cache and keeps new events ephemeral. Changing storage modes clears existing local history and cached contacts so encrypted and plaintext records are never mixed.
BlueFerry stores configuration in ~/.config/blueferry and local state in
~/.local/state/blueferry. Pacman leaves those directories alone when the
packages are removed. Delete them yourself if you want a complete reset; the
encrypted mode's key is named “BlueFerry local storage key” in your wallet
manager.
The default popup lifetime and history limits can be changed in
~/.config/blueferry/local.env:
BLUEFERRY_SHOW_NOTIFICATION_CONTENT=false
BLUEFERRY_NOTIFICATION_TIMEOUT_MS=8000
BLUEFERRY_HISTORY_RETENTION_DAYS=30
BLUEFERRY_HISTORY_MAX_EVENTS=10000
BLUEFERRY_HISTORY_MAX_PAYLOAD_BYTES=268435456Restart the user service after changing those environment settings.
The graphical clients cover normal use, but the CLI is handy for diagnostics and scripts:
blueferry sms-list
blueferry sms-send '+15551234567' 'on my way'
blueferry sms-send person@icloud.com 'hello from Linux'
blueferry sms-send Alice 'running late'
blueferry contacts-sync
blueferry history-clear
blueferry doctorsms-list asks the live phone first and falls back to retained history.
Ambiguous contact names are resolved interactively rather than guessed.
Start with the iPhone page in the app. It reports Messages, Contacts, and ANCS separately, which matters: messages and contact sync can work even when the optional notification connection does not.
For logs and prerequisite checks:
blueferry doctor
journalctl --user -u blueferry -fIf messages work but names do not, run Sync Contacts or
blueferry contacts-sync. When reporting a hardware problem, include the
iPhone model, iOS and BlueZ versions, and Bluetooth controller model. Remove
phone numbers, names, message bodies, and Bluetooth addresses from logs first.
BlueFerry uses three Bluetooth paths:
- MAP over OBEX carries messages, inbox queries, read state, and sends.
- PBAP over OBEX supplies vCard contacts.
- ANCS over BLE supplies optional app notifications and sometimes enough display information to identify an unnamed group.
MAP and PBAP need a BR/EDR-capable controller. ANCS additionally needs usable Bluetooth LE support. The full path has been tested with a MediaTek MT7922, but BlueFerry checks controller capabilities rather than requiring a particular vendor.
One unprivileged user daemon owns the Bluetooth sessions and exposes a small session D-Bus API to the clients. Private records are returned by method call, not broadcast in signals. Clients reply through opaque thread identities so a UI cannot silently change the recipients of an existing conversation. The default local encryption protects data at rest; unencrypted storage deliberately gives up that protection, and neither mode is a sandbox against another process already running as the same Unix user.
The pairing helper configures BlueZ through Polkit and presents the computer as an ordinary accessory. It does not exploit the phone, bypass pairing consent, or speak a hidden iCloud protocol. The long-running daemon is unprivileged and there is no sudoers rule.
BlueFerry used iphonebridge, created by Gabe Shatunovsky, as its initial implementation point.
The ANCS constants and wire-format parser/builders are adapted from ANCS4Linux, by Paweł Zmarzły and Bradley Harmon, under GPL-2.0-or-later.
The details live in ARCHITECTURE.md, PROTOCOL.md, and TESTING.md.
BlueFerry is licensed under GPL-2.0-only.
