agentleFS
BasedHardwareBasedHardware/omi/app/AGENTS.md

omi / app

AGENTS.md14k starsChanged 10 months agoMITView on GitHub

UI: contract. Speakers: SpeakerNames/DiarizationLabel (lib/ui/format/); EpisodePresentation.participants counts names. This handles: pub get, build_runner, gen-l10n, and flavor configuration. For physical-device builds, use the wrapper: it owns dev + local_dev and prod + mobile_beta pairing plus auth env setup. Direct builds must first run scripts/validate_mobile_build_config.sh --flavor <dev|prod> --profile <profile> with the matching OMI_APP_PROFILE; release/profile helpers do this too. OMI_MOBILE_BUILD_MODE=profile installs an AOT build that opens untethered (debug builds need flutter run attached on a physical iPhone; see README).

  • Reads credentials
  • Installs packages

Trending

More talk lately.about the whole repository

Dec 2025: 0 mentionsJan 2026: 2 mentionsFeb 2026: 0 mentionsMar 2026: 1 mentionApr 2026: 13 mentionsMay 2026: 1 mentionJun 2026: 0 mentionsJul 2026: 1 mentionAug 2026: 1 mentionSep 2026: 5 mentionsOct 2026: 40 mentionsNov 2026: 2 mentions
Dec 2025Jun 2026Nov 2026
Mentions a month of the BasedHardware/omi repository that our weekly crawl found. There is no adoption data for this file yet.

Who's talking about BasedHardware/omi

The biggest 5 of 83 mentions linking to the repository that our crawl found. Each line is their own headline.

See all 83

Talked about on GitHub, YouTube, Bluesky and Hacker News (83 times).

On GitHub · 50

45 more on GitHub

On YouTube · 21

16 more on YouTube

On Bluesky · 7

2 more on Bluesky

The file

We split this AGENTS.md into the rules it gives an agent

8 rules. About 0 are common, 1 is distinctive, and 7 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 7

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Never run flutterfire configure — it overwrites prod credentials.

    line 36
  2. Very specific:

    After editing the contract, regenerate: flutter pub run build_runner build

    line 49
  3. Very specific:

    All user-facing strings use context.l10n.keyName.

    line 121
  4. Very specific:

    Add/change/remove a key with scripts/l10n.py (add/set/remove).

    line 122
  5. Very specific:

    If expired, calls AuthService.instance.getIdToken() for Firebase refresh

    line 129
  6. Very specific:

    After any Flutter UI edit, verify with agent-flutter (Marionette is integrated in debug builds).

    line 151
  7. Distinctive:

    Must reconnect after every hot restart (kills VM Service session).

    line 161
  8. Very specific:

    Prefer find type X / find key "name" over hardcoded @ref.

    line 164

≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
AGENTS.md

App (Flutter)

UI: contract.

Speakers: SpeakerNames/DiarizationLabel (lib/ui/format/); EpisodePresentation.participants counts names.

Build Bootstrap

Flavors

  • dev: Android com.friend.ios.dev, iOS com.friend-app-with-wearable.ios12.development — uses .dev.env, Firebase project based-hardware-dev
  • prod: Android com.friend.ios, iOS com.friend-app-with-wearable.ios12 — uses .env, Firebase project based-hardware-prod
  • raybanDat: camera-capable iOS target with the same iOS development identity; scripts/rayban_dat.sh excludes mcumgr only for that transaction, then restores the default graph.

Version string

pubspec.yaml (1.0.543+992) is the local placeholder. Store binaries ignore it: Codemagic sets BUILD_NAME from the latest store version and BUILD_NUMBER to max(store)+1 (pubspec seeds only with no store history). Analytics/Crashlytics build_number is OMI_BUILD_NUMBER. Authoritative: stores = Codemagic; local/dev = pubspec; analytics = OMI_BUILD_NUMBER.

Release

GREEN gate (13:15 UTC) → train: iOS phased 100% after 12h; Android 1%→10%→50%→100%; rollout-advance every 4h on a ≤26h GREEN receipt. Never withdraw an iOS version Apple has to ship a newer one. .github/agent-docs/mobile-release-process.md.

Generated Files (never edit)

envied, json_serializable, pigeon (lib/pigeon_interfaces.dart → lib/gen/ + iOS/Android stubs), and flutter_gen: flutter pub run build_runner build. ARB → flutter gen-l10n (lib/l10n/app_localizations*.dart). Never edit *.g.dart / *.gen.dart.

Setup Sequence

bash setup.sh ios    # or: bash setup.sh android

This handles: pub get, build_runner, gen-l10n, and flavor configuration.

