diff --git a/CLAUDE.md b/CLAUDE.md index e0c1a1e..1ddc818 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,16 +1,58 @@ # CLAUDE.md -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - ## Project Overview -SpendingAnalysis is a Python application that ingests data from various sources to analyze spending habits. The project is in early development. +SpendingAnalysis is a PySide6 desktop GUI application for importing bank/credit card CSV statements and analyzing spending habits. Uses SQLAlchemy ORM with SQLite and matplotlib for charts. ## Repository - Remote: https://gitea.conlon.fun/andy/SpendingAnalysis.git - Branch: main -## Development Setup +## Commands -Python project — no build system, dependencies, or test framework configured yet. Standard Python .gitignore is in place covering common tooling (pytest, mypy, ruff, venv, etc.). +```bash +# Setup +python -m venv .venv +.venv\Scripts\activate # Windows +pip install -e ".[dev]" + +# Run +python -m src.main # or: spending-analysis + +# Test +pytest +``` + +## Architecture + +Three-layer structure under `src/`: + +- **models/** — SQLAlchemy ORM: Transaction, Account, Category, Rule, HouseholdMember, CsvMapping +- **services/** — Pure Python business logic (no Qt dependencies): importer, categorizer, analysis, forecasting, recurring detection, transfer detection, normalizer, csv_reader +- **ui/** — PySide6 views: ImportView (3-stage wizard), TransactionsView (table + inline editing), AnalysisView (matplotlib charts), RecurringView, SettingsView + +Entry point: `src/main.py` → initializes DB, seeds defaults, launches MainWindow. +Database: `~/.spending_analysis/spending.db` (SQLite, auto-created on first run). +Theme: Cyberpunk "Matrix 2026" defined in `src/ui/themes/` (palette in `__init__.py`, stylesheet in `dark.qss`). + +## Key Conventions + +- Services are pure Python with no UI imports — keep them testable independently +- Categorizer uses a Protocol interface — future AI categorizers can implement the same protocol +- Tests use in-memory SQLite (`sqlite:///:memory:`) +- Transactions store both `description` (normalized) and `raw_description` (original) +- Amounts are signed: negative = expense, positive = income + +## Gotchas + +- **Rule cache**: `RuleBasedCategorizer` caches rules in memory; call `invalidate_cache()` after editing rules in Settings +- **CSV first-row heuristic**: csv_reader checks if the first row looks like data (contains dates/numbers) to handle headerless CSVs (e.g., Wells Fargo) +- **SQLite threading**: Import runs on QThread but SQLAlchemy sessions aren't thread-isolated — avoid concurrent DB writes +- **pandas imported but unused**: Listed in dependencies but not actively used in current code + +## Dependencies + +Runtime: PySide6, SQLAlchemy, pandas, matplotlib +Dev: pytest, pytest-qt +Configured in `pyproject.toml`. No CI/CD or linting tools configured.