Skip to main content

Overview

There are two ways to set up the Omi app for development:

Automatic Setup

Recommended for most developersOne command setup against the local backend harness

Manual Setup

For custom backendsFull control over configuration and backend
Don’t want to build from source? Download the official app from the App Store or Google Play.

Prerequisites

Before starting, make sure you have the following installed:

Flutter SDK

Includes Dart - the core framework

Xcode

Required for iOS development

Android Studio

Required for Android development

CocoaPods

iOS dependency manager
You’ll also need NDK to build Opus for ARM devices.
The local backend harness additionally needs Python 3.11 (not 3.12+ — the backend pins 3.11), a Java runtime for the Firestore emulator, and firebase-tools (or npx). make dev-up names any of these that are missing.

Build the App Automatically

This is the recommended way to get started. setup.sh builds the dev flavor against the local backend harness — the Python API on port 8000 and the Firebase Auth emulator on port 9099, using the demo-omi-local Firebase project. iOS builds address them as 127.0.0.1; Android builds default to the emulator’s host alias 10.0.2.2.
setup.sh does not start the backend or the emulator — start the harness first (step 1 below), or the app builds and launches but every request fails to connect.Do not point this build at https://api.omiapi.com/. That API verifies Firebase ID tokens against Omi’s production Firebase project, and Firebase tokens are project-scoped, so a demo-omi-local token is rejected with 401 Unauthorized on every call — sign-in appears to succeed and nothing else works. Production data requires the explicit beta profile (see Mobile beta).

Video Walkthrough

Setup Steps

Start the local backend harness

From the root of the repository, one-time setup then start the services:
make dev-init builds backend/.venv from whatever python3 resolves to, and the backend requires Python 3.11 — make sure that’s what you get, or the harness fails later with import errors.No provider API keys? Use fake providers instead:
Check what came up with make dev-status, and stop it later with make dev-down. Ports, seeded local users, and troubleshooting live in the local emulator runbook.

Navigate to the app directory

Run setup for your platform

Run in simulator

Open the app in your IDE and hit run:
  • Xcode: Open app/ios folder
  • Android Studio: Open app/android folder
Or run from terminal:
The automatic setup runs entirely on your machine — local API, local emulators, no production data — making it the fastest way to start building apps and making changes. On a physical iPhone, set OMI_DEV_HOST to your Mac’s LAN or Tailscale address before running both setup.sh ios and make dev-up (in the same shell, or exported so both commands see it) — this now makes the harness itself listen there too, not just the app you build. Only a private address works (LAN, e.g. 192.168.x.x, or Tailscale/CGNAT, e.g. 100.x.x.x); a public address is rejected. Use OMI_DEV_BIND_HOST instead if you want the harness to bind a different address than the one the app is compiled to reach.

Build the App Manually

Manual setup gives you full control, allowing you to use your own backend.

Verify Flutter Installation

Ensure Flutter is installed by following the official Flutter Installation Guide.Verify your setup:

Get Flutter Dependencies

From the app directory, install packages:

Install iOS Pods

Navigate to iOS directory and install CocoaPods dependencies:

Configure Environment

Create your environment file from the template:

Add API Keys

Edit .dev.env and add your API keys:
Be sure to include the trailing / in API_BASE_URL or you’ll get malformed URLs. If you change this later, delete the builds folder and recreate the runner.
Whatever backend you point at must verify Firebase ID tokens against the same Firebase project the app signs into. Tokens are project-scoped, so a mismatch returns 401 Unauthorized on every authenticated call while sign-in still appears to succeed. Omi’s shared https://api.omiapi.com/ verifies against the production project and will reject tokens from the demo-omi-local emulator or from your own Firebase project.

Run Build Runner

Generate necessary files:

Setup Firebase