For physical-device builds, use the wrapper: it owns dev + local_dev and prod + mobile_beta pairing plus auth env setup. Direct builds must first run scripts/validate_mobile_build_config.sh --flavor <dev|prod> --profile <profile> with the matching OMI_APP_PROFILE; release/profile helpers do this too. OMI_MOBILE_BUILD_MODE=profile installs an AOT build that opens untethered (debug builds need flutter run attached on a physical iPhone; see README).

Firebase Config

Never run flutterfire configure — it overwrites prod credentials. Config files:

  • Dev: android/app/src/dev/
  • Prod: android/app/src/prod/
  • Local emulator: lib/firebase_options_local.dart

Native Bridge

Pigeon Interface (bidirectional, iOS ↔ Dart)

  • Contract: lib/pigeon_interfaces.dart — paired host/Flutter APIs for the watch recorder, BLE, and Ray-Ban Meta
  • Dart side: lib/gen/pigeon_communicator.g.dart
  • iOS side: ios/Runner/PigeonCommunicator.g.swift
  • Android side: android/app/src/main/kotlin/com/friend/ios/PigeonCommunicator.g.kt
  • Implementation: ios/Runner/RecorderHostApiImpl.swift
  • After editing the contract, regenerate: flutter pub run build_runner build

MethodChannel (Phone Calls)

  • Channel: com.omi/phone_calls + EventChannel com.omi/phone_calls/events
  • Dart: lib/services/phone_call_service.dart
  • iOS: ios/Runner/PhoneCalls/OmiPhoneCallsPlugin.swift
  • Android: android/app/src/main/kotlin/com/friend/ios/phonecalls/PhoneCallsPlugin.kt
  • Methods: initialize, makeCall, endCall, toggleMute, toggleSpeaker

Pigeon (Phone Mic — conversation capture)

  • Contract: lib/phone_mic_interface.dart → lib/gen/phone_mic_pigeon.g.dart + ios/Runner/PhoneMic/PhoneMicPigeon.g.swift + android/app/src/main/kotlin/com/friend/ios/phonemic/PhoneMicPigeon.g.kt
  • Regenerate: dart run pigeon --input lib/phone_mic_interface.dart
  • Modules: iOS ios/Runner/PhoneMic/ (self-healing AVAudioEngine capture; interruptions/routes recover natively); Android android/app/src/main/kotlin/com/friend/ios/phonemic/ (AudioRecord with self-healing rebuild + silencing detection; PhoneMicForegroundService keeps background capture alive; batch opus encode via a JNI shim over the plugin-shipped libopus)
  • Dart service: lib/services/mic/native_mic_recorder_service.dart behind ServiceManager.phoneMic; chat memos/speech profile stay on flutter_sound via ServiceManager.mic; MicArbiter arbitrates the two stacks
  • Events carry a Dart-minted session id (start(mode, sessionId)); Dart drops foreign-id events, start() onto a live session adopts the new id and re-emits state, and stop() always forwards to native then tears down locally once
  • Two capture modes fixed at start(mode): stream (frames → Dart → socket/WAL) and batch (Transcribe Later — opus → WAL-compatible audio_omibatchphone[auto]_…bin; no frames cross to Dart; liveness = onBatchProgress: iOS 4s healthy/1s fault, Android 1Hz; Dart 10s unchanged). Selection: CaptureController.streamRecording (explicit/offline); omibatchphoneauto uploads on reconnect

On-device speech deadlines and cleanup: contract.

MethodChannel (On-device tool surface)

  • com.omi.device_tools (lib/services/device_tools/device_tool_surface.dart, iOS DeviceToolsService.swift): search_contacts, propose_message, request_permission. iOS verb is propose — the compose sheet is the approval; cancelled ≠ delivered. Rides device_tools on POST /v2/messages + tool: SSE frames, never surfaced to chat UI. Contract: desktop/macos/docs/device-tool-surface.md.

Permission Matrix

PermissionAndroidiOSFeature
MicrophoneRECORD_AUDIONSMicrophoneUsageDescriptionRecording, speech profile
BluetoothBLUETOOTH_SCAN, BLUETOOTH_CONNECTNSBluetoothAlwaysUsageDescriptionOmi device connection
LocationACCESS_FINE_LOCATIONNSLocationUsageDescriptionBackground features
ContactsREAD_CONTACTSNSContactsUsageDescriptionPeople recognition
CalendarREAD/WRITE_CALENDARNSCalendarsUsageDescriptionCalendar integration
Camera—NSCameraUsageDescriptionQR/photo features
NotificationsPOST_NOTIFICATIONS(automatic)Push notifications
BackgroundFOREGROUND_SERVICE_* (5 types)UIBackgroundModes (7 modes)Continuous capture

Test Strategy

Test Structure

  • test/spine/ — protected contracts; test/unit/ — auth and utilities
  • test/widgets/ — UI components (shimmer, waveform, transcript)
  • test/providers/ — State management (capture_provider, device_provider)
  • test/utils/ — Utility functions (localization helpers)

