Why We Open-Sourced the District AI Apps, and What You Can Build With Them
The District AI apps for iPhone, iPad, Android and Linux are open source under Apache-2.0. Why we published them, and what you can build from the code.
When you install our app, you give it your microphone, your camera and your notifications, and you sign it in to your workspace, with every call and transcript in it. Until now you had to take our word for what it does with them. You no longer do: the source code of the District AI apps for iPhone, iPad, Android and Linux is public, under the Apache-2.0 licence, in the same three repositories we build and ship the apps from.
Why we published the apps
The apps are the one part of District AI that runs on a device you own. Everything else runs on our servers, and for those we publish what a customer needs to check us: where each kind of data is kept and every outside company that helps us process it. The same rule applies to the apps, and for software on your phone or your computer the most direct answer is the code itself.
So the promises in each app's security policy are now things you can read rather than take on trust:
- The Android app asks for no SMS, contacts, call-log or location permission, and its notifications carry identifiers, never message content or a phone number.
- The iOS app keeps its sign-in only in the Keychain, where a backup cannot carry it to another device.
- The Linux app signs in through your own browser and never sees your password. It keeps its sign-in in the desktop's keyring, never in a plain file, and as a Flatpak it asks for the network, the display, the GPU, sound and the system's sleep notices, and nothing else.
- A build made from the iOS or Android repository reports no crashes unless someone supplies the settings for it at build time. The Linux app has no crash reporting in it at all.
Built and released in the open
These are the repositories we ship from, with their issues, changelogs and security policies in the open. Each app is now built and released by a GitHub Actions workflow in its own repository, started by a protected release tag, and a tag that is not on the main branch or does not match the app's version is refused. The iOS and Android builds are signed there with keys the workflow borrows from our Google Cloud account for the length of one run, so no signing key or store credential is stored in the repositories or on GitHub, and only that repository's release environment can ask for them. Sending a build to App Review or to Google Play's review still waits for our explicit approval. Each Linux package carries a signed attestation of the build that made it, which you can check with the GitHub CLI.
The versions in the stores today were built from the same repositories before those workflows existed, on a maintainer's machine, and each repository's release names the commit its store build came from: App Store build 4102 for iOS 1.2, and the Google Play release of Android 1.0.
What is open source, and what is not
All three apps are published under Apache-2.0. You can read them, build them, change them and send your changes back. The District AI and Distronode names, logos and app icons are trademarks and are not part of that licence, so an app you build and distribute uses its own name, its own icon and its own identifier.
The District AI service the apps talk to is not open source. Everything the apps show comes from that service, so a build from the source still needs a District AI account to sign in. The apps themselves are not samples: each repository is the complete source of its app, the same code the store builds and packages are made from.
Without an account with us
Today every one of these apps needs a District AI account to sign in, because the service is where calls are answered, and where the transcripts, messages and contacts the apps show are kept. We want the apps to work without an account with us too.
We have not worked out what that looks like, or whether it can work. It could mean pointing an app at a server you run yourself, or at services you already use, and some of those may turn out not to work at all. What the apps should work with is a question for the people who would use them that way, so we are asking before we build anything. If that is you, tell us in the discussion which app you would use, what you would connect it to, and what you would use it for.
What is in the three repositories
District AI for iOS is one universal SwiftUI app for iPhone and iPad. Most of its logic lives in a core package, DistrictCore (the models, the API client, and the sign-in and call state machines), which builds and tests on Linux as well as on a Mac. UI tests cover the signed-out screens, and no certificates or provisioning profiles are committed.
District AI for Android is written in Kotlin and Jetpack Compose. It is a self-managed softphone that places and answers calls through Android's Telecom framework, and the repository holds no signing key, store credential or crash-reporting token.
District AI for Linux is a Rust workspace with the GTK 4 and libadwaita app on top. Nothing below the app depends on GTK, so the API client, the sign-in and the app's state build and test on a machine with no display. Calls use LiveKit and the project's own build of LiveKit's libwebrtc, which leaves out the H.264 and H.265 codecs and FFmpeg, and CI tests them against a media server of its own: two-way audio, end-to-end encryption and reconnecting.
The same recorded answers, in all three. Each repository carries contract fixtures: responses recorded from the District AI service by the service's own test suite, with fictional data. Each app's tests decode them strictly, so a field the service sends that an app does not model fails that app's tests instead of shipping unnoticed. The strictness is in the tests only, so an installed app keeps working when the service adds a field. The Linux app carries the Android set and a desktop set of its own, with a checksum for every file.
The Android security policy also answers the question a secret scanner raises first. Two kinds of value in the repository look like credentials: the Firebase client configuration that ships inside every Firebase app, and end-to-end encryption keys in three fixtures, made by the service's test suite from fixed inputs, that protect no room. The policy lists each one and why it is there, and the repository's secret scan allows exactly those values, so a real key added beside them is still reported.
What you can build with them
Build and test, with no account. For iOS, swift test in
Packages/DistrictCore runs the core tests with no simulator, no network and
no account, and xcodebuild builds the app for the simulator with signing
turned off. For Android, ./gradlew assembleDebug builds a debug version and
./gradlew testDebugUnitTest runs every module's unit tests. For Linux,
cargo build --release --locked builds the app, and
cargo test --workspace --exclude district-app runs the tests of everything
below the interface. Each README gives the exact commands and what to install
first.
A client of your own. You can change an app and ship your own build under the fork rules: your own name, icon and identifier, and on iOS your own signing team. Push does not carry over: on iOS it is tied to the App Store build's team, and an Android fork that sends push needs its own Firebase project. A Linux build from source has no calls until you build it with them, which needs clang 21 or newer, as its CONTRIBUTING.md describes. Signing in still needs a District AI account.
The API, as it really answers. The contract fixtures are the most direct record of how the District AI API answers: response bodies generated by the service's own test suite from its real route handlers, with fictional data.
Pieces for your own calling app. Apache-2.0 lets you take code into a project of your own, as long as the licence and its notices go with it. The Android app keeps its LiveKit wrapper behind a CallEngine interface in a module of its own. The iOS app keeps its CallKit, PushKit and LiveKit code together in one Platform folder. The Linux app's call engine is a crate of its own, district-call, and so is its OAuth 2.0 sign-in with PKCE, district-auth.
Where to get the apps
The iOS app, for iPhone and iPad, is on the App Store, and the Android app is on Google Play. The Linux app is on the district-linux Releases page, as a .deb for Ubuntu 24.04, Debian 13 and newer, and as a Flatpak bundle for any distribution with Flatpak, both for x86_64.
Where to ask, contribute and report
Contributions happen on GitHub, at district-ios, district-android and district-linux. Questions go to each repository's Discussions, bugs to its issues, and changes to pull requests, and each repository's CONTRIBUTING.md says what a pull request needs before it is reviewed. A security problem goes privately, through GitHub's private vulnerability reporting as each SECURITY.md describes, never in a public issue.
Each app also has a read-only mirror on GitLab, as bridgewatch does, as a second place to read the code: district-ios, district-android and district-linux.
Where to start
Each app has its own page: District AI for iOS, District AI for Android and District AI for Linux. Our open-source page lists all five projects we publish, bridgewatch and District Scheduler among them. Why we publish at all, and why we send our fixes back to the projects we build on, is in our earlier post.
Frequently asked questions
Can I build and run the apps from the source?
Yes, and building and testing need no District AI account. Each repository's README gives the exact commands: the iOS app builds for the simulator with signing turned off, the Android app builds a debug version with a JDK, the Android SDK and the Gradle wrapper, and the Linux app builds with Rust and the GTK 4 and libadwaita development files. Signing in needs a District AI account. An unsigned iOS build stops at a Try again screen rather than Sign in, because without a signing identity it has no Keychain access, and a Linux build from source has no calls unless it is built with them, as the released packages are. Any build you distribute must use its own name, icon and identifier.
Where do I get the apps?
The iOS app, for iPhone and iPad, is on the App Store, and the Android app is on Google Play. The Linux app is on the district-linux repository's Releases page, as a .deb for Ubuntu 24.04, Debian 13 and newer, and as a Flatpak bundle, both for x86_64. Each repository's release names the source its store build or packages came from.
Why is the District AI service not open source too?
District AI is our commercial service, and the apps are how customers reach it. We published the part that runs on a device you own, where reading the code is the most direct way to check what it does. For the service, we publish where each kind of data is kept and every outside company that helps us process it, on our data residency and sub-processor pages.
Will the apps work without a District AI account?
Not today: signing in needs a District AI account. We want the apps to work without an account with us too, and we have not yet worked out what that looks like or whether it can work. We are asking first what people would use them with, in a public discussion on GitHub linked from this post and from each app's README.
Where do I ask a question, or report a security problem?
Questions go to the Discussions tab of the repository concerned, and bugs to its issues. A security problem goes privately, through GitHub's private vulnerability reporting on that repository, as its SECURITY.md describes, and never in a public issue. If you cannot use GitHub, all three apps also take reports at opensource@distronode.com. A security problem in the District AI service itself goes to security@distronode.com, because the service's code is not in any of the three repositories.

