Android app that tracks your spending automatically by reading incoming bank SMS messages and categorizing them with an LLM. Built for Jordanian banks (Arabic + English SMS), works with any bank whose messages contain amounts and balances.
incoming SMS ──▶ regex heuristic (bank SMS? ≥2 of 5 patterns, AR+EN)
│ yes
▼
LLM categorization (OpenAI-compatible API, default OpenRouter)
│
┌─────────┴──────────┐
▼ ▼
confidence ≥ 0.7 low confidence / API down
auto-categorized saved + notification with
category quick-actions
Transactions are never dropped — if the AI is unreachable, the amount is extracted locally by regex and the transaction is stored uncategorized for you to fix with one tap.
- Automatic SMS capture — Arabic and English bank message formats, multipart SMS reassembly, duplicate detection
- AI categorization — 12 categories, any OpenAI-compatible endpoint (OpenRouter, OpenAI, Groq, Together, local Ollama), bring your own key
- Notification quick-categorize — uncertain transactions ask you via notification action buttons
- Budgets — per-category monthly limits with progress bars, over-limit warnings
- Monthly summary — donut chart, category breakdown, month navigation, 6-month trends comparison
- Manual entry — cash expenses via FAB
- Search + filters — text search, date-range presets and custom ranges, sort modes, category filter
- Data import — restore from a previous database file via the system file picker (atomic, dedup-safe)
- Privacy-minded — API key and financial DB excluded from cloud backups; response logging disabled in release builds; everything stays on-device except the single SMS being categorized
Grab the APK from Releases and install it (you may need to allow "install from unknown sources"), or build from source (below).
On first launch the app asks for:
| Permission | Why |
|---|---|
| Receive/Read SMS | detect incoming bank messages — nothing else is read or sent |
| Notifications | the "Categorize Transaction" prompt when the AI is unsure |
The app needs an LLM for categorization. Easiest path — OpenRouter:
- Create an account at openrouter.ai and add a few dollars of credit (classification costs fractions of a cent per SMS).
- Create an API key at openrouter.ai → Keys.
Any OpenAI-compatible endpoint works too (OpenAI, Groq, Together, or a local Ollama server — preset URLs are built in).
Open Settings in the app:
| Field | Value |
|---|---|
| Base URL | https://openrouter.ai/api (preset, default) |
| API key | your key |
| Model name | e.g. anthropic/claude-haiku-4.5 — fast, cheap, accurate for classification |
| Currency | your currency code, e.g. JOD |
Tap Save. Done — the next bank SMS shows up categorized in the Transactions tab.
Settings → Import old database → pick a previously exported money_tracker.db file. Import is atomic and skips duplicates.
Summary → Edit budgets → enter monthly limits per category. Progress bars turn red when you overshoot.
git clone git@github.com:AvAl4nch/money-tracker.git
cd money-tracker
./gradlew :app:assembleDebug # or :app:installDebug with a device attached
./gradlew :app:testDebugUnitTest # 30 unit tests
./gradlew :app:connectedDebugAndroidTest # Room migration test (needs device/emulator)Requires JDK 17+ and the Android SDK (compileSdk 36, minSdk 33).
Kotlin · Jetpack Compose (Material 3) · Hilt · Room (versioned migrations + instrumented migration tests) · Preferences DataStore · OkHttp + Gson · clean architecture (ai / data / domain / notification / sms / ui)
Contributions are welcome — bug reports, feature ideas, and pull requests alike.
- Found a bug / want a feature? Open an issue.
- Sending a PR? Fork, branch, and make sure
./gradlew :app:testDebugUnitTestpasses (and:app:connectedDebugAndroidTestif you touch the database layer). Add tests for new logic where it makes sense.
By contributing you agree your work is licensed under the project's MIT license.