Local-first, privacy-centric financial intelligence for mobile
Ledger.AI transforms raw mobile notifications (SMS, push, UPI) into a structured, searchable financial ledger — without cloud APIs, bank logins, or OAuth intermediaries.
- Every financial transaction generates a notification
- These notifications contain all the data we need (merchant, amount, category)
- By intercepting at the OS layer, we bypass API complexity entirely
- On-device LLM (Gemma 4) parses unstructured text into structured records
- Financial data never leaves the device
Phase: Foundation (Phase 1) — Core infrastructure complete
| Component | Status |
|---|---|
| Project scaffolding | ✅ Expo SDK 55, TypeScript strict, ESLint, Prettier |
| SQLite database | ✅ op-sqlite with WAL mode, migrations, repositories |
| Basic UI | ✅ Navigation, tab structure, transaction cards |
| SMS reader module | ✅ Custom Expo module for inbox query |
| Notification listener | ✅ Manifest-registered BroadcastReceiver (pending device test) |
| Transaction list | ✅ FlatList with date grouping, empty states |
| Manual entry | ✅ Form for testing/fallback |
| LLM integration | ✅ Classification + parsing (PoC validated) |
- Manifest-registered BroadcastReceiver captures SMS even when app is killed
- Inbox-as-queue architecture (no data loss on force-quit)
- Capped processing (20 SMS max) to avoid thermal issues
- Gemma 4 E2B Q4_K_M (~2GB, fits on 4GB+ devices)
- Classifies SMS → parses to structured JSON → inserts to SQLite
- Falls back to regex parser for low-end devices
- SQLite with WAL mode, SQLCipher encryption
- Repository pattern for CRUD operations
- Summary strip, date grouping, empty states
| Layer | Technology |
|---|---|
| Framework | Expo SDK 55+ (with prebuild) |
| Language | TypeScript (strict) |
| Database | op-sqlite (JSI-based SQLite) |
| State | Zustand |
| Navigation | React Navigation v6 |
| Local LLM | llama.rn + Gemma 4 |
| Notifications | Custom Android NotificationListenerService |
├── app/ # Expo Router screens
├── src/
│ ├── components/ # UI components (cards, empty-state, etc.)
│ ├── database/ # SQLite + repositories
│ ├── parsers/ # LLM + regex parsers
│ └── hooks/ # React hooks
├── modules/
│ ├── sms-reader/ # Expo module for SMS inbox query
│ └── sms-listener/ # Expo module for real-time SMS capture
├── hooks/ # Global hooks (use-sms-listener.ts)
└── .documentation/ # Plans, evidence, decisions (project memory)
This project uses structured documentation in .documentation/:
- PROJECT_PLAN.md — Living roadmap
- plans/PLAN-NNN-* — Feature plans
- evidence/EVIDENCE-NNN-* — Validation results
- decisions/ADR-NNN-* — Architecture decisions
See CONTRIBUTING.md for development workflow.
# Install dependencies
npm install
# Run on Android (requires physical device for SMS features)
npx expo run:android# Clean prebuild
npx expo prebuild --clean
# Build debug APK
cd android && ./gradlew assembleDebug
# Install and test SMS capture
adb install app/build/outputs/apk/debug/app-debug.apk- ✅ Phase 1: Foundation (complete)
- 🔄 Phase 2: PoC — Device testing of notification listener
- ⏳ Phase 3: MVP — Auto-categorization, insights, battery optimization
- ⏳ Phase 4: Polish — iOS support, model fine-tuning, Play Store
- No cloud APIs
- No data leaves device
- SQLCipher encryption at rest
- No analytics, no tracking