NAVI
Une compagne IA qui vit sur le téléphone, pas sur un serveur
Assistant Android natif local-first : la collecte, la mémoire et la décision de parler vivent sur le téléphone ; le cloud ne sert qu'à générer le texte.
Statut
En usage quotidien, développement actif
Application privée utilisée au jour le jour. Pas de distribution publique : le dépôt est privé et il n'y a pas de version en magasin.
Accès
NAVI est une application privée, mono-utilisateur, sans distribution publique. Il n'y a donc ni lien de démonstration, ni dépôt consultable.
- donnée conversationnelle côté serveur
- 0donnée conversationnelle côté serveur
- de la mémoire chiffrée sur l’appareil
- 100 %de la mémoire chiffrée sur l’appareil
- de coût d’inférence visé par mois
- Quelques €de coût d’inférence visé par mois
Le problème
Un assistant conversationnel qui prend l'initiative doit observer le contexte de son utilisateur — notifications, applications utilisées, musique, santé, déplacements, agenda. Confier ces signaux à un serveur, c'est construire le profil comportemental le plus intrusif qui soit. Le problème n'était donc pas de faire parler un modèle, mais de le faire parler à propos, sans jamais externaliser la vie privée de l'utilisateur.
Mon rôle
Conception produit et développement intégral : cadrage, architecture, développement Android natif, proxy serveur, découpage en issues et supervision des agents IA d'exécution.
Les décisions qui ont façonné le produit.
Deux piliers, et rien de plus
Présence spontanée et mémoire relationnelle. Tout ce qui ne sert pas l'un des deux est refusé — y compris des directions déjà commencées, abandonnées en cours de route pour recentrer le produit.
Elle tient compagnie, elle ne coache pas
Pas de score, pas d'objectif, pas de jugement. Ce parti pris contraint la personnalité, le ton des notifications et ce que l'application se permet de retenir.
L'observation plutôt que la saisie
L'utilisateur ne remplit aucun formulaire. La seule entrée volontaire est le partage : depuis n'importe quelle application, « Partager → Navi » dépose un lien ou une image dans le fil.
Application privée, hors magasin
Mono-utilisateur, installée manuellement. Ce choix libère des contraintes de distribution et permet d'utiliser des permissions système qu'un magasin d'applications refuserait.
Natif Android, parce que le produit est fait de services système
NotificationListenerService, UsageStatsManager, Health Connect, geofencing, tâches de fond, bulles de conversation. Un socle multiplateforme aurait passé son temps à contourner la plateforme au lieu de s'appuyer dessus.
Mémoire chiffrée sur l’appareil
Room chiffrée via SQLCipher, clé conservée dans le Keystore Android. Les souvenirs et leurs embeddings restent locaux, et la recherche sémantique s'exécute sur le téléphone.
Un proxy plutôt qu’un backend
Un Worker Cloudflare porte la clé de l'API Gemini et ne stocke rien. Aucune donnée conversationnelle ne persiste côté serveur, et la clé ne se retrouve jamais dans l'APK.
Le moteur d’initiative décide localement
Scoring local, présence adaptative et anti-répétition déterminent s'il y a lieu de parler. Le modèle distant n'est appelé qu'une fois la décision prise, ce qui borne le coût.
Raisonnement au minimum, pour une vraie raison
Les tokens de raisonnement de Gemini 3 sont décomptés du plafond de sortie : au niveau par défaut, les réponses se coupaient en plein milieu d'une phrase. Passer `thinkingLevel` au minimum a corrigé la troncature autant que la facture.
Architecture volontairement plate
Compose, ViewModel, repositories. Pas de multi-modules ni de clean architecture cérémonielle : le projet est mono-développeur et doit rester lisible. Les décisions structurantes sont tracées en ADR.
Du signal capté sur le téléphone à la phrase générée.
- Étape 01
Sources de contexte
Notifications, applications utilisées, musique, Health Connect, géorepérage, agenda.
- Étape 02
Journal de contexte
Événements typés, rétention courte, filtrés par un registre d'applications.
- Étape 03
Moteur d'initiative
Scoring local, présence adaptative, anti-répétition. Décide seul s’il y a lieu de parler.
- Étape 04
Mémoire chiffrée
Room + SQLCipher, clé en Keystore. Souvenirs, embeddings et recherche sémantique locale.
- Étape 05
Proxy Cloudflare Worker
Porte la clé API, ne stocke rien, seul point de sortie réseau.
- Étape 06
Génération Gemini
Flash pour la conversation, Flash-Lite pour les initiatives et les tâches légères.
Contraintes
- Aucune donnée conversationnelle stockée côté serveur.
- Coût cible de quelques euros par mois, ce qui impose de choisir le modèle appelé selon l’enjeu.
- Application mono-utilisateur, installée manuellement, sans magasin.
- Développement solo, branche unique, CI légère.
Stack
- Kotlin
- Jetpack Compose
- Coroutines / Flow
- Room + SQLCipher
- Android Keystore
- WorkManager
- NotificationListenerService
- Health Connect
- Cloudflare Workers
- API Gemini
Ce que ce projet démontre
Développement Android natif moderne, au contact des services système.
Conception d'une architecture local-first où la vie privée est une contrainte structurelle, pas une option.
Arbitrage coût / qualité sur un usage réel de modèles génératifs.
Capacité à retirer des fonctionnalités déjà écrites pour préserver la cohérence d'un produit.