Firebase is mandatory for the app to run.
setup.sh installs local emulator Firebase configs (the demo-omi-local project) for the dev flavor. If you’re using the local backend harness (the common case), they’re already in place — skip to the next step. These configs only work against the Firebase Auth emulator; they are not credentials for any hosted Firebase project.Never run flutterfire configure against Omi’s bundle IDs — it overwrites the prebuilt prod credentials in app/ios/Config/Prod/, app/lib/firebase_options_prod.dart, and app/android/app/src/prod/.
If you need your own Firebase project (custom backend):
  1. Follow the official Firebase Flutter Setup through Step 1
  2. For Apple login, create an identifier first
  3. Configure flutterfire config using your own bundle IDs and your own project — not Omi’s
  4. Generate SHA1/SHA256 keys for your keystore and add them to Firebase (StackOverflow guide | Official Docs)
If you’re facing auth issues, enable Google/Apple sign-in in the Firebase Console under Authentication → Sign-in method.

Run the App

Select your target device and run:
To build an APK:

Code Formatting

We use dart format with a line length of 120 characters. To automatically format code on commit, install the pre-commit hook:

Troubleshooting

  • Run flutter doctor -v for detailed output
  • Follow the suggestions to fix each issue
  • Make sure all required SDKs are installed
  • Ensure CocoaPods is installed: sudo gem install cocoapods
  • Run pod install in the ios directory
  • Try pod repo update if dependencies fail
  • Check NDK is installed via Android Studio SDK Manager
  • Verify JDK version matches requirements (JDK 21)
  • Accept all Android licenses: flutter doctor --android-licenses
  • Enable Google/Apple sign-in in Firebase Console
  • Verify SHA1/SHA256 keys are added to Firebase
  • Check bundle IDs match your Firebase configuration
setup.sh builds against http://127.0.0.1:8000 but does not start anything. Run make dev-up from the repo root first, and confirm with make dev-status.On a physical device, 127.0.0.1 is the phone — set OMI_DEV_HOST to your Mac’s LAN or Tailscale address before running both setup.sh (so the build points at your machine) and make dev-up (so the harness actually listens there — it defaults to loopback-only otherwise, which is why a device build alone used to reach nothing). Export it in the same shell so both commands see it. The Android emulator uses 10.0.2.2 by default.
The app and the backend are on different Firebase projects. Firebase ID tokens are project-scoped: a token minted for one project cannot be verified by a backend initialized for another, so authentication succeeds locally and every authenticated API call is rejected.This shows up on the manual path, where you choose both sides: your own Firebase project signs the user in while API_BASE_URL points at a backend initialized for a different project. Point API_BASE_URL at a backend that verifies against your project.Omi’s shared https://api.omiapi.com/ is never a valid target for a self-configured build — it verifies against Omi’s own Firebase project, and the demo-omi-local configs setup.sh installs are emulator-only fakes that no hosted backend can verify. Production data requires the explicit beta profile.
Error Message:
Cause: This error occurs because iOS security restrictions prevent the Dart VM from changing memory protection during JIT compilation in Debug mode on physical devices.Solutions:
  1. Use iOS Simulator (Recommended for Development):
    • In Xcode, select an iOS Simulator (e.g., “iPhone 16 Pro”) instead of your physical device
    • The simulator doesn’t have this restriction, so Debug mode works normally
    • Or run: flutter run --flavor dev (it will use a simulator if available)
  2. Use Release/Profile Mode for Physical Devices:
    • If you need to test on a physical device, build in Release or Profile mode:
    • Or in Xcode, select “Release” or “Profile” scheme instead of “Debug”
Note: This is a known Flutter/iOS limitation. Debug mode with JIT compilation requires memory protection changes that iOS blocks on physical devices for security reasons.

Need Help?

Discord Community

Search the help channel or ask questions

GitHub Issues

Report bugs or browse existing issues

Backend Setup

Set up your own Omi backend

Build Apps

Create Omi apps and integrations

Firmware Setup

Flash and update device firmware

Contribution Guide

How to contribute to Omi