Running Tests

bash test.sh            # all unit/widget tests (hermetic)
flutter test test/unit/ # specific directory
make mobile-verify ARGS="fast --paths <changed-file>"  # focused product journeys
make mobile-verify ARGS="fast --all"                   # full hermetic journey suite
(cd android && ./gradlew :app:testDevDebugUnitTest)     # Android JVM: JDK 21, SDK 36

test.sh bootstraps missing inputs with empty API_BASE_URL. Journey selection/receipts/CI: scripts/dev-harness/MOBILE_VERIFY.md.

Native: ruby ios/test/batch_audio_energy_test.rb; phone/BLE replay.

Performance

UI: bash app/tool/perf_gate.sh (guide); red blocks shipping. Heavy: bash app/tool/perf_device_run.sh (never-uninstall guide).

Test Patterns

  • Mock singletons (SharedPreferencesUtil, AuthService, FirebaseAuth) since they aren't injectable
  • Capture seams/ownership: C1 contract; inject fakes.
  • HTTP result/consumer migration: C3 contract.
  • Mind Map identity: contract.
  • Everything under test/ must be hermetic — no network, live backends, or real devices — because bash test.sh (the CI suite) runs all of it.
  • Chat transcript layout: pumping only AIMessage in a SingleChildScrollView misses scroll-extent bugs; chat list changes must keep test/widgets/chat_scroll_layout_test.dart green (ListView drag + citation/markdown sizes) — it is the Mobile App Checks contract for this class.
  • Tests needing a live service/device/real API go under integration_test/ (plain test.sh skips them); the hermetic seeded journeys there run in CI via mobile-verify fast --all with loopback fixtures only. Local-backend tests set OMI_APP_TEST_API_BASE_URL=http://127.0.0.1:<port>/.
  • Coverage: root AGENTS.md → Testing.

Localization (l10n)

  • All user-facing strings use context.l10n.keyName. Template: lib/l10n/app_en.arb. Never hardcode a locale count; python3 scripts/l10n.py template lists every locale the tree has.
  • Add/change/remove a key with scripts/l10n.py (add/set/remove). Do not edit ARB files by hand or with jq. The caller supplies translations (no network); the tool writes every locale, runs flutter gen-l10n, formats generated Dart, and refuses a partial or placeholder-mismatched change.
  • python3 scripts/l10n.py check is the fast consistency gate (parse, key-set, placeholders, generated freshness). Ready for a pre-push hook; not wired in this package.

Auth & Security

Token Lifecycle

  1. getAuthHeader() in lib/backend/http/shared.dart checks token expiry (5-minute buffer)
  2. If expired, calls AuthService.instance.getIdToken() for Firebase refresh
  3. Token stored via SharedPreferencesUtil in flutter_secure_storage (Keychain / EncryptedSharedPreferences); expiration timestamp stays in SharedPreferences. One-time migrateAuthTokenFromPrefs() runs at SharedPreferencesUtil.init() so existing sessions keep their token.
  4. 401 responses trigger automatic refresh + retry

Auth Methods

  • Google google_sign_in; Apple sign_in_with_apple (nonce+SHA256 PKCE).
  • Firebase Auth; browser flows: mobile auth.

Request Headers

Gated features show read-only on TestFlight by default; never money, entitlements or data: backend/config/app_channel.py.

API Base URLs

  • Dev: configured in .dev.env → Env.apiBaseUrl
  • Prod: configured in .prod.env → Env.apiBaseUrl

App Flows & E2E

  • Flows: e2e/SKILL.md. Own-voice enrollment: guide.
  • See e2e/flows/*.yaml for individual flow definitions

Verifying UI Changes (agent-flutter)

After any Flutter UI edit, verify with agent-flutter (Marionette is integrated in debug builds). Install once: npm install -g agent-flutter-cli.

Edit → Verify → Evidence loop:

  1. Edit code, hot restart: kill -SIGUSR2 $(pgrep -f "flutter run" | head -1)
  2. Connect: AGENT_FLUTTER_LOG=/tmp/flutter-run.log agent-flutter connect
  3. Verify: agent-flutter snapshot -i
  4. Interact: agent-flutter press @e3 / press 540 1200 / find type button press / fill @e5 "text" / dismiss
  5. Evidence: agent-flutter screenshot /tmp/evidence.png

Key rules:

  • Must reconnect after every hot restart (kills VM Service session).
  • Refs go stale frequently — always re-snapshot before every interaction. Use press x y as fallback.
  • AGENT_FLUTTER_LOG must point to flutter run stdout (not logcat).
  • Prefer find type X / find key "name" over hardcoded @ref. Add Key('descriptive_name') to new interactive widgets.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.