PennyWise is a minimalist, AI-powered expense tracker for Android that automatically extracts transaction data from SMS messages using on-device processing.
Please reference these documents when working on this project:
- Architecture:
/docs/architecture.md- MVVM + Clean Architecture patterns, layer responsibilities - Design System:
/docs/design.md- Material 3 theming, colors, typography, components - PRD:
/prd.md- Product requirements, features, timeline
- UI Framework: Jetpack Compose with Material 3
- Architecture: MVVM with Clean Architecture (UI, Domain, Data layers)
- State Management: Unidirectional Data Flow with StateFlow
- DI: Hilt for dependency injection
- Database: Room for local storage
- AI/ML: MediaPipe LLM (Qwen 2.5) for on-device processing
- Background: WorkManager for SMS scanning
- Material You: Dynamic color from wallpaper (Android 12+)
- Light/Dark Theme: Full support with semantic color roles
- Spacing: 8dp grid system
- Typography: Material 3 type scale
- Navigation: NavigationBar for phones, NavigationRail for tablets
- Edge-to-Edge: All screens use PennyWiseScaffold with default TopAppBar for consistent system bar handling
- Consistent UI: PennyWiseScaffold provides default TopAppBar with options for title, navigation, actions, and transparency
- Follow Kotlin coding conventions
- Use meaningful variable names
- Implement proper error handling with sealed classes
- Ensure UI components are reusable and testable
- Always test on both light and dark themes
Working on Phase 1: Core Foundation (Project setup, Material 3 theming, Room database, Navigation)
- Build:
./gradlew build - Test:
./gradlew test - Lint:
./gradlew lint
We follow Semantic Versioning (SemVer) - MAJOR.MINOR.PATCH:
- MAJOR: Breaking changes, major UI overhauls, architecture changes
- MINOR: New features, significant improvements
- PATCH: Bug fixes, minor improvements, performance optimizations
Current version: 2.1.3 (versionCode: 13)
Recent version history:
- 2.1.3: Federal Bank support, Discord community, GitHub issue templates
- 2.1.2: Spotlight tutorial, SBI/Indian Bank support, auto-scan on launch
- 2.0.1: Previous release
The project now uses a multi-module architecture:
- app: Main Android application module
- parser-core: Standalone bank parser module (no Android dependencies)
Bank parsers are now in the parser-core module for reusability across platforms.
- Location: Add to
parser-core/src/main/kotlin/com/pennywiseai/parser/core/bank/ - Base Class: All bank parsers extend
BankParserabstract class- Indian Banks: MUST extend
BaseIndianBankParserto inherit centralized mandate, subscription, and balance update logic. - UAE Banks: MUST extend
UAEBankParserfor currency and transaction type handling.
- Indian Banks: MUST extend
- Key Methods:
getBankName(): Returns the bank's display namecanHandle(sender: String): Checks if parser can handle SMS from senderparse(smsBody, sender, timestamp): ReturnsParsedTransactionor null
- Override Patterns: Banks typically override:
extractAmount(): Bank-specific amount patternsextractMerchant(): Bank-specific merchant extractionextractTransactionType(): If needed for special cases
- Registration: Add new parser to
BankParserFactory.parserslist in parser-core - Return Type: Use
ParsedTransactionfrom parser-core - Imports for parser-core:
com.pennywiseai.parser.core.TransactionTypecom.pennywiseai.parser.core.ParsedTransactionjava.math.BigDecimalfor amounts
- Use
com.pennywiseai.tracker.data.mapper.toEntity()to convert ParsedTransaction to TransactionEntity - The mapper handles type conversions between modules
- Airtel Payments Bank
- Al Rajhi Bank (Saudi Arabia) - Arabic SMS support
- Alinma Bank (Saudi Arabia) - Arabic SMS support
- Altana Federal Credit Union (USA)
- American Express (AMEX)
- Axis Bank
- Bank of Baroda
- Bank of India
- Canara Bank
- Central Bank of India
- Chase Bank (USA)
- City Union Bank
- DBS Bank
- Federal Bank
- HDFC Bank
- HSBC Bank
- Huntington Bank (USA)
- ICICI Bank
- IDBI Bank
- IDFC First Bank
- Indian Bank
- Indian Overseas Bank
- India Post Payments Bank (IPPB)
- Jio Payments Bank
- JioPay
- Jammu & Kashmir Bank
- Jupiter Bank
- Juspay
- Karnataka Bank
- Kerala Gramin Bank
- Kotak Bank
- LazyPay
- Liv Bank (UAE) - Digital bank
- Mashreq Bank
- mBank CZ (Czech Republic) - Czech SMS support
- M-PESA (Kenya) - Mobile money service
- Navy Federal Credit Union (USA) - NFCU
- NMB Bank / Nabil Bank (Nepal)
- OneCard
- Priorbank (Belarus) - Russian/Belarusian SMS support
- Punjab National Bank (PNB)
- Punjab & Sind Bank (PSB)
- Saraswat Co-operative Bank
- Saudi National Bank / Al Ahli (SNB-AlAhli, Saudi Arabia) - Arabic SMS support
- Siddhartha Bank Limited (Nepal)
- State Bank of India (SBI)
- Slice
- South Indian Bank
- Standard Chartered Bank
- STC Bank (Saudi Arabia)
- T-Bank / Tinkoff (Russia) - Russian SMS support
- Union Bank
- Utkarsh Bank
When implementing any feature, please ensure it aligns with the architecture patterns and design system defined in the documentation.
Never use pii in comments, code anywhere
- Parser tests must use the shared JUnit helpers under
ParserTestUtils. For full guidance (examples, migration checklist), readdocs/parser-test-standards.md.