Skip to content

Codestz/Mintroot

Repository files navigation

Mintroot

A privacy-conscious Android app that turns Bancolombia statements into actionable financial insights, powered by an AI assistant you can chat with.

Home Activity AI Hub

Insights Files Settings

Amounts in the screenshots above are masked with the in-app privacy toggle.

What it does

  • Import Bancolombia XLSX statements — Savings, Credit Card (incl. multi-currency COP/USD), Investment Fund. Period coverage is tracked per file.
  • Process every imported transaction with one tap: Classify (REAL_EXPENSE, REAL_INCOME, INTERNAL_TRANSFER, …) → Polish (clean merchant name, recurrence, payment method) → match internal transfers between your own accounts.
  • Chat with Gemini about your money. Multi-turn function-calling lets it pull totals, list merchants, suggest aliases, or recategorize batches — every write is gated by an explicit confirmation card.
  • Audit any decision: every classification override leaves a JSON trail (reasoning, source, at) on the transaction.
  • Train merchants by alias: "Rappi Restaurantes is Rappi" — the alias persists, future imports follow it, and matching past transactions are backfilled immediately.
  • Insights dashboard: net worth + 6-month chart, income vs expense, recurring vs one-off, top merchants, by-category breakdown, by-weekday spend.

Why

Most personal-finance apps in Latin America either charge a subscription, ship financial data to third-party servers, or lock users into proprietary formats. Mintroot:

  • No subscription, no ads, no broker. You bring your own Gemini API key (free tier is enough for monthly use).
  • Encrypted on-device storage. SQLCipher-backed Room DB; the API key is stored alongside transaction data in the same encrypted file.
  • Auditable. Open source, no hidden classification rules — the LLM does the work, results are cached as data, never code.
  • Bancolombia-shaped. The parser understands the bank's actual XLSX layout, including Colombian-locale amount strings, US-locale savings amounts, multi-currency CC sheets, installment plans, and reversal pairs.

How it works

XLSX  ─►  Parser  ─►  Transactions  ─►  Classify (Gemini)  ─►  Polish (Gemini)  ─►  Insights
                          ▲                  │                     │
                          │                  ▼                     ▼
                          └──────────  Classification Cache    Merchant Aliases
                                       (user overrides win)    (user-trained)
  • Parser: Apache POI on Bancolombia XLSX with locale-aware amount parsing and per-account-type adapters.
  • Classifier: Gemini Flash-Lite, batched 20-tx-per-request; results cached on raw_description so repeats short-circuit the model.
  • Polisher: Gemini Flash-Lite, Spanish-only output (Bancolombia descriptions are Spanish); user aliases pre-empt the model.
  • Chat: stateless multi-turn Gemini client with seven function tools (read: query, aggregate, accounts, categories, aliases; write: add alias, recategorize batch).
  • Storage: Room + SQLCipher. v1 baseline schema, destructive migration during pre-release.

Setup

  1. Build: ./gradlew :app:assembleDebug
  2. Install on device (Android 12+): adb install -r app/build/outputs/apk/debug/app-debug.apk (use -t for MIUI).
  3. Launch → tap the violet Connect Gemini card on Home → Settings → paste your key from aistudio.google.com/apikey.
  4. Tap Import → pick a Bancolombia XLSX statement → tap Process.

Toggle Auto-process new imports in Settings → Automation if you want the Classify + Polish chain to fire automatically after every import.

Build

./gradlew :app:assembleDebug

Requirements:

  • JDK 17 (Zulu, Temurin, or equivalent)
  • Android SDK 35, Min SDK 31 (Android 12)
  • AGP 8.13.x (Hilt blocks AGP 9.x)

Stack

Kotlin · Jetpack Compose · Hilt · Room + SQLCipher · WorkManager (foreground services) · Apache POI · Vico (charts) · Gemini v1beta REST · Core SplashScreen.

Core philosophy

  1. AI-first, not rule-based. The LLM classifies and polishes; results are cached as data. No hardcoded merchant lists, glosa regexes, or category catalogs.
  2. The raw file is the source of truth. Imported XLSX files are archived; the DB is derived from them and rebuildable.
  3. Privacy is non-negotiable. Encrypted at rest. The only outbound call is to your own Gemini key.
  4. The transaction is the atomic unit. Transfers, payments, installments, and loan payments are either a transaction or a relationship between transactions.
  5. Classification is metadata, not structure. The core (date, amount, description, account) is immutable; the interpretation (category, classification type, person) is mutable and auditable.
  6. Explicit states over booleans. Lifecycled entities use enum status, not correlated boolean flags.
  7. Multi-currency from day one. Every transaction declares its currency. No implicit COP assumptions.
  8. Auditability for life. Every classification change leaves a trail.

Documentation

Design docs are intentionally kept local-only (excluded via .gitignore) because they reference real bank-statement samples. If you are a contributor and need access, contact the maintainer.

Distribution

Signed APK via GitHub Releases. Sideload-only (the app needs file-system access for XLSX import; no Play Store dependency).

Cutting a release

The release.yml workflow builds a signed APK and creates a GitHub Release every time a v*.*.* tag is pushed.

One-time setup — generate a keystore once and add four secrets to the repo (Settings → Secrets and variables → Actions):

keytool -genkey -v -keystore mintroot.keystore -alias mintroot \
    -keyalg RSA -keysize 2048 -validity 10000
base64 -i mintroot.keystore | pbcopy  # paste into RELEASE_KEYSTORE_BASE64
Secret Value
RELEASE_KEYSTORE_BASE64 base64-encoded keystore file
RELEASE_KEYSTORE_PASSWORD the store password you set
RELEASE_KEY_ALIAS mintroot (or whatever alias you chose)
RELEASE_KEY_PASSWORD the key password

Cut a release:

git tag v1.0.1
git push origin v1.0.1

The workflow runs, builds, signs, and creates the Release. The APK is named mintroot-1.0.1.apk. versionName comes from the tag; versionCode is the GitHub Actions run number (monotonic).

In-app updates

On every launch the app calls GitHub's Releases API, compares the latest tag against the installed versionName, and shows a violet update banner on Home if a newer version exists. Tap Install update → the app downloads the APK to its cache and hands it to Android's Package Installer (you'll need "Install unknown apps" granted to Mintroot the first time).

Banner can be dismissed; check fires again on the next process start. Repo slug is BuildConfig.GITHUB_REPO, set in app/build.gradle.kts.

Status

Pre-release. Daily-driven by the maintainer; schema may break between commits (the app falls back to a destructive re-import).

License

TBD (MIT or Apache 2.0).

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages