getfin 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. getfin-1.0.0/.gitignore +23 -0
  2. getfin-1.0.0/LICENSE +133 -0
  3. getfin-1.0.0/PKG-INFO +499 -0
  4. getfin-1.0.0/README.md +324 -0
  5. getfin-1.0.0/pyproject.toml +82 -0
  6. getfin-1.0.0/src/fin/__init__.py +0 -0
  7. getfin-1.0.0/src/fin/audit.py +305 -0
  8. getfin-1.0.0/src/fin/cache.py +167 -0
  9. getfin-1.0.0/src/fin/categorize.py +338 -0
  10. getfin-1.0.0/src/fin/classifier.py +598 -0
  11. getfin-1.0.0/src/fin/cli.py +2885 -0
  12. getfin-1.0.0/src/fin/close_books.py +659 -0
  13. getfin-1.0.0/src/fin/config.py +116 -0
  14. getfin-1.0.0/src/fin/credentials.py +163 -0
  15. getfin-1.0.0/src/fin/csv_import.py +364 -0
  16. getfin-1.0.0/src/fin/dates.py +354 -0
  17. getfin-1.0.0/src/fin/db.py +1310 -0
  18. getfin-1.0.0/src/fin/demo.py +250 -0
  19. getfin-1.0.0/src/fin/integrity.py +136 -0
  20. getfin-1.0.0/src/fin/legacy_analysis.py +851 -0
  21. getfin-1.0.0/src/fin/legacy_classify.py +2356 -0
  22. getfin-1.0.0/src/fin/log.py +11 -0
  23. getfin-1.0.0/src/fin/models.py +21 -0
  24. getfin-1.0.0/src/fin/money.py +295 -0
  25. getfin-1.0.0/src/fin/normalize.py +204 -0
  26. getfin-1.0.0/src/fin/planner.py +429 -0
  27. getfin-1.0.0/src/fin/projections.py +555 -0
  28. getfin-1.0.0/src/fin/reconciliation.py +580 -0
  29. getfin-1.0.0/src/fin/refund_matching.py +446 -0
  30. getfin-1.0.0/src/fin/report_service.py +293 -0
  31. getfin-1.0.0/src/fin/reporting.py +371 -0
  32. getfin-1.0.0/src/fin/reporting_models.py +271 -0
  33. getfin-1.0.0/src/fin/simplefin_client.py +221 -0
  34. getfin-1.0.0/src/fin/static/css/fin_drilldown.css +206 -0
  35. getfin-1.0.0/src/fin/static/js/fin_api.js +37 -0
  36. getfin-1.0.0/src/fin/static/js/fin_drilldown.js +500 -0
  37. getfin-1.0.0/src/fin/static/js/fin_ui.js +133 -0
  38. getfin-1.0.0/src/fin/status_commands.py +512 -0
  39. getfin-1.0.0/src/fin/templates/audit.html +510 -0
  40. getfin-1.0.0/src/fin/templates/base.html +3638 -0
  41. getfin-1.0.0/src/fin/templates/budget.html +554 -0
  42. getfin-1.0.0/src/fin/templates/commitments.html +461 -0
  43. getfin-1.0.0/src/fin/templates/connect.html +1003 -0
  44. getfin-1.0.0/src/fin/templates/dashboard.html +1391 -0
  45. getfin-1.0.0/src/fin/templates/dashboard_v2.html +1767 -0
  46. getfin-1.0.0/src/fin/templates/insights.html +187 -0
  47. getfin-1.0.0/src/fin/templates/plan.html +18 -0
  48. getfin-1.0.0/src/fin/templates/subs.html +466 -0
  49. getfin-1.0.0/src/fin/templates/sync-log.html +276 -0
  50. getfin-1.0.0/src/fin/tls.py +214 -0
  51. getfin-1.0.0/src/fin/transfer_pairing.py +426 -0
  52. getfin-1.0.0/src/fin/versioning.py +84 -0
  53. getfin-1.0.0/src/fin/view_models.py +479 -0
  54. getfin-1.0.0/src/fin/web.py +4067 -0
  55. getfin-1.0.0/tests/__init__.py +1 -0
  56. getfin-1.0.0/tests/conftest.py +482 -0
  57. getfin-1.0.0/tests/test_analysis.py +345 -0
  58. getfin-1.0.0/tests/test_audit.py +151 -0
  59. getfin-1.0.0/tests/test_backup_export.py +411 -0
  60. getfin-1.0.0/tests/test_classifier.py +379 -0
  61. getfin-1.0.0/tests/test_cli_integration.py +484 -0
  62. getfin-1.0.0/tests/test_commitments.py +972 -0
  63. getfin-1.0.0/tests/test_credentials.py +354 -0
  64. getfin-1.0.0/tests/test_csv_import.py +312 -0
  65. getfin-1.0.0/tests/test_dashboard_metrics.py +154 -0
  66. getfin-1.0.0/tests/test_dates.py +290 -0
  67. getfin-1.0.0/tests/test_duplicate_detection.py +469 -0
  68. getfin-1.0.0/tests/test_insights_route.py +191 -0
  69. getfin-1.0.0/tests/test_known_subscriptions.py +239 -0
  70. getfin-1.0.0/tests/test_money.py +336 -0
  71. getfin-1.0.0/tests/test_no_legacy_engine.py +402 -0
  72. getfin-1.0.0/tests/test_period_selection.py +248 -0
  73. getfin-1.0.0/tests/test_reconciliation.py +338 -0
  74. getfin-1.0.0/tests/test_refund_matching.py +287 -0
  75. getfin-1.0.0/tests/test_reporting.py +237 -0
  76. getfin-1.0.0/tests/test_simplefin_setup.py +144 -0
  77. getfin-1.0.0/tests/test_sketchy_detection.py +482 -0
  78. getfin-1.0.0/tests/test_transfer_pairing.py +357 -0
  79. getfin-1.0.0/tests/test_txn_type_overrides.py +190 -0
  80. getfin-1.0.0/tests/test_web_functional.py +628 -0
