Voice dictation for iPhone and Android.
Speak into your phone. Text shows up where you're typing. Speech-to-text runs on your phone by default, or on optional self-hosted VocaGateway, and never on a cloud speech service.
VocaPhone is the phone side of the Voca family, next to VocaLinux, VocaMac, and VocaWin. VocaWin is an unsigned Beta on GitHub Releases. SmartScreen is expected; it is not a store ship.
Licensed under AGPL-3.0: free to use, study, modify, and share, with copyleft that also covers modified versions offered as a network service.
| Client | State |
|---|---|
| Android | Public beta for Android 13+. releases · vocaphone.vocahq.com |
| iOS | Public TestFlight beta for iOS 17+ · join · or build from source (Mac, Xcode, signing team, physical iPhone) · iPhone guide |
| Gateway | Optional. Self-host VocaGateway on macOS/Linux or Docker when you want more models or shared compute |
On iPhone, VocaPhone is a custom keyboard plus a containing app. On Android it
is a normal system keyboard: select it when you want to dictate. Both insert at
the cursor (iOS through UITextDocumentProxy, Android through
InputConnection) with the same styles and transcription choices.
Both clients can run speech-to-text on the phone after a model download, or send recoverable audio to optional VocaGateway. Either way, the transcript inserts at the active cursor. A gateway is never required for on-device mode.
Important
iOS keyboard extensions cannot access the microphone. VocaPhone records in
the containing app, shares only versioned session state with the keyboard, and
then inserts through UITextDocumentProxy. Quick Dictation can keep that app
ready — for 10 or 20 minutes, or until you close the app — so most later
dictations do not require another app switch. The speech-to-text model still runs on the iPhone in on-device mode.
- The keyboard inserts the transcript at the cursor in the field you are already using
- After you download a speech-to-text model, on-device dictation needs no gateway
- Optional VocaGateway runs on a Mac, Linux box, or home server you control when you want larger models or shared compute. That path is self-hosted, not on-device
- 54 transcription languages plus Automatic, and four writing styles: Formal, Casual, Very Casual, and Excited
- Clean up speech, on by default: hesitation sounds ("um", "uh"), false starts and repeated words are dropped, and missing sentence punctuation is filled in, entirely on the phone with no model and no network call. Turn it off in Settings, or pick the Raw writing style, and the model's own words go in untouched
- Optional on-device translation where the model was actually trained for it: Canary between English, German, Spanish and French, and the multilingual Whisper models into English. Language says what you are speaking; Translate to says what comes back
- On iOS the containing app records, because a keyboard extension cannot use the microphone
| Platform | Project | Website | Source | Status |
|---|---|---|---|---|
| Linux | VocaLinux | vocalinux.com | VocaHQ/vocalinux | Available now |
| macOS | VocaMac | vocamac.com | VocaHQ/vocamac | Beta |
| Windows | VocaWin | vocawin.com | VocaHQ/vocawin | Beta · v0.1.0-beta.1 |
| iOS / Android | VocaPhone | vocaphone.vocahq.com | VocaHQ/vocaphone | Android beta / iOS TestFlight |
| Gateway | VocaGateway | vocagateway.vocahq.com | VocaHQ/vocagateway | Early |
Org: github.com/VocaHQ. Contact: hello@vocahq.com
Public beta APKs for Android 13+ are on GitHub Releases. Install one, enable VocaPhone in Android's keyboard settings, grant microphone (and notifications if asked), then download an on-device speech-to-text model.
To build from source:
cd android
# macOS default; on Linux try $HOME/Android/Sdk
export ANDROID_HOME="${ANDROID_HOME:-$HOME/Library/Android/sdk}"
# "full" is the flavor to develop against; "fdroid" is the from-source-only
# build described under Build flavors in android/README.md.
./gradlew assembleFullDebug
# Uninstall any pre-rename Local Flow build first. Application IDs differ, so
# `adb install -r` will side-install next to io.github.mrsunglasses.localflow.
adb uninstall io.github.mrsunglasses.localflow 2>/dev/null || true
adb install -r app/build/outputs/apk/full/debug/vocaphone-fullDebug.apkSee the Android client guide for keyboard setup and the supported gateway address forms.
To just use it on an iPhone, join the public TestFlight beta — no Mac, no Xcode, no signing. A TestFlight build expires after 90 days and the beta has a tester limit, so the source route below stays the one that always works.
The Simulator needs no Apple account at all:
cd ios
just doctor # checks Xcode, xcodegen, and a simulator runtime are present
just run # generates the project, builds, boots a simulator, installs, launchesios/project.yml is the real project source; just run (and every other iOS
recipe) regenerates VocaPhone.xcodeproj from it before building, so don't
hand-edit the .xcodeproj. Prefer working in Xcode itself? just edit does
the same regeneration, then opens it.
Add the keyboard the same way you would on a device: just settings opens
iOS Settings on the simulator, then General → Keyboard → Keyboards → Add
New Keyboard → vocaphone, with Allow Full Access turned on (see
privacy.md for exactly what that is and isn't
used for). Typing, autocorrect, and swipe work immediately. For actual
dictation, Settings → Transcription → On this iPhone plus a downloaded
model is the fastest path with nothing else to configure, or point
Settings → Transcription → Gateway at an optional VocaGateway.
On your own iPhone (just device, phone connected and trusted): code
signing has to already work in Xcode first. The project ships with VocaHQ's
own identifiers (com.vocahq.vocaphone and friends, team 92962VK378; see
decisions.md). If you have access to that team, select
it on all three targets (VocaPhoneApp, VocaPhoneKeyboard,
VocaPhoneLiveActivity) under Signing & Capabilities; automatic signing
does the rest. If you don't (most outside contributors), either ask a
maintainer to comment /build ios on your pull request for a signed ad-hoc
IPA (see CONTRIBUTING.md), or run
it under your own free Apple ID by changing bundleIdPrefix and the three
PRODUCT_BUNDLE_IDENTIFIERs in ios/project.yml, the App Group string in all
three .entitlements files, and AppConfiguration.swift's
appGroupIdentifier/keyboardBundleIdentifier. Don't commit that change.
Grant microphone access on first launch, add the keyboard as above, and turn on Full Access. Complete the physical-device checklist in device setup.
The gateway checkout is a submodule. iOS also needs the Sherpa ONNX xcframeworks, which are fetched at build time (not Git LFS):
git clone --recurse-submodules https://github.com/VocaHQ/vocaphone.git
cd vocaphone
just ios fetch # or: bash ios/ThirdParty/SherpaOnnx/fetch.shOn an existing clone: git submodule update --init --recursive and the same
fetch. Without that step the iOS project cannot link the on-device engine.
Pin bumps live in
CONTRIBUTING.md.
On-device mode needs no gateway. When you want larger models or shared compute, self-host VocaGateway and point the phone at it. Native vs Docker, pairing, and how the phone reaches the host are in that repository and in docs/deployment.md.
Development uses just. Each application has a
justfile, and the repository root aggregates them, so every recipe works from
the root or from inside the application directory:
just ci # all three applications, skipping absent toolchains
just gateway test # gateway: lint, types, dependency audit, tests, Compose
just gateway-sync # optional: local gateway/ → tip of main (does not commit)
just gateway-pin-status
just ios ci # iOS: regenerate the project, build, run unit tests
just android ci # Android: assemble, unit tests, lint, Room schema
just doctor # what each toolchain is still missingiOS and Android CI live in this repository. Gateway quality and container
builds run in vocagateway; just gateway test still exercises the submodule checkout locally. just --list shows the
rest, including running the apps (just ios run, just android run,
just gateway run), streaming logs, installing onto a physical phone, and
managing the container deployment.
Optional: with direnv installed, direnv allow once after
cloning puts the gateway virtualenv and the Android SDK's platform-tools on
PATH and exports ANDROID_HOME, so pytest and adb resolve without a
prefix or a full path. Everything works without it. See
CONTRIBUTING.md.
The generated Xcode project is checked in. Run just ios gen after changing
ios/project.yml and commit the result; CI fails when it is stale. Keyboard,
microphone, background audio, and insertion changes still require
physical-device verification.
ios/ Swift app, keyboard, Live Activity, shared state, tests
android/ Kotlin app, voice keyboard, foreground dictation service, tests
gateway/ Git submodule → VocaHQ/vocagateway (gateway + WebUI)
docs/ Architecture, device setup, privacy, decisions, historical plans
| Guide | Covers |
|---|---|
| Android client | Building the APK, guided setup, voice keyboard, and privacy boundaries |
| Gateway reference | Native service, Compose, models, configuration, health, and CLI commands (vocagateway) |
| Deployment | Pointers into vocagateway for native vs Docker, pairing, and host setup |
| Device setup | Apple signing, keyboard installation, and physical-device acceptance |
| Releasing | Platform-prefixed tags, Android-only / iOS-only / joint drops, changelogs |
| TestFlight | App Store Connect setup, archiving, and TestFlight distribution |
| Google Play prep | Full-flavor AAB, upload signing, listing and Console checklist |
| Tailscale | Private HTTPS ingress for the gateway |
| Architecture | Components, state transitions, engine boundary, and observability |
| Privacy | Audio lifecycle, authentication, metrics, and threat model |
| Troubleshooting | Keyboard, microphone, model, network, and Docker failures |
| Decisions | Current assumptions and choices still requiring confirmation |
| iOS plan | Original iOS implementation plan and acceptance criteria |
| Android plan | Original Android implementation plan and acceptance criteria |
| Contributing | Development workflow and required checks |
| Security | Private vulnerability-reporting process |
- The iOS keyboard never records audio; Android's IME delegates capture to the microphone foreground service and never uses clipboard insertion.
- Quick Dictation standby buffers are discarded rather than saved or uploaded.
- Successful audio is deleted by default; failed sessions expire after the configured retry window.
- Operational metrics contain counts and timings only and reset when the gateway restarts.
- iOS does not provide a public API to reopen an arbitrary previously active app. If Quick Dictation expires, the containing app must open and the user returns manually.
- Secure fields and apps that disable third-party keyboards remain iOS platform limitations.
- On Android, the VocaPhone keyboard inserts through
InputConnectionand does not read surrounding field contents. Sensitive input types disable dictation.
See CONTRIBUTING.md for setup, required checks, and pull request expectations. SUPPORT.md is where to ask for help and what to include (or omit). CODE_OF_CONDUCT.md is Contributor Covenant 2.1. SECURITY.md is the private vulnerability-reporting process.
Report suspected microphone, recording, token, gateway, or tailnet vulnerabilities through the private process in SECURITY.md, not a public issue.
VocaPhone is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0), matching VocaMac and VocaLinux (both AGPL-3.0).
You may use, study, modify, and redistribute the software under AGPL-3.0. Because VocaPhone includes an optional network gateway, AGPL also requires that modified versions offered as a network service make their corresponding source available.