finance-cli 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 (170) hide show
  1. finance_cli-1.0.0/.gitignore +14 -0
  2. finance_cli-1.0.0/LICENSE +21 -0
  3. finance_cli-1.0.0/PKG-INFO +116 -0
  4. finance_cli-1.0.0/README.md +82 -0
  5. finance_cli-1.0.0/finance_cli/__init__.py +4 -0
  6. finance_cli-1.0.0/finance_cli/__main__.py +166 -0
  7. finance_cli-1.0.0/finance_cli/ai_categorizer.py +738 -0
  8. finance_cli-1.0.0/finance_cli/ai_statement_parser.py +631 -0
  9. finance_cli-1.0.0/finance_cli/budget_engine.py +432 -0
  10. finance_cli-1.0.0/finance_cli/categorizer.py +665 -0
  11. finance_cli-1.0.0/finance_cli/commands/__init__.py +1 -0
  12. finance_cli-1.0.0/finance_cli/commands/account_cmd.py +599 -0
  13. finance_cli-1.0.0/finance_cli/commands/balance_cmd.py +333 -0
  14. finance_cli-1.0.0/finance_cli/commands/biz_cmd.py +3292 -0
  15. finance_cli-1.0.0/finance_cli/commands/budget.py +485 -0
  16. finance_cli-1.0.0/finance_cli/commands/cat.py +855 -0
  17. finance_cli-1.0.0/finance_cli/commands/common.py +95 -0
  18. finance_cli-1.0.0/finance_cli/commands/daily.py +101 -0
  19. finance_cli-1.0.0/finance_cli/commands/db_cmd.py +209 -0
  20. finance_cli-1.0.0/finance_cli/commands/debt_cmd.py +702 -0
  21. finance_cli-1.0.0/finance_cli/commands/dedup_cmd.py +918 -0
  22. finance_cli-1.0.0/finance_cli/commands/export.py +119 -0
  23. finance_cli-1.0.0/finance_cli/commands/goal_cmd.py +380 -0
  24. finance_cli-1.0.0/finance_cli/commands/ingest.py +695 -0
  25. finance_cli-1.0.0/finance_cli/commands/liability_cmd.py +322 -0
  26. finance_cli-1.0.0/finance_cli/commands/liquidity_cmd.py +61 -0
  27. finance_cli-1.0.0/finance_cli/commands/monthly_cmd.py +362 -0
  28. finance_cli-1.0.0/finance_cli/commands/notify_cmd.py +166 -0
  29. finance_cli-1.0.0/finance_cli/commands/plaid_cmd.py +382 -0
  30. finance_cli-1.0.0/finance_cli/commands/plan.py +195 -0
  31. finance_cli-1.0.0/finance_cli/commands/projection_cmd.py +218 -0
  32. finance_cli-1.0.0/finance_cli/commands/provider_cmd.py +190 -0
  33. finance_cli-1.0.0/finance_cli/commands/rules.py +505 -0
  34. finance_cli-1.0.0/finance_cli/commands/schwab_cmd.py +125 -0
  35. finance_cli-1.0.0/finance_cli/commands/setup_cmd.py +828 -0
  36. finance_cli-1.0.0/finance_cli/commands/spending_cmd.py +202 -0
  37. finance_cli-1.0.0/finance_cli/commands/stripe_cmd.py +384 -0
  38. finance_cli-1.0.0/finance_cli/commands/subs.py +555 -0
  39. finance_cli-1.0.0/finance_cli/commands/summary_cmd.py +297 -0
  40. finance_cli-1.0.0/finance_cli/commands/txn.py +899 -0
  41. finance_cli-1.0.0/finance_cli/commands/weekly.py +209 -0
  42. finance_cli-1.0.0/finance_cli/config.py +81 -0
  43. finance_cli-1.0.0/finance_cli/data/rules.yaml +88 -0
  44. finance_cli-1.0.0/finance_cli/db.py +234 -0
  45. finance_cli-1.0.0/finance_cli/debt_calculator.py +535 -0
  46. finance_cli-1.0.0/finance_cli/dedup.py +403 -0
  47. finance_cli-1.0.0/finance_cli/exporters.py +199 -0
  48. finance_cli-1.0.0/finance_cli/extractors/__init__.py +214 -0
  49. finance_cli-1.0.0/finance_cli/extractors/ai_extractor.py +139 -0
  50. finance_cli-1.0.0/finance_cli/extractors/azure_extractor.py +394 -0
  51. finance_cli-1.0.0/finance_cli/extractors/bsc_extractor.py +359 -0
  52. finance_cli-1.0.0/finance_cli/forecasting.py +381 -0
  53. finance_cli-1.0.0/finance_cli/importers/__init__.py +1006 -0
  54. finance_cli-1.0.0/finance_cli/importers/_legacy_pdf_extractors.py +305 -0
  55. finance_cli-1.0.0/finance_cli/importers/csv_normalizers.py +454 -0
  56. finance_cli-1.0.0/finance_cli/importers/pdf.py +782 -0
  57. finance_cli-1.0.0/finance_cli/ingest_validation.py +526 -0
  58. finance_cli-1.0.0/finance_cli/institution_names.py +107 -0
  59. finance_cli-1.0.0/finance_cli/liquidity.py +158 -0
  60. finance_cli-1.0.0/finance_cli/logging_config.py +53 -0
  61. finance_cli-1.0.0/finance_cli/mcp_server.py +2313 -0
  62. finance_cli-1.0.0/finance_cli/migrate_legacy.py +46 -0
  63. finance_cli-1.0.0/finance_cli/migrations/001_initial.sql +186 -0
  64. finance_cli-1.0.0/finance_cli/migrations/002_extensions.sql +220 -0
  65. finance_cli-1.0.0/finance_cli/migrations/003_balances_liabilities.sql +75 -0
  66. finance_cli-1.0.0/finance_cli/migrations/004_cooldown_timestamps.sql +3 -0
  67. finance_cli-1.0.0/finance_cli/migrations/005_plaid_item_institution_id.sql +4 -0
  68. finance_cli-1.0.0/finance_cli/migrations/006_ai_parse_audit.sql +5 -0
  69. finance_cli-1.0.0/finance_cli/migrations/007_normalize_dates_iso.sql +4 -0
  70. finance_cli-1.0.0/finance_cli/migrations/008_account_aliases.sql +7 -0
  71. finance_cli-1.0.0/finance_cli/migrations/009_content_hash.sql +2 -0
  72. finance_cli-1.0.0/finance_cli/migrations/010_backend_dedupe.sql +31 -0
  73. finance_cli-1.0.0/finance_cli/migrations/011_import_batch_extras.sql +4 -0
  74. finance_cli-1.0.0/finance_cli/migrations/012_category_normalization.sql +222 -0
  75. finance_cli-1.0.0/finance_cli/migrations/013_subscription_recurring.sql +4 -0
  76. finance_cli-1.0.0/finance_cli/migrations/014_normalize_account_ids.sql +30 -0
  77. finance_cli-1.0.0/finance_cli/migrations/015_category_pipeline.sql +214 -0
  78. finance_cli-1.0.0/finance_cli/migrations/016_account_source.sql +16 -0
  79. finance_cli-1.0.0/finance_cli/migrations/017_provider_routing.sql +5 -0
  80. finance_cli-1.0.0/finance_cli/migrations/018_backfill_pdf_payment_flags.sql +13 -0
  81. finance_cli-1.0.0/finance_cli/migrations/019_account_type_override.sql +13 -0
  82. finance_cli-1.0.0/finance_cli/migrations/020_business_accounting.sql +265 -0
  83. finance_cli-1.0.0/finance_cli/migrations/021_stripe_integration.sql +224 -0
  84. finance_cli-1.0.0/finance_cli/migrations/022_tax_compliance.sql +7 -0
  85. finance_cli-1.0.0/finance_cli/migrations/023_biz_section_budgets.sql +12 -0
  86. finance_cli-1.0.0/finance_cli/migrations/024_settings_table.sql +5 -0
  87. finance_cli-1.0.0/finance_cli/migrations/025_mileage_and_contractors.sql +50 -0
  88. finance_cli-1.0.0/finance_cli/migrations/026_goals.sql +16 -0
  89. finance_cli-1.0.0/finance_cli/migrations/027_budget_use_type.sql +40 -0
  90. finance_cli-1.0.0/finance_cli/migrations/028_subscription_type.sql +2 -0
  91. finance_cli-1.0.0/finance_cli/migrations/029_investment_sync.sql +1 -0
  92. finance_cli-1.0.0/finance_cli/models.py +61 -0
  93. finance_cli-1.0.0/finance_cli/plaid_client.py +2979 -0
  94. finance_cli-1.0.0/finance_cli/provider_routing.py +66 -0
  95. finance_cli-1.0.0/finance_cli/schwab_client.py +406 -0
  96. finance_cli-1.0.0/finance_cli/sheets_export.py +1002 -0
  97. finance_cli-1.0.0/finance_cli/spending_analysis.py +149 -0
  98. finance_cli-1.0.0/finance_cli/stripe_client.py +846 -0
  99. finance_cli-1.0.0/finance_cli/subscriptions.py +796 -0
  100. finance_cli-1.0.0/finance_cli/tests/conftest.py +8 -0
  101. finance_cli-1.0.0/finance_cli/tests/test_account_cmd.py +536 -0
  102. finance_cli-1.0.0/finance_cli/tests/test_account_type_override.py +255 -0
  103. finance_cli-1.0.0/finance_cli/tests/test_account_unification.py +468 -0
  104. finance_cli-1.0.0/finance_cli/tests/test_ai_categorizer.py +480 -0
  105. finance_cli-1.0.0/finance_cli/tests/test_ai_statement_parser.py +642 -0
  106. finance_cli-1.0.0/finance_cli/tests/test_balance.py +106 -0
  107. finance_cli-1.0.0/finance_cli/tests/test_balances_liabilities.py +159 -0
  108. finance_cli-1.0.0/finance_cli/tests/test_biz.py +57 -0
  109. finance_cli-1.0.0/finance_cli/tests/test_biz_cmd.py +1228 -0
  110. finance_cli-1.0.0/finance_cli/tests/test_budget_alerts.py +171 -0
  111. finance_cli-1.0.0/finance_cli/tests/test_budget_use_type.py +687 -0
  112. finance_cli-1.0.0/finance_cli/tests/test_business_accounting.py +729 -0
  113. finance_cli-1.0.0/finance_cli/tests/test_cat_cmd.py +301 -0
  114. finance_cli-1.0.0/finance_cli/tests/test_categorizer.py +376 -0
  115. finance_cli-1.0.0/finance_cli/tests/test_cli_parse_errors.py +39 -0
  116. finance_cli-1.0.0/finance_cli/tests/test_cli_report_quality.py +350 -0
  117. finance_cli-1.0.0/finance_cli/tests/test_csv_normalizers.py +912 -0
  118. finance_cli-1.0.0/finance_cli/tests/test_data002_payment_fix.py +801 -0
  119. finance_cli-1.0.0/finance_cli/tests/test_db_commands.py +221 -0
  120. finance_cli-1.0.0/finance_cli/tests/test_debt_calculator.py +342 -0
  121. finance_cli-1.0.0/finance_cli/tests/test_debt_cmd.py +195 -0
  122. finance_cli-1.0.0/finance_cli/tests/test_debt_impact.py +459 -0
  123. finance_cli-1.0.0/finance_cli/tests/test_dedup.py +2178 -0
  124. finance_cli-1.0.0/finance_cli/tests/test_empty_response_context.py +55 -0
  125. finance_cli-1.0.0/finance_cli/tests/test_export_income.py +173 -0
  126. finance_cli-1.0.0/finance_cli/tests/test_extractors.py +505 -0
  127. finance_cli-1.0.0/finance_cli/tests/test_forecasting.py +567 -0
  128. finance_cli-1.0.0/finance_cli/tests/test_goals.py +218 -0
  129. finance_cli-1.0.0/finance_cli/tests/test_import.py +1275 -0
  130. finance_cli-1.0.0/finance_cli/tests/test_ingest_cmd.py +1529 -0
  131. finance_cli-1.0.0/finance_cli/tests/test_ingest_validation.py +307 -0
  132. finance_cli-1.0.0/finance_cli/tests/test_institution_names.py +44 -0
  133. finance_cli-1.0.0/finance_cli/tests/test_json_contract.py +23 -0
  134. finance_cli-1.0.0/finance_cli/tests/test_liquidity.py +75 -0
  135. finance_cli-1.0.0/finance_cli/tests/test_logging_config.py +87 -0
  136. finance_cli-1.0.0/finance_cli/tests/test_mcp_server.py +1423 -0
  137. finance_cli-1.0.0/finance_cli/tests/test_migration_002.py +213 -0
  138. finance_cli-1.0.0/finance_cli/tests/test_migration_015.py +234 -0
  139. finance_cli-1.0.0/finance_cli/tests/test_mileage_and_contractors.py +671 -0
  140. finance_cli-1.0.0/finance_cli/tests/test_money_and_constraints.py +42 -0
  141. finance_cli-1.0.0/finance_cli/tests/test_monthly_cmd.py +470 -0
  142. finance_cli-1.0.0/finance_cli/tests/test_name_validation.py +252 -0
  143. finance_cli-1.0.0/finance_cli/tests/test_notify_module.py +255 -0
  144. finance_cli-1.0.0/finance_cli/tests/test_obligations.py +133 -0
  145. finance_cli-1.0.0/finance_cli/tests/test_pdf_account_derivation.py +647 -0
  146. finance_cli-1.0.0/finance_cli/tests/test_pdf_importers.py +129 -0
  147. finance_cli-1.0.0/finance_cli/tests/test_phase2_commands.py +458 -0
  148. finance_cli-1.0.0/finance_cli/tests/test_phase4_commands.py +123 -0
  149. finance_cli-1.0.0/finance_cli/tests/test_plaid_commands.py +552 -0
  150. finance_cli-1.0.0/finance_cli/tests/test_plaid_sync_logic.py +3313 -0
  151. finance_cli-1.0.0/finance_cli/tests/test_projection.py +156 -0
  152. finance_cli-1.0.0/finance_cli/tests/test_provider_routing.py +461 -0
  153. finance_cli-1.0.0/finance_cli/tests/test_rules_commands.py +503 -0
  154. finance_cli-1.0.0/finance_cli/tests/test_schwab_sync.py +165 -0
  155. finance_cli-1.0.0/finance_cli/tests/test_search_resilience.py +74 -0
  156. finance_cli-1.0.0/finance_cli/tests/test_setup_cmd.py +501 -0
  157. finance_cli-1.0.0/finance_cli/tests/test_sheets_export.py +1442 -0
  158. finance_cli-1.0.0/finance_cli/tests/test_spending.py +139 -0
  159. finance_cli-1.0.0/finance_cli/tests/test_spending_analysis.py +126 -0
  160. finance_cli-1.0.0/finance_cli/tests/test_stripe_client.py +629 -0
  161. finance_cli-1.0.0/finance_cli/tests/test_stripe_cmd.py +305 -0
  162. finance_cli-1.0.0/finance_cli/tests/test_subs_audit.py +399 -0
  163. finance_cli-1.0.0/finance_cli/tests/test_subscriptions.py +1504 -0
  164. finance_cli-1.0.0/finance_cli/tests/test_summary.py +177 -0
  165. finance_cli-1.0.0/finance_cli/tests/test_tax_compliance.py +616 -0
  166. finance_cli-1.0.0/finance_cli/tests/test_txn_explain.py +134 -0
  167. finance_cli-1.0.0/finance_cli/tests/test_txn_list_cli.py +100 -0
  168. finance_cli-1.0.0/finance_cli/tests/test_user_rules.py +470 -0
  169. finance_cli-1.0.0/finance_cli/user_rules.py +464 -0
  170. finance_cli-1.0.0/pyproject.toml +67 -0