@@ -0,0 +1,23 @@
1
+ .env
2
+
3
+ data/
4
+ exports/
5
+
6
+ __pycache__/
7
+ .pytest_cache/
8
+ *.egg-info/
9
+ dist/
10
+ build/
11
+ *.log
12
+ *.pyc
13
+ *.pyo
14
+ *.pyd
15
+ *.sqlite
16
+ *.db
17
+ *.test_backup
18
+ .vscode/
19
+
20
+ # Local files
21
+ .claude/
22
+ BACKLOG.md
23
+ buglist.txt
getfin-1.0.0/LICENSE ADDED
@@ -0,0 +1,133 @@
1
+ # PolyForm Noncommercial License 1.0.0
2
+
3
+ <https://polyformproject.org/licenses/noncommercial/1.0.0>
4
+
5
+ Required Notice: Copyright Arclight Engineering (http://www.arclighteng.com)
6
+
7
+ ## Acceptance
8
+
9
+ In order to get any license under these terms, you must agree
10
+ to them as both strict obligations and conditions to all
11
+ your licenses.
12
+
13
+ ## Copyright License
14
+
15
+ The licensor grants you a copyright license for the
16
+ software to do everything you might do with the software
17
+ that would otherwise infringe the licensor's copyright
18
+ in it for any permitted purpose. However, you may
19
+ only distribute the software according to [Distribution
20
+ License](#distribution-license) and make changes or new works
21
+ based on the software according to [Changes and New Works
22
+ License](#changes-and-new-works-license).
23
+
24
+ ## Distribution License
25
+
26
+ The licensor grants you an additional copyright license
27
+ to distribute copies of the software. Your license
28
+ to distribute covers distributing the software with
29
+ changes and new works permitted by [Changes and New Works
30
+ License](#changes-and-new-works-license).
31
+
32
+ ## Notices
33
+
34
+ You must ensure that anyone who gets a copy of any part of
35
+ the software from you also gets a copy of these terms or the
36
+ URL for them above, as well as copies of any plain-text lines
37
+ beginning with `Required Notice:` that the licensor provided
38
+ with the software. For example:
39
+
40
+ > Required Notice: Copyright Yoyodyne, Inc. (http://example.com)
41
+
42
+ ## Changes and New Works License
43
+
44
+ The licensor grants you an additional copyright license to
45
+ make changes and new works based on the software for any
46
+ permitted purpose.
47
+
48
+ ## Patent License
49
+
50
+ The licensor grants you a patent license for the software that
51
+ covers patent claims the licensor can license, or becomes able
52
+ to license, that you would infringe by using the software.
53
+
54
+ ## Noncommercial Purposes
55
+
56
+ Any noncommercial purpose is a permitted purpose.
57
+
58
+ ## Personal Uses
59
+
60
+ Personal use for research, experiment, and testing for
61
+ the benefit of public knowledge, personal study, private
62
+ entertainment, hobby projects, amateur pursuits, or religious
63
+ observance, without any anticipated commercial application,
64
+ is use for a permitted purpose.
65
+
66
+ ## Noncommercial Organizations
67
+
68
+ Use by any charitable organization, educational institution,
69
+ public research organization, public safety or health
70
+ organization, environmental protection organization,
71
+ or government institution is use for a permitted purpose
72
+ regardless of the source of funding or obligations resulting
73
+ from the funding.
74
+
75
+ ## Fair Use
76
+
77
+ You may have "fair use" rights for the software under the
78
+ law. These terms do not limit them.
79
+
80
+ ## No Other Rights
81
+
82
+ These terms do not allow you to sublicense or transfer any of
83
+ your licenses to anyone else, or prevent the licensor from
84
+ granting licenses to anyone else. These terms do not imply
85
+ any other licenses.
86
+
87
+ ## Patent Defense
88
+
89
+ If you make any written claim that the software infringes or
90
+ contributes to infringement of any patent, your patent license
91
+ for the software granted under these terms ends immediately. If
92
+ your company makes such a claim, your patent license ends
93
+ immediately for work on behalf of your company.
94
+
95
+ ## Violations
96
+
97
+ The first time you are notified in writing that you have
98
+ violated any of these terms, or done anything with the software
99
+ not covered by your licenses, your licenses can nonetheless
100
+ continue if you come into full compliance with these terms,
101
+ and take practical steps to correct past violations, within
102
+ 32 days of receiving notice. Otherwise, all your licenses
103
+ end immediately.
104
+
105
+ ## No Liability
106
+
107
+ ***As far as the law allows, the software comes as is, without
108
+ any warranty or condition, and the licensor will not be liable
109
+ to you for any damages arising out of these terms or the use
110
+ or nature of the software, under any kind of legal claim.***
111
+
112
+ ## Definitions
113
+
114
+ The **licensor** is the individual or entity offering these
115
+ terms, and the **software** is the software the licensor makes
116
+ available under these terms.
117
+
118
+ **You** refers to the individual or entity agreeing to these
119
+ terms.
120
+
121
+ **Your company** is any legal entity, sole proprietorship,
122
+ or other kind of organization that you work for, plus all
123
+ organizations that have control over, are under the control of,
124
+ or are under common control with that organization. **Control**
125
+ means ownership of substantially all the assets of an entity,
126
+ or the power to direct its management and policies by vote,
127
+ contract, or otherwise. Control can be direct or indirect.
128
+
129
+ **Your licenses** are all the licenses granted to you for the
130
+ software under these terms.
131
+
132
+ **Use** means anything you do with the software requiring one
133
+ of your licenses.
getfin-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,499 @@
1
+ Metadata-Version: 2.4
2
+ Name: getfin
3
+ Version: 1.0.0
4
+ Summary: Local-first personal finance — sync with your bank, detect subscriptions, track spending. All data stays on your machine.
5
+ Project-URL: Homepage, https://github.com/arclighteng/fin
6
+ Project-URL: Documentation, https://github.com/arclighteng/fin#readme
7
+ Author-email: Arclight Engineering <hello@arclighteng.com>
8
+ License: # PolyForm Noncommercial License 1.0.0
9
+
10
+ <https://polyformproject.org/licenses/noncommercial/1.0.0>
11
+
12
+ Required Notice: Copyright Arclight Engineering (http://www.arclighteng.com)
13
+
14
+ ## Acceptance
15
+
16
+ In order to get any license under these terms, you must agree
17
+ to them as both strict obligations and conditions to all
18
+ your licenses.
19
+
20
+ ## Copyright License
21
+
22
+ The licensor grants you a copyright license for the
23
+ software to do everything you might do with the software
24
+ that would otherwise infringe the licensor's copyright
25
+ in it for any permitted purpose. However, you may
26
+ only distribute the software according to [Distribution
27
+ License](#distribution-license) and make changes or new works
28
+ based on the software according to [Changes and New Works
29
+ License](#changes-and-new-works-license).
30
+
31
+ ## Distribution License
32
+
33
+ The licensor grants you an additional copyright license
34
+ to distribute copies of the software. Your license
35
+ to distribute covers distributing the software with
36
+ changes and new works permitted by [Changes and New Works
37
+ License](#changes-and-new-works-license).
38
+
39
+ ## Notices
40
+
41
+ You must ensure that anyone who gets a copy of any part of
42
+ the software from you also gets a copy of these terms or the
43
+ URL for them above, as well as copies of any plain-text lines
44
+ beginning with `Required Notice:` that the licensor provided
45
+ with the software. For example:
46
+
47
+ > Required Notice: Copyright Yoyodyne, Inc. (http://example.com)
48
+
49
+ ## Changes and New Works License
50
+
51
+ The licensor grants you an additional copyright license to
52
+ make changes and new works based on the software for any
53
+ permitted purpose.
54
+
55
+ ## Patent License
56
+
57
+ The licensor grants you a patent license for the software that
58
+ covers patent claims the licensor can license, or becomes able
59
+ to license, that you would infringe by using the software.
60
+
61
+ ## Noncommercial Purposes
62
+
63
+ Any noncommercial purpose is a permitted purpose.
64
+
65
+ ## Personal Uses
66
+
67
+ Personal use for research, experiment, and testing for
68
+ the benefit of public knowledge, personal study, private
69
+ entertainment, hobby projects, amateur pursuits, or religious
70
+ observance, without any anticipated commercial application,
71
+ is use for a permitted purpose.
72
+
73
+ ## Noncommercial Organizations
74
+
75
+ Use by any charitable organization, educational institution,
76
+ public research organization, public safety or health
77
+ organization, environmental protection organization,
78
+ or government institution is use for a permitted purpose
79
+ regardless of the source of funding or obligations resulting
80
+ from the funding.
81
+
82
+ ## Fair Use
83
+
84
+ You may have "fair use" rights for the software under the
85
+ law. These terms do not limit them.
86
+
87
+ ## No Other Rights
88
+
89
+ These terms do not allow you to sublicense or transfer any of
90
+ your licenses to anyone else, or prevent the licensor from
91
+ granting licenses to anyone else. These terms do not imply
92
+ any other licenses.
93
+
94
+ ## Patent Defense
95
+
96
+ If you make any written claim that the software infringes or
97
+ contributes to infringement of any patent, your patent license
98
+ for the software granted under these terms ends immediately. If
99
+ your company makes such a claim, your patent license ends
100
+ immediately for work on behalf of your company.
101
+
102
+ ## Violations
103
+
104
+ The first time you are notified in writing that you have
105
+ violated any of these terms, or done anything with the software
106
+ not covered by your licenses, your licenses can nonetheless
107
+ continue if you come into full compliance with these terms,
108
+ and take practical steps to correct past violations, within
109
+ 32 days of receiving notice. Otherwise, all your licenses
110
+ end immediately.
111
+
112
+ ## No Liability
113
+
114
+ ***As far as the law allows, the software comes as is, without
115
+ any warranty or condition, and the licensor will not be liable
116
+ to you for any damages arising out of these terms or the use
117
+ or nature of the software, under any kind of legal claim.***
118
+
119
+ ## Definitions
120
+
121
+ The **licensor** is the individual or entity offering these
122
+ terms, and the **software** is the software the licensor makes
123
+ available under these terms.
124
+
125
+ **You** refers to the individual or entity agreeing to these
126
+ terms.
127
+
128
+ **Your company** is any legal entity, sole proprietorship,
129
+ or other kind of organization that you work for, plus all
130
+ organizations that have control over, are under the control of,
131
+ or are under common control with that organization. **Control**
132
+ means ownership of substantially all the assets of an entity,
133
+ or the power to direct its management and policies by vote,
134
+ contract, or otherwise. Control can be direct or indirect.
135
+
136
+ **Your licenses** are all the licenses granted to you for the
137
+ software under these terms.
138
+
139
+ **Use** means anything you do with the software requiring one
140
+ of your licenses.
141
+ License-File: LICENSE
142
+ Classifier: Development Status :: 4 - Beta
143
+ Classifier: Environment :: Console
144
+ Classifier: Environment :: Web Environment
145
+ Classifier: Intended Audience :: End Users/Desktop
146
+ Classifier: Programming Language :: Python :: 3.12
147
+ Classifier: Programming Language :: Python :: 3.13
148
+ Classifier: Topic :: Office/Business :: Financial
149
+ Requires-Python: >=3.12
150
+ Requires-Dist: fastapi
151
+ Requires-Dist: filelock>=3.13.0
152
+ Requires-Dist: httpx>=0.27.0
153
+ Requires-Dist: jinja2>=3.1.0
154
+ Requires-Dist: keyring>=25.0.0
155
+ Requires-Dist: numpy>=1.24.0
156
+ Requires-Dist: pydantic>=2.7.0
157
+ Requires-Dist: python-dateutil>=2.9.0
158
+ Requires-Dist: python-dotenv>=1.0.0
159
+ Requires-Dist: python-multipart>=0.0.9
160
+ Requires-Dist: rich>=13.7.0
161
+ Requires-Dist: slowapi>=0.1.9
162
+ Requires-Dist: tenacity>=8.2.0
163
+ Requires-Dist: typer>=0.12.0
164
+ Requires-Dist: tzdata>=2024.1
165
+ Requires-Dist: uvicorn
166
+ Provides-Extra: dev
167
+ Requires-Dist: httpx>=0.27.0; extra == 'dev'
168
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
169
+ Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
170
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
171
+ Provides-Extra: ml
172
+ Requires-Dist: sentence-transformers>=2.2.0; extra == 'ml'
173
+ Requires-Dist: torch>=2.0.0; extra == 'ml'
174
+ Description-Content-Type: text/markdown
175
+
176
+ # fin
177
+
178
+ A local-first personal finance tool. Syncs with your bank accounts via SimpleFIN or import CSV directly—analyzes spending patterns, detects subscriptions, and keeps your data local with encrypted backups.
179
+
180
+ ## Features
181
+
182
+ **Security & Privacy**
183
+ - **Local-Only Data**: All data stays on your machine in SQLite. No cloud sync, no tracking.
184
+ - **System Keyring**: Credentials stored in OS secure storage (Keychain, Credential Manager, Secret Service)
185
+ - **Encrypted Backups**: Age encryption for portable, audited backup files
186
+
187
+ **Accuracy & Trust**
188
+ - **Known Service Detection**: 150+ subscription services recognized instantly (Netflix, Spotify, etc.)
189
+ - **Pattern Validation**: `fin audit-subs` verifies detection accuracy—no false positives
190
+ - **Manual Override**: Correct any miscategorization; your choice persists
191
+
192
+ **Analysis**
193
+ - **Dashboard**: Visual overview of income, spending, alerts, and subscriptions
194
+ - **Smart Categorization**: Automatic transaction categorization with manual override
195
+ - **Subscription Detection**: Finds recurring charges and separates subscriptions from utility bills
196
+ - **Alerts**: Detects duplicate charges, unusual amounts, price increases
197
+ - **Bundle Detection**: Flags potential duplicate subscriptions (Disney+/Hulu/ESPN+ overlap)
198
+
199
+ **Interface**
200
+ - **Web Dashboard**: Full-featured UI at localhost
201
+ - **CLI Tools**: Complete command-line interface for automation
202
+ - **Mobile Responsive**: Works on phone, tablet, and desktop
203
+ - **Dark Mode**: Easy on the eyes
204
+
205
+ ## Getting Started
206
+
207
+ > **Two install paths are in progress.** A guided installer (no Python required, wizard-based setup) is under active development. The manual path below is current and stable.
208
+
209
+ ### Manual Install (Python required)
210
+
211
+ ```bash
212
+ # 1. Create virtual environment
213
+ python -m venv .venv
214
+ .venv\Scripts\activate # Windows
215
+ # source .venv/bin/activate # Mac/Linux
216
+
217
+ # 2. Install
218
+ pip install -e .
219
+
220
+ # 3. Start the web dashboard
221
+ fin web
222
+ # Browser opens automatically to http://127.0.0.1:8000/dashboard
223
+ # If no data exists, demo data loads with a "Connect your bank" banner
224
+ ```
225
+
226
+ The database is stored automatically at:
227
+ - **Windows**: `%APPDATA%\fin\fin.db`
228
+ - **macOS/Linux**: `~/.local/share/fin/fin.db`
229
+
230
+ Override with `FIN_DB_PATH` if needed.
231
+
232
+ ### Connecting Your Bank
233
+
234
+ From the dashboard, click **"Connect your bank"** to open the setup page. Two options:
235
+
236
+ **Import CSV** (easiest — no account required)
237
+ 1. Log into your bank and download a transaction export (CSV)
238
+ 2. Drag and drop it onto the import page
239
+ 3. fin detects the format automatically for Chase, BofA, Amex, Wells Fargo, and Capital One; shows a preview before importing
240
+
241
+ **SimpleFIN** (automatic daily sync, ~$1.50/month)
242
+ 1. Go to [SimpleFIN Bridge](https://beta-bridge.simplefin.org/), subscribe, and link your bank
243
+ 2. Copy your Setup Token
244
+ 3. Paste it into the SimpleFIN section on the connect page
245
+
246
+ See [docs/SIMPLEFIN_SETUP.md](docs/SIMPLEFIN_SETUP.md) for detailed SimpleFIN instructions.
247
+
248
+ ### Docker
249
+
250
+ ```bash
251
+ # 1. Configure
252
+ cp .env.example .env
253
+ # Edit .env with your SimpleFIN access URL
254
+
255
+ # 2. Build & run
256
+ docker compose build
257
+ docker compose run --rm fin sync
258
+ docker compose run --rm fin web
259
+ ```
260
+
261
+ ## Security
262
+
263
+ Your financial data is sensitive. fin is designed with security as a priority.
264
+
265
+ ### Credential Storage
266
+
267
+ **Recommended: System Keyring**
268
+
269
+ ```bash
270
+ fin credentials set
271
+ # Prompted for SimpleFIN Access URL, stored securely
272
+ ```
273
+
274
+ Credentials are stored in:
275
+ - **Windows**: Credential Manager
276
+ - **macOS**: Keychain
277
+ - **Linux**: Secret Service (GNOME Keyring, KWallet)
278
+
279
+ Check status: `fin credentials status`
280
+
281
+ **Alternative: Environment File**
282
+
283
+ Create a `.env` file (gitignored):
284
+
285
+ ```bash
286
+ SIMPLEFIN_ACCESS_URL=https://your-access-url-from-simplefin
287
+ ```
288
+
289
+ Keyring takes priority over .env if both are configured.
290
+
291
+ ### Data Protection
292
+
293
+ **Full-Disk Encryption (Recommended)**
294
+
295
+ Enable your OS's built-in encryption:
296
+
297
+ | OS | Solution |
298
+ |----|----------|
299
+ | Windows | BitLocker (Pro/Enterprise) or VeraCrypt |
300
+ | macOS | FileVault |
301
+ | Linux | LUKS |
302
+
303
+ This protects your database at rest with zero configuration in fin.
304
+
305
+ **Encrypted Backups**
306
+
307
+ ```bash
308
+ # Create encrypted backup with passphrase
309
+ fin export-backup -p
310
+
311
+ # Or with age public key (for automated backups)
312
+ fin export-backup -r age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p
313
+
314
+ # Decrypt later
315
+ age -d -o fin.db fin_backup_20260123.finbak
316
+ ```
317
+
318
+ Requires `age`: `winget install FiloSottile.age` (Windows) / `brew install age` (macOS) / `apt install age` (Linux).
319
+
320
+ ### Why This Architecture?
321
+
322
+ We chose OS-level encryption + encrypted exports over SQLCipher because:
323
+ 1. Zero configuration for users who already have FileVault/BitLocker enabled
324
+ 2. No additional dependencies or build complexity
325
+ 3. `age` is a modern, audited tool with better key management
326
+ 4. You control when encryption happens (backups) vs always-on overhead
327
+
328
+ ## Web Dashboard
329
+
330
+ The dashboard displays your financial overview in a 5-card responsive layout.
331
+
332
+ ### Card 1: Cash Flow (Hero)
333
+ Shows income vs expenses side-by-side with a big "Kept $X" or "Over $X" number, savings rate, and a 3-month rolling comparison. Mid-month pacing projection appears if you're still in the current month. Pending transactions show a warning if they exceed the typical threshold.
334
+
335
+ ### Card 2: Monthly Commitments
336
+ Lists detected subscriptions and utility bills (using pattern detection over 400 days). Click any item to see all transactions from that merchant. Shows total committed this month as a percentage of income with a color-coded bar (green under 50%, yellow 50-70%, red over 70%). Inline price change alerts flag recent increases. Footer breaks down subscription vs bill totals.
337
+
338
+ ### Card 3: Spending Breakdown
339
+ Top 7 spending categories with horizontal bars and 3-month averages. Click any category to drill down to merchants and transactions. Outlier badges (+X%) highlight categories that exceed their 3-month average. Footer shows total vs 3-month comparison.
340
+
341
+ ### Card 4: Heads Up
342
+ Shows unusual charges with dismiss actions ("Looks fine" / "Flag it"), multi-month spending trends, and bill deviation alerts. When empty, displays "Nothing unusual this month."
343
+
344
+ ### Card 5: Your Trend
345
+ 6-month bar chart of net cash flow (kept vs over). Green bars for positive months, red for negative. Current month shown as dashed outline. Click any bar to navigate to that month. Footer shows 6-month average.
346
+
347
+ ### Navigation & Controls
348
+ - **Month navigation**: Previous/next buttons with current month indicator dot
349
+ - **Account filter**: Multi-select dropdown to focus on specific accounts
350
+ - **Transaction search**: Live results dropdown—type a merchant name or amount to find transactions
351
+ - **Keyboard accessible**: Tab navigation, Enter to select, Escape to close dropdowns
352
+
353
+ ### Drilldown System
354
+ Click any number, bar, category, or merchant to open a modal with the full transaction list. Sortable columns, account filtering, and scopes including income, spend, recurring, discretionary, net, merchant, and category.
355
+
356
+ ## Other Pages
357
+
358
+ **Connect** (`/connect`)
359
+ Import CSV files or connect via SimpleFIN. Drag-and-drop CSV upload with automatic format detection for major banks.
360
+
361
+ **Recurring Charges** (`/subs`)
362
+ Dedicated page for subscriptions and utility bills. Filter by account, see payment history, toggle between subscription and bill types, and export to CSV.
363
+
364
+ **Budget** (`/budget`)
365
+ Set spending targets by category. Compare targets vs actual spending with visual indicators.
366
+
367
+ **Audit** (`/audit`)
368
+ Review and correct transaction categorization. Manages override history for future reference.
369
+
370
+ ## Subscription Detection
371
+
372
+ fin uses a two-tier approach to find subscriptions:
373
+
374
+ ### Known Services (Instant)
375
+
376
+ 150+ well-known services are recognized immediately, even with just one charge:
377
+ - Streaming: Netflix, Hulu, Disney+, HBO Max, YouTube TV, Spotify
378
+ - Software: Adobe, Microsoft 365, GitHub, ChatGPT, 1Password
379
+ - Fitness: Peloton, Planet Fitness, Strava
380
+ - And many more...
381
+
382
+ ### Pattern Detection (3+ charges)
383
+
384
+ Unknown merchants are detected via:
385
+ - Consistent amounts (low variance)
386
+ - Regular intervals (weekly, monthly, annual)
387
+ - Recurring payment indicators
388
+
389
+ ### Verifying Accuracy
390
+
391
+ ```bash
392
+ # Audit what's being detected
393
+ fin audit-subs
394
+
395
+ # Show all detected (including pattern-based)
396
+ fin audit-subs --all
397
+ ```
398
+
399
+ ### Bundle Detection
400
+
401
+ ```bash
402
+ fin bundle-check
403
+ ```
404
+
405
+ Flags vendor families where you might be paying twice (Disney+/Hulu/ESPN+, Apple services, etc.)
406
+
407
+ ## CLI Commands
408
+
409
+ ### Everyday Use
410
+
411
+ | Command | Description |
412
+ |---------|-------------|
413
+ | `fin sync` | Pull latest transactions from bank |
414
+ | `fin web` | Start the web dashboard (browser opens automatically) |
415
+ | `fin web --no-browser` | Start without auto-opening browser |
416
+ | `fin status` | Financial status at a glance (CLI) |
417
+ | `fin trend` | Monthly trend over time |
418
+
419
+ ### Analysis & Audit
420
+
421
+ | Command | Description |
422
+ |---------|-------------|
423
+ | `fin drill recurring` | All recurring expenses |
424
+ | `fin drill one-offs` | Discretionary spending |
425
+ | `fin drill alerts` | All alerts with details |
426
+ | `fin drill income` | Income sources |
427
+ | `fin audit-subs` | Verify subscription detection accuracy |
428
+ | `fin bundle-check` | Find duplicate/overlapping subscriptions |
429
+ | `fin dashboard-cli` | Full CLI dashboard with alerts |
430
+
431
+ ### Export & Backup
432
+
433
+ | Command | Description |
434
+ |---------|-------------|
435
+ | `fin export-csv` | Export all data to CSV files |
436
+ | `fin export-backup -p` | Encrypted backup with passphrase |
437
+ | `fin export-backup -r age1...` | Encrypted backup to recipient key |
438
+ | `fin export-summary` | Income vs spend summary with rolling averages |
439
+ | `fin export-duplicates` | Export duplicate subscription groups |
440
+ | `fin import-csv FILE` | Import transactions from CSV (CLI) |
441
+
442
+ ### Credentials & Setup
443
+
444
+ | Command | Description |
445
+ |---------|-------------|
446
+ | `fin setup TOKEN` | Exchange SimpleFIN setup token for access URL |
447
+ | `fin credentials set` | Store credentials in system keyring |
448
+ | `fin credentials status` | Show credential source (keyring/env/none) |
449
+ | `fin credentials clear` | Remove credentials from keyring |
450
+
451
+ ## Sync Options
452
+
453
+ ```bash
454
+ # Daily sync (14 days) - catches new transactions
455
+ fin sync --quick
456
+
457
+ # Weekly sync (30 days) - default, covers statement cycle
458
+ fin sync
459
+
460
+ # After vacation/absence (120 days)
461
+ fin sync --full
462
+
463
+ # January annual (400 days) - finds yearly subscriptions
464
+ fin sync --annual-bootstrap
465
+ ```
466
+
467
+ ## Troubleshooting
468
+
469
+ ### "No transactions found"
470
+ Run `fin sync --full` to pull more history, or import a CSV from `/connect`.
471
+
472
+ ### Categories are wrong
473
+ Click the category in the dashboard, then click the edit icon to override.
474
+
475
+ ### Subscription showing as Bill (or vice versa)
476
+ Click the type badge on the Recurring page to toggle.
477
+
478
+ ### Suspicious subscription detection
479
+ Run `fin audit-subs` to verify what's being detected.
480
+
481
+ ### Alerts not showing expected transactions
482
+ Use the date pickers to select a custom range, or click the month navigation to reset to the current month.
483
+
484
+ ## Development
485
+
486
+ ```bash
487
+ # Install with dev dependencies
488
+ pip install -e ".[dev]"
489
+
490
+ # Run tests
491
+ FIN_DB_PATH=/tmp/test.db pytest
492
+
493
+ # Type checking
494
+ mypy src/fin
495
+ ```
496
+
497
+ ## License
498
+
499
+ PolyForm Noncommercial 1.0.0