The iOS app
A client in your pocket, with HomeKit, QR pairing, local discovery and a model on the phone.
The iOS app puts Parlour on the phone you already carry. It records, sends the recording home and plays the answer back, just as a satellite does. Everything that thinks, holds a key or touches the house still runs on the Mac at home. The phone adds HomeKit, which it knows about without any setup, and a small model of its own for when the house cannot be reached.
The app has three tabs: Talk, where you hold the button and speak; House, your HomeKit rooms and accessories; and Settings, which server, which room and what the app is allowed to do.
The app lives in apps/ios and uses only the public routes in
Clients: /health to check, /v1/models to confirm the
token, /voice for a recording and /ask for text. Anything the app does, you could build against those routes
too.
Building it
The Xcode project is generated from apps/ios/project.yml instead of being
checked in, because nobody can review a .pbxproj.
brew install xcodegen
pnpm exec nx run ios:app # generate the project and open it
pnpm exec nx run ios:xcodebuild # compile for the simulator
pnpm exec nx run ios:xcodetest # run ParlourTestsParlour for iOS is not on the App Store yet, so for now you build it yourself.
It needs iOS 18 or newer. Signing is up to you. Set PARLOUR_DEVELOPMENT_TEAM
before generating, or pick a team in Xcode once. HomeKit and the local network
both need a real device, not the simulator.
The first run
A fresh install walks you through setup before it shows the talk button, in the same order and words as the menu bar app, so it takes about a minute with the Mac nearby:
- Connect. Scan the pairing code. The servers Bonjour found, and typing an address and token by hand, are folded away until you ask. The app checks the server there and then, so a wrong token shows up now rather than on your first question.
- Voice. Allow the microphone, and say which room the phone usually lives in, so "lights off" means the lights in there.
- Extras. Answering on the phone when home is out of reach. A phone that cannot run the on-device model skips this step.
- Finish. What was set.
Settings has Run setup again at the bottom. A phone that was already paired before setup existed counts as set up.
What it asks for
You should know what a voice assistant is allowed to do before you trust it. So the Settings tab lists the four permissions it relies on, with a mark against each and an Ask button for any not yet granted, and every prompt says what the permission gives you.
| Permission | What it gives you | Asked for when |
|---|---|---|
| Microphone | Recording while you hold the talk button | The Voice step of setup, or the first time you hold the button |
| Local network | Finding the server with Bonjour, then talking to it | The app opens |
| HomeKit | The rooms and accessories on the House tab | You open that tab |
| Speech recognition | Understanding a request on the phone when the server cannot be reached | The phone first has to answer by itself, with the on-device answer switched on |
| Camera | Scanning the pairing code on the Mac | You tap Scan pairing code, in setup or in Settings |
HomeKit and multicast networking are entitlements as well as prompts. Apple
grants multicast to the team, so a build signed with another team needs it
left out of Parlour.entitlements or its own grant. If you say no to the
local network, iOS does not ask again, so Settings and setup offer
Open Settings, where the Local Network switch is. NSAllowsLocalNetworking
allows plain HTTP to the house, and only on the local network, because the
server sits on a private address and speaks HTTP. The phone page makes the
same trade. It is also why a reverse proxy is worth having if you want to
reach the house from outside.
Pairing with your Mac
The quickest way to connect is a QR code. Run parlour pair on the Mac, or
open Pair a phone on the menu bar app's Status tab, then tap
Scan pairing code in the app's Settings. The Camera app reads the code too
and hands it to Parlour. One code carries the server's address and its access
token together, so the two can never come from different servers. The token
goes into the phone's keychain, never into a backup, and Settings checks the
server straight away.
A pairing link can also arrive from outside the app: from the Camera, or from
any web page or message with a parlour://pair link in it. So before taking
one, the app asks whether to pair with the server it names and shows the
address everything you say would go to. Only pair with a code your own server
showed you.
Finding the server
Without a code, the app finds the server the same way a satellite does. It browses for
_parlour._tcp. Bonjour returns a service rather than an address, so the app
opens a connection to the service and reads the host and port off the
resolved path. Anything it finds appears in Settings.
An address you type in, pick from that list or take from a pairing code wins over anything found. From then on, it is the only server the app talks to, just as a satellite pins the first server it trusts. You can also name the room the phone is in, so a follow-up lands in the right one.
Browsing is also what raises the local network prompt. So the prompt appears as the app opens, not while someone is trying to say something.
Managing the server
The Server tab manages the Mac from the phone, over the routes in Managing the server:
- Model servers. Whether the local model and whisper are running, with buttons to start, stop and restart them. Stopping one asks first, because the house cannot answer the same way without it.
- Pipeline. How many requests run at once, how many can wait per room, how many tasks one request can become, when to give up, and whether to read requests first. Saving restarts the agent so the change takes effect, and the steppers stop at the same limits the server enforces.
- Maintenance. Runs the doctor, shows the end of any of the three logs, and restarts the agent.
The server has the final say on every change and explains any refusal in its own words. For example, it refuses to start a model that is too big for the Mac, or to restart something that was restarted a moment ago.
The model on the phone
The app can answer on its own using Apple's Foundation Models, which need iOS 26 and Apple Intelligence switched on. It is off by default, and it is a fallback, not a first stop. The phone has no tools, so it cannot switch anything on, read a sensor or look anything up. The phone defers to the house for the same reason the house tries its local model first.
When it is on and the server cannot be reached, the phone transcribes the recording with on-device speech recognition and answers it on the device. The answer is labelled as coming from the phone, not from home. Nothing in that path leaves the handset. When the model is unavailable, Settings says why: too old an iOS, a phone without it, Apple Intelligence switched off, or the model still downloading.
HomeKit
The House tab shows the homes, rooms and accessories HomeKit already knows about, and can switch anything with a power state. It is deliberately not how Parlour controls the house. The agent's tools go through Home Assistant on the server, the one place that knows what is connected to what. The House tab is a second opinion in your pocket, and a screen that still works when the Mac at home is off.