@@ -0,0 +1,14 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ .pytest_cache/
4
+ .env
5
+
6
+ finance_cli/data/finance.db
7
+ finance_cli/data/*.db-shm
8
+ finance_cli/data/*.db-wal
9
+ logs/
10
+ inbox/
11
+ exports/mcp_cache/
12
+ dist/
13
+ build/
14
+ *.egg-info/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024-2026 Henry Chien
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,116 @@
1
+ Metadata-Version: 2.4
2
+ Name: finance-cli
3
+ Version: 1.0.0
4
+ Summary: Personal finance CLI: bank statement import, transaction categorization, budgets, and net worth tracking
5
+ License-Expression: MIT
6
+ License-File: LICENSE
7
+ Requires-Python: >=3.11
8
+ Requires-Dist: pydantic>=2.0
9
+ Requires-Dist: pyyaml>=6.0
10
+ Provides-Extra: all
11
+ Requires-Dist: fastmcp>=2.0; extra == 'all'
12
+ Requires-Dist: plaid-python>=20.0; extra == 'all'
13
+ Requires-Dist: schwab-py>=1.0; extra == 'all'
14
+ Requires-Dist: stripe>=7.0; extra == 'all'
15
+ Provides-Extra: dev
16
+ Requires-Dist: fastmcp>=2.0; extra == 'dev'
17
+ Requires-Dist: plaid-python>=20.0; extra == 'dev'
18
+ Requires-Dist: pytest>=7.0; extra == 'dev'
19
+ Requires-Dist: schwab-py>=1.0; extra == 'dev'
20
+ Requires-Dist: stripe>=7.0; extra == 'dev'
21
+ Provides-Extra: mcp
22
+ Requires-Dist: fastmcp>=2.0; extra == 'mcp'
23
+ Provides-Extra: plaid
24
+ Requires-Dist: plaid-python>=20.0; extra == 'plaid'
25
+ Provides-Extra: providers
26
+ Requires-Dist: plaid-python>=20.0; extra == 'providers'
27
+ Requires-Dist: schwab-py>=1.0; extra == 'providers'
28
+ Requires-Dist: stripe>=7.0; extra == 'providers'
29
+ Provides-Extra: schwab
30
+ Requires-Dist: schwab-py>=1.0; extra == 'schwab'
31
+ Provides-Extra: stripe
32
+ Requires-Dist: stripe>=7.0; extra == 'stripe'
33
+ Description-Content-Type: text/markdown
34
+
35
+ # finance-cli
36
+
37
+ Personal finance CLI and MCP server for AI-assisted financial management.
38
+
39
+ Import bank statements (Plaid, CSV, PDF), categorize transactions via rules + AI,
40
+ track budgets, subscriptions, debt, and net worth. SQLite backend, 130 MCP tools
41
+ for Claude Code integration.
42
+
43
+ ## Features
44
+
45
+ - **Multi-source import**: Plaid API, CSV statements, PDF statements (AI-parsed)
46
+ - **Smart categorization**: Keyword rules → vendor memory → Plaid PFC → AI fallback
47
+ - **Budget tracking**: Per-category budgets with alerts and forecasting
48
+ - **Debt management**: Dashboard, paydown simulator, spending impact analysis
49
+ - **Subscription detection**: Fixed + metered recurring charge detection
50
+ - **Business accounting**: P&L, Schedule C, estimated tax, 1099 tracking
51
+ - **Net worth tracking**: Balance snapshots, investment accounts, projections
52
+ - **130 MCP tools**: Full Claude Code integration for AI-assisted workflows
53
+
54
+ ## Quick Start
55
+
56
+ ```bash
57
+ pip install -e ".[all]" # Install with all provider extras
58
+ finance-cli setup init # Initialize database and seed categories
59
+ finance-cli setup connect # Link bank accounts via Plaid
60
+ finance-cli plaid sync # Sync transactions
61
+ finance-cli daily # Today's spending summary
62
+ ```
63
+
64
+ ## Installation
65
+
66
+ ```bash
67
+ # Core only (categorization, budgets, reports)
68
+ pip install -e .
69
+
70
+ # With specific providers
71
+ pip install -e ".[plaid]" # Plaid bank sync
72
+ pip install -e ".[stripe]" # Stripe revenue tracking
73
+ pip install -e ".[mcp]" # Claude Code MCP server
74
+ pip install -e ".[all]" # Everything
75
+ ```
76
+
77
+ ## Configuration
78
+
79
+ Set environment variables (or use a `.env` file):
80
+
81
+ ```bash
82
+ # Plaid (optional)
83
+ PLAID_CLIENT_ID=...
84
+ PLAID_SECRET=...
85
+ PLAID_ENV=production
86
+
87
+ # Stripe (optional)
88
+ STRIPE_API_KEY=...
89
+
90
+ # AI categorization (optional)
91
+ OPENAI_API_KEY=...
92
+ ANTHROPIC_API_KEY=...
93
+ ```
94
+
95
+ ## MCP Server (Claude Code)
96
+
97
+ ```bash
98
+ claude mcp add finance-cli -- python3 -m finance_cli.mcp_server
99
+ ```
100
+
101
+ ## Documentation
102
+
103
+ - [How It Works](docs/overview/HOW_IT_WORKS.md) — Architecture overview
104
+ - [Project Guide](docs/overview/PROJECT_GUIDE.md) — Detailed project guide
105
+ - [Agent Workflows](docs/AGENT_WORKFLOWS.md) — AI agent operational playbooks
106
+ - [Import Workflow](docs/ingest/INGEST_WORKFLOW.md) — Bank statement import guide
107
+ - [Adding Institutions](docs/developer/ADD_INSTITUTION_RUNBOOK.md) — CSV normalizer guide
108
+
109
+ ## Requirements
110
+
111
+ - Python 3.11+
112
+ - SQLite (included with Python)
113
+
114
+ ## License
115
+
116
+ MIT
@@ -0,0 +1,82 @@
1
+ # finance-cli
2
+
3
+ Personal finance CLI and MCP server for AI-assisted financial management.
4
+
5
+ Import bank statements (Plaid, CSV, PDF), categorize transactions via rules + AI,
6
+ track budgets, subscriptions, debt, and net worth. SQLite backend, 130 MCP tools
7
+ for Claude Code integration.
8
+
9
+ ## Features
10
+
11
+ - **Multi-source import**: Plaid API, CSV statements, PDF statements (AI-parsed)
12
+ - **Smart categorization**: Keyword rules → vendor memory → Plaid PFC → AI fallback
13
+ - **Budget tracking**: Per-category budgets with alerts and forecasting
14
+ - **Debt management**: Dashboard, paydown simulator, spending impact analysis
15
+ - **Subscription detection**: Fixed + metered recurring charge detection
16
+ - **Business accounting**: P&L, Schedule C, estimated tax, 1099 tracking
17
+ - **Net worth tracking**: Balance snapshots, investment accounts, projections
18
+ - **130 MCP tools**: Full Claude Code integration for AI-assisted workflows
19
+
20
+ ## Quick Start
21
+
22
+ ```bash
23
+ pip install -e ".[all]" # Install with all provider extras
24
+ finance-cli setup init # Initialize database and seed categories
25
+ finance-cli setup connect # Link bank accounts via Plaid
26
+ finance-cli plaid sync # Sync transactions
27
+ finance-cli daily # Today's spending summary
28
+ ```
29
+
30
+ ## Installation
31
+
32
+ ```bash
33
+ # Core only (categorization, budgets, reports)
34
+ pip install -e .
35
+
36
+ # With specific providers
37
+ pip install -e ".[plaid]" # Plaid bank sync
38
+ pip install -e ".[stripe]" # Stripe revenue tracking
39
+ pip install -e ".[mcp]" # Claude Code MCP server
40
+ pip install -e ".[all]" # Everything
41
+ ```
42
+
43
+ ## Configuration
44
+
45
+ Set environment variables (or use a `.env` file):
46
+
47
+ ```bash
48
+ # Plaid (optional)
49
+ PLAID_CLIENT_ID=...
50
+ PLAID_SECRET=...
51
+ PLAID_ENV=production
52
+
53
+ # Stripe (optional)
54
+ STRIPE_API_KEY=...
55
+
56
+ # AI categorization (optional)
57
+ OPENAI_API_KEY=...
58
+ ANTHROPIC_API_KEY=...
59
+ ```
60
+
61
+ ## MCP Server (Claude Code)
62
+
63
+ ```bash
64
+ claude mcp add finance-cli -- python3 -m finance_cli.mcp_server
65
+ ```
66
+
67
+ ## Documentation
68
+
69
+ - [How It Works](docs/overview/HOW_IT_WORKS.md) — Architecture overview
70
+ - [Project Guide](docs/overview/PROJECT_GUIDE.md) — Detailed project guide
71
+ - [Agent Workflows](docs/AGENT_WORKFLOWS.md) — AI agent operational playbooks
72
+ - [Import Workflow](docs/ingest/INGEST_WORKFLOW.md) — Bank statement import guide
73
+ - [Adding Institutions](docs/developer/ADD_INSTITUTION_RUNBOOK.md) — CSV normalizer guide
74
+
75
+ ## Requirements
76
+
77
+ - Python 3.11+
78
+ - SQLite (included with Python)
79
+
80
+ ## License
81
+
82
+ MIT
@@ -0,0 +1,4 @@
1
+ """Personal finance CLI package."""
2
+
3
+ __all__ = ["__version__"]
4
+ __version__ = "1.0.0"
@@ -0,0 +1,166 @@
1
+ """CLI entry point for finance_cli."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import sys
7
+
8
+ from .commands import (
9
+ account_cmd,
10
+ balance_cmd,
11
+ biz_cmd,
12
+ budget,
13
+ cat,
14
+ daily,
15
+ debt_cmd,
16
+ db_cmd,
17
+ dedup_cmd,
18
+ export,
19
+ goal_cmd,
20
+ ingest,
21
+ liability_cmd,
22
+ liquidity_cmd,
23
+ monthly_cmd,
24
+ notify_cmd,
25
+ plaid_cmd,
26
+ plan,
27
+ projection_cmd,
28
+ provider_cmd,
29
+ rules,
30
+ setup_cmd,
31
+ stripe_cmd,
32
+ schwab_cmd,
33
+ spending_cmd,
34
+ subs,
35
+ summary_cmd,
36
+ txn,
37
+ weekly,
38
+ )
39
+ from .commands.common import error_envelope, print_envelope, success_envelope
40
+ from .config import load_dotenv
41
+ from .db import connect, initialize_database
42
+ from .logging_config import setup_logging
43
+ from .migrate_legacy import migrate_legacy_source
44
+
45
+
46
+ class CLIParseError(Exception):
47
+ """Raised when CLI argument parsing fails with non-zero exit status."""
48
+
49
+ def __init__(self, message: str, exit_code: int = 2) -> None:
50
+ super().__init__(message)
51
+ self.exit_code = int(exit_code)
52
+
53
+
54
+ class SafeArgumentParser(argparse.ArgumentParser):
55
+ """ArgumentParser that raises exceptions instead of exiting on parse errors."""
56
+
57
+ def error(self, message: str) -> None:
58
+ raise CLIParseError(message, exit_code=2)
59
+
60
+ def exit(self, status: int = 0, message: str | None = None) -> None:
61
+ if status == 0:
62
+ super().exit(status=status, message=message)
63
+ return
64
+ detail = (message or "").strip() or "Argument parsing failed"
65
+ raise CLIParseError(detail, exit_code=status)
66
+
67
+
68
+ def register_migrate_command(subparsers, format_parent) -> None:
69
+ parser = subparsers.add_parser("migrate", parents=[format_parent], help="Migrate legacy financial_system CSVs")
70
+ parser.add_argument("--source", required=True)
71
+ parser.add_argument("--dry-run", action="store_true")
72
+ parser.set_defaults(func=handle_migrate, command_name="migrate")
73
+
74
+
75
+ def handle_migrate(args, conn):
76
+ summary = migrate_legacy_source(conn, source_dir=args.source, dry_run=args.dry_run)
77
+ txn_inserted = sum(item["inserted"] for item in summary.get("transactions", []))
78
+ cli_report = f"Migrated {len(summary.get('transactions', []))} files, inserted={txn_inserted}"
79
+ return {
80
+ "data": summary,
81
+ "summary": {
82
+ "total_transactions": txn_inserted,
83
+ "total_amount": 0,
84
+ },
85
+ "cli_report": cli_report,
86
+ }
87
+
88
+
89
+ def build_parser() -> argparse.ArgumentParser:
90
+ parser = SafeArgumentParser(prog="finance_cli")
91
+ format_parent = SafeArgumentParser(add_help=False)
92
+ format_parent.add_argument("--format", choices=["json", "cli"], default="json")
93
+
94
+ subparsers = parser.add_subparsers(dest="command", required=True)
95
+ txn.register(subparsers, format_parent)
96
+ account_cmd.register(subparsers, format_parent)
97
+ cat.register(subparsers, format_parent)
98
+ daily.register(subparsers, format_parent)
99
+ weekly.register(subparsers, format_parent)
100
+ budget.register(subparsers, format_parent)
101
+ export.register(subparsers, format_parent)
102
+ ingest.register(subparsers, format_parent)
103
+ db_cmd.register(subparsers, format_parent)
104
+ dedup_cmd.register(subparsers, format_parent)
105
+ subs.register(subparsers, format_parent)
106
+ liquidity_cmd.register(subparsers, format_parent)
107
+ balance_cmd.register(subparsers, format_parent)
108
+ liability_cmd.register(subparsers, format_parent)
109
+ plan.register(subparsers, format_parent)
110
+ plaid_cmd.register(subparsers, format_parent)
111
+ stripe_cmd.register(subparsers, format_parent)
112
+ schwab_cmd.register(subparsers, format_parent)
113
+ provider_cmd.register(subparsers, format_parent)
114
+ rules.register(subparsers, format_parent)
115
+ setup_cmd.register(subparsers, format_parent)
116
+ monthly_cmd.register(subparsers, format_parent)
117
+ notify_cmd.register(subparsers, format_parent)
118
+ debt_cmd.register(subparsers, format_parent)
119
+ biz_cmd.register(subparsers, format_parent)
120
+ summary_cmd.register(subparsers, format_parent)
121
+ spending_cmd.register(subparsers, format_parent)
122
+ projection_cmd.register(subparsers, format_parent)
123
+ goal_cmd.register(subparsers, format_parent)
124
+ register_migrate_command(subparsers, format_parent)
125
+
126
+ return parser
127
+
128
+
129
+ def main(argv: list[str] | None = None) -> int:
130
+ load_dotenv()
131
+ setup_logging()
132
+ parser = build_parser()
133
+ try:
134
+ args = parser.parse_args(argv)
135
+ except CLIParseError as exc:
136
+ command_name = "unknown"
137
+ if argv:
138
+ head = argv[0].strip()
139
+ if head:
140
+ command_name = head
141
+ envelope = error_envelope(command_name, str(exc))
142
+ print_envelope(envelope, "json")
143
+ return exc.exit_code
144
+
145
+ try:
146
+ initialize_database()
147
+ with connect() as conn:
148
+ result = args.func(args, conn)
149
+ envelope = success_envelope(
150
+ command=args.command_name,
151
+ data=result.get("data", {}),
152
+ summary=result.get("summary"),
153
+ cli_report=result.get("cli_report"),
154
+ )
155
+ print_envelope(envelope, args.format)
156
+ return 0
157
+ except Exception as exc:
158
+ command_name = getattr(args, "command_name", "unknown")
159
+ envelope = error_envelope(command_name, str(exc))
160
+ output_format = getattr(args, "format", "json")
161
+ print_envelope(envelope, output_format)
162
+ return 1
163
+
164
+
165
+ if __name__ == "__main__":
166
+ sys.exit(main())