finance-assistant-skill
Health Warn
- No license — Repository has no license file
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 5 GitHub stars
Code Pass
- Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Pass
- Permissions — No dangerous permissions requested
This skill acts as a personal finance copilot for AI coding assistants, handling everything from budget tracking and investment monitoring to bank statement imports (CSV/MT940/OFX) and scenario modeling. It processes highly sensitive financial data locally on your machine, claiming to encrypt it at rest.
Security Assessment
The tool handles extremely sensitive financial data, including bank transactions, debts, and net worth calculations. The light code scan found no dangerous patterns, hardcoded secrets, or dangerous permission requests. While the README claims a "privacy-first" approach that automatically adds the data directory to `.gitignore` and encrypts data at rest, users should still exercise caution. Because this tool integrates as an AI skill, all your parsed financial information is exposed to the AI model's context window. Overall risk is rated as Medium simply due to the highly sensitive nature of the financial data it processes.
Quality Assessment
The project is actively maintained, with its last push occurring today. However, it has extremely low community visibility (5 GitHub stars) and lacks a formal license file. Without a license, the legal terms of use and distribution are technically undefined, which may be a concern for professional or commercial environments.
Verdict
Use with caution — the code is actively maintained and free of obvious malware, but you must be comfortable trusting unlicensed, low-visibility software with your sensitive financial data and your AI provider's context window.
Personal finance copilot for Claude Code — budgets, savings goals, investments, debt optimization, taxes, insurance, net worth, bank import (CSV/MT940/OFX), multi-currency, and scenario modeling. Privacy-first, encrypted at rest.
Finance Assistant Skill
Personal finance copilot for Claude Code — budgets, savings goals, investments, debt optimization, taxes, insurance, net worth, bank import, and scenario modeling. Privacy-first: all data stays on your machine, encrypted at rest.
Table of Contents
- What It Does
- Quick Start
- How It Works
- Data Storage Layout
- Security & Privacy
- German Locale
- Bank Statement Import
- Module Reference
- Example Conversations
- Running Tests
- Origin
What It Does
Finance Assistant covers the full personal finance lifecycle across 11 operating modes:
| Mode | What you say | What you get |
|---|---|---|
| Budget Manager | "how am I doing on my budget?" | Variance by category, overspend alerts, pace warnings |
| Transaction Logger | "I spent €42 at REWE" | Logged, auto-categorized, budget actuals updated |
| Savings Planner | "I want to save €10k for a trip" | Timeline projection, monthly contribution needed |
| Investment Tracker | "show my portfolio" | Allocation, total return, XIRR, rebalance suggestions |
| Debt Optimizer | "best way to pay off my debts?" | Avalanche vs snowball comparison, debt-free date, interest saved |
| Tax Module | "what can I deduct?" | Locale-specific deductions (German 2024-2026 bundled) |
| Insurance Reviewer | "do I have enough coverage?" | Coverage gap analysis, renewal alerts |
| Net Worth Dashboard | "where do I stand?" | Net worth with 7-domain health score and trend |
| Data Import | "import this DKB CSV" | Parse → preview → categorize → deduplicate → import |
| Scenario Lab | "should I rent or buy?" | Before/after comparison with multi-year projection |
| Specialist Handoff | complex case | Structured brief for a Steuerberater or financial adviser |
Proactive Session Alerts
Every session start checks five domains automatically:
- Budget overspend or pacing warnings ("85% of Groceries used at 16% of month")
- Upcoming recurring payments in the next 7 days
- Savings goal deadlines within 45 days
- Tax filing deadlines within 45 days (German locale)
- Monthly FIRE progress bar (
[████████░░░░░░░░░░░░] 42.3% — €317k / €750k)
Quick Start
git clone https://github.com/googlarz/finance-assistant-skill.git
cd finance-assistant-skill
pip install -r requirements.txt
Add as a Claude Code skill in ~/.claude/settings.json:
{
"skills": [
{
"name": "finance-assistant",
"path": "/path/to/finance-assistant-skill"
}
]
}
Then in Claude Code: What's my financial health?
First Session
On first run, Finance Assistant:
- Automatically adds
.finance/to your.gitignore(prevents accidental commits of financial data) - Checks file permissions and warns if they're too open
- Starts a lightweight onboarding to collect your profile
If you're migrating from the original TaxDE skill, your existing profile is detected and migrated automatically — tax history preserved.
How It Works
Profile-First Architecture
Every session starts by loading your stored profile with profile_manager.py. All scripts operate on this profile + the .finance/ data directory. Nothing is hardcoded; everything adapts to your locale, currency, and situation.
Insight Pipeline
The insight engine (insight_engine.py) runs after every major data update. It dispatches to domain-specific generators:
budget_insights → savings_insights → investment_insights
→ debt_insights → insurance_insights → tax_insights → net_worth_insights
Each insight carries a 4-level status:
ready— actionable right nowneeds_input— needs one more fact from youneeds_evidence— needs a document or statementdetected— background risk found, FYI
And a confidence label: Definitive | Likely | Debatable | Avoid
Locale Plugin System
Tax rules are country-specific plugins in locales/<country_code>/. Each locale exports a standard interface:
LOCALE_CODE = "de"
SUPPORTED_YEARS = [2024, 2025, 2026]
def get_tax_rules(year) -> dict
def calculate_tax(profile, year) -> dict
def get_filing_deadlines(year) -> list[dict]
def get_social_contributions(gross, year) -> dict
def generate_tax_claims(profile, year) -> list[dict]
The German locale is fully bundled. New locales can be scaffolded automatically via locale_loader.py.
Multi-Currency
All amounts use the Money class (backed by Decimal) to avoid floating-point errors. Exchange rates are cached in .finance/exchange_rates.json with a 24-hour TTL; fallback rates are clearly marked as lower confidence.
Data Storage Layout
All data is project-local in .finance/. No cloud sync, no external APIs, no telemetry.
.finance/
├── finance_profile.json # Core profile (employment, housing, goals, preferences)
├── accounts/
│ ├── accounts.json # Account registry (no IBANs stored)
│ └── transactions/
│ └── <account>_<year>.json # Transaction log by account and year
├── budgets/
│ ├── 2025.json # Annual budget
│ └── 2025-04.json # Monthly budget with actuals
├── goals/
│ └── goals.json # Savings goals with progress
├── investments/
│ ├── portfolio.json # Holdings with current values
│ └── snapshots/
│ └── 2025-04-01.json # Point-in-time portfolio snapshots
├── debt/
│ ├── debts.json # Debt registry with rates and balances
│ └── payoff_plans/
│ └── <plan_id>.json # Avalanche/snowball simulation results
├── insurance/
│ └── policies.json # Insurance policies and renewal dates
├── net_worth/
│ └── snapshots/
│ └── 2025-04-01.json # Monthly net worth snapshots
├── taxes/
│ └── de/
│ ├── 2024.json # Tax year data
│ └── 2024-claims.json # Deduction claims for filing
├── imports/
│ └── import_log.json # Import history for deduplication
├── workspace/
│ └── 2025.json # Financial health dashboard
├── exchange_rates.json # Cached FX rates (24h TTL)
└── audit/
└── access_log.json # Audit trail of all data access
What is never stored:
- Bank login credentials, passwords, PINs, TANs
- Full IBAN or bank account numbers
- Credit card numbers or CVV codes
- Tax IDs, passport numbers, national IDs
- Raw document contents
Security & Privacy
Design Principles
- Local-only: All data lives in
.finance/on your machine. No network calls for your personal data. No telemetry. No cloud sync. - Structured summaries, not raw data: Transaction amounts and categories are stored, not raw bank statements or login sessions.
- You own the delete button: Every data category can be deleted individually or all at once.
- Encryption at rest: Fernet AES-128-CBC + HMAC-SHA256 — the same authenticated encryption scheme used in production web services.
- Passphrase quality enforced: The system rejects weak passphrases before encrypting (minimum 12 chars, character variety required), because a strong cipher with a weak key is still weak.
- Atomic writes: Encrypted files are written to a
.enc.tmpfile first, then atomically renamed — a power failure or crash cannot leave a half-encrypted, unreadable file. - File permissions:
harden_permissions()sets.finance/to700(owner-only directory) and all files to600(owner-only read/write). Other OS users on the same machine cannot read your data. - Git guard: On first session,
.finance/is automatically added to.gitignoreso financial data cannot be accidentally committed and pushed to a repository. - Audit log: Every significant data access (read, write, encrypt, export, delete) is logged to
audit/access_log.jsonwith a timestamp. - Sanitize before sharing:
sanitize_for_sharing(data)strips all PII (names, employers, payees, addresses) before you share data to get help — financial amounts and structures are preserved.
Encryption Details
Key derivation: PBKDF2-HMAC-SHA256
Iterations: 480,000 (NIST 2023 recommendation)
Salt: 16 bytes random per file (unique per encryption)
Cipher: AES-128 in CBC mode (via Fernet)
MAC: HMAC-SHA256 (Fernet built-in; prevents ciphertext tampering)
Encoding: Base64url
Dependency: pip install cryptography
Each file gets its own random salt. Two files encrypted with the same passphrase produce different ciphertexts — you cannot tell if two files contain the same data by comparing them.
The salt is stored alongside the ciphertext (standard practice — it only makes brute-force harder when combined with high iteration counts; it does not weaken the encryption).
Encrypted Export
Backups can be encrypted before leaving your machine:
# Encrypted backup — safe to store in cloud or email to yourself
export_all_data(passphrase="MyStr0ng!Passphrase")
# Plaintext export — keep offline only
export_all_data()
The encrypted export uses the same Fernet key derivation as individual file encryption. The passphrase is never stored anywhere.
All Security Controls
from scripts.data_safety import (
get_privacy_summary, # Full security status report
get_data_inventory, # Audit what's stored and where
harden_permissions, # chmod 600/700 on all .finance/ files
check_permissions, # Check for insecure file permissions
ensure_gitignore_protection, # Add .finance/ to .gitignore
encrypt_sensitive_files, # Encrypt profile, accounts, investments, debt
decrypt_sensitive_files, # Decrypt for use
encrypt_file, # Encrypt a single file
decrypt_file, # Decrypt a single file
export_all_data, # Export (plain or encrypted)
import_data, # Import from export file
delete_all_data, # Permanent wipe (requires confirm=True)
delete_category, # Delete one category (requires confirm=True)
sanitize_for_sharing, # Strip PII before sharing for help
get_access_log, # View audit trail
)
What Happens on First Session
skill.py (session start)
├── ensure_gitignore_protection() # .finance/ → .gitignore
├── check_permissions() # warn if group/world readable
└── get_profile() # load or start onboarding
└── (new user) show privacy statement
The privacy statement is shown once:
Your data lives only in
.finance/on your machine — nothing is ever uploaded. You can encrypt it, export it, or delete it completely at any time. I never store bank credentials, card numbers, IBANs, or government IDs.
Threat Model
| Threat | Protection |
|---|---|
| Another user on same machine reads your files | harden_permissions() — chmod 600/700 |
Accidental git push of financial data |
ensure_gitignore_protection() — automatic on session start |
| Laptop stolen, unencrypted disk | encrypt_sensitive_files(passphrase) + OS disk encryption (FileVault/LUKS) |
| Weak passphrase undermines AES | _check_passphrase_strength() — enforced before every encrypt call |
| Power failure during encryption corrupts file | Atomic write via .enc.tmp → rename() — POSIX atomic |
| Sharing data for help leaks names/employer | sanitize_for_sharing() — redacts all PII fields |
| Unexpected data access by a process | get_access_log() — timestamped audit trail |
| Cloud backup of export file exposes data | export_all_data(passphrase=...) — Fernet-encrypted export |
Known Limitations
- Memory: Decrypted data resides in Python process memory while the skill is running. Python does not securely zero memory on deallocation. This is a fundamental Python limitation.
- OS keychain: Passphrases are not stored in the OS keychain (macOS Keychain, GNOME Keyring). You must provide the passphrase each session when using encrypted files. This is deliberate — no stored secret means no stored secret to steal.
- Disk encryption: If your disk is not encrypted (macOS FileVault, Linux LUKS), Fernet protects against OS-level access control bypass but not against forensic disk reads. Enable full-disk encryption for maximum protection.
- Audit log: The access log itself is protected by
harden_permissions()but is not encrypted by default (it contains timestamps and action types, not financial amounts).
German Locale
The German locale (locales/de/) is fully bundled with support for tax years 2024, 2025, and 2026.
Supported Features
| Feature | Module |
|---|---|
| Income tax (Einkommensteuer), Soli, Kirchensteuer | tax_calculator.py |
| Social contributions (RV, KV, PV, AV) | social_contributions.py |
| Deduction discovery (Werbungskosten, Sonderausgaben, ab. Belastungen) | claim_rules.py |
| Filing deadlines (Abgabefrist, ELSTER) | tax_dates.py |
| Tax rule provenance and freshness | rule_updater.py |
| GKV/PKV insurance thresholds (Versicherungspflichtgrenze) | insurance_rules.py |
2026 Parameters
All 2026 parameters are filled (no None values). The Rürup ceiling (ruerup_max_single: 30,784) is estimated from the 2025 BBG progression (BBG 2026: €101,400 × 2025 ratio) and sourced in provenance.json.
Tax Classes
All Steuerklassen (I–VI) are supported, including:
- Married couples filing jointly (Ehegattensplitting)
- Single parents (Alleinerziehendenentlastungsbetrag)
- Dual-income couples (Steuerklasse III/V)
German-Specific References
| File | Content |
|---|---|
references/budgeting-strategies.md |
Berlin-specific tips: average rent, BVG Monatskarte, Rundfunkbeitrag |
references/insurance-checklist.md |
GKV vs PKV decision, Haftpflicht, Berufsunfähigkeit, what NOT to buy |
references/fire-planning.md |
FIRE with GKV minimum contributions, Vorabpauschale, Teilfreistellung |
references/debt-strategies.md |
Schufa, Dispo rates, Schuldnerberatung |
references/investment-basics.md |
VWCE, IWDA+EIMI, Freistellungsauftrag, Riester/Rürup |
Bank Statement Import
Supported Formats
| Format | Banks / Sources |
|---|---|
| CSV (auto-detected by header fingerprint) | DKB, ING-DiBa, Comdirect, N26, Wise (EUR), Revolut (EUR), generic fallback |
| MT940 | Any German bank (SWIFT standard) |
| OFX / QFX | Most German brokers, international banks |
Import Flow
- Detect format — header fingerprinting identifies the bank automatically
- Parse — extract date, amount, payee, description
- Preview — show first 10 transactions for review
- Confirm — user approves before any data is written
- Auto-categorize — keyword + payee rules assign categories
- Deduplicate — exact-match deduplication against existing transactions
- Update — account balance and budget actuals refreshed
Auto-Categorization
transaction_normalizer.py maps transactions to 30 categories across 8 domains. category_learner.py remembers corrections and applies them to future imports from the same payee — the categorization improves over time.
Module Reference
Core
| Module | Purpose |
|---|---|
skill.py |
Session entry: load profile, run security checks, surface alerts |
finance_storage.py |
Path resolution, JSON persistence, .taxde/ → .finance/ migration |
profile_manager.py |
v2 profile schema, deep-merge updates, TaxDE migration |
currency.py |
Money dataclass (Decimal), exchange rates with 24h cache |
Accounts & Transactions
| Module | Purpose |
|---|---|
account_manager.py |
CRUD for checking/savings/investment/loan accounts |
transaction_logger.py |
Log income/expense with auto-categorization (30 categories) |
recurring_engine.py |
Auto-generate recurring transactions (rent, salary, subscriptions) |
category_learner.py |
Learn from corrections to improve future auto-categorization |
Planning & Goals
| Module | Purpose |
|---|---|
budget_engine.py |
Create budgets, 50/30/20 auto-distribution, variance analysis |
goal_tracker.py |
Savings goals with completion projections |
Wealth
| Module | Purpose |
|---|---|
investment_tracker.py |
Portfolio CRUD, allocation, FIRE number, monthly snapshots |
investment_returns.py |
TWR, XIRR (Newton's method), per-holding performance |
debt_optimizer.py |
Avalanche/snowball simulation, mortgage optimization, debt-free date |
insurance_analyzer.py |
Policy tracking, coverage gaps, renewal alerts |
net_worth_engine.py |
Aggregate assets + investments − liabilities, JSON snapshots |
Tax
| Module | Purpose |
|---|---|
tax_engine.py |
Country-agnostic interface, delegates to locale plugin via importlib |
locale_registry.py |
Rule provenance (source URL, verification date, confidence) |
locale_loader.py |
Dynamic locale import, on-demand skeleton builder for new countries |
locales/de/ |
Full German locale (2024-2026, all parameters filled) |
Import
| Module | Purpose |
|---|---|
import_router.py |
Format detection and routing |
csv_importer.py |
DKB, ING-DiBa, Comdirect, N26, Wise, Revolut, generic |
mt940_importer.py |
SWIFT MT940 with graceful fallback if library not installed |
ofx_importer.py |
OFX/QFX with normalized date parsing |
transaction_normalizer.py |
Auto-categorize, deduplicate, normalize amounts |
Intelligence & Output
| Module | Purpose |
|---|---|
insight_engine.py |
Cross-domain insights, 4-status model, sorted by urgency |
scenario_engine.py |
Salary comparison, FIRE projection, rent-vs-buy, debt-vs-invest, mortgage |
workspace_builder.py |
7-domain weighted health score |
output_builder.py |
Structured deliverables assembled into an output suite |
report_renderer.py |
Markdown and HTML reports |
snapshot_scheduler.py |
Monthly auto-snapshots (portfolio and net worth) |
session_alerts.py |
Proactive session nudges (budget, bills, deadlines, FIRE) |
document_sorter.py |
Classify financial documents by type |
adviser_handoff.py |
Structured referral brief for Steuerberater or adviser |
Security
| Module | Purpose |
|---|---|
data_safety.py |
Fernet AES encryption, permissions hardening, git guard, export, delete, sanitize, audit |
Example Conversations
Budget Check
You: How am I doing on my April budget?
FA: €340 of €400 food budget used (85%) — 28 days into 30-day month. On pace.
Transport: €112 / €150 (75%) — fine.
Eating out: €89 / €80 — OVER by €9 ⚠
Suggestion: €11 left in eating out. One meal left this month.
Adjacent: Groceries has €60 remaining — cooking covers the gap.
FIRE Calculation
You: When can I retire if I invest €1,500/month?
FA: FIRE number: €900,000 (€36,000 expenses ÷ 4% withdrawal rate)
Current portfolio: €180,000
Monthly investment: €1,500 at 7% average return
Projected FIRE date: 2044 (18 years)
Formula: FV = PV×(1+r)^n + PMT×((1+r)^n−1)/r
Confidence: Likely (assumes 7% return; actual will vary)
What changes it: every extra €200/month cuts ~1 year.
Debt Optimization
You: Best strategy to pay off my 3 loans?
FA: Avalanche (highest rate first):
Credit card €3,200 @ 18.9% → Car loan €8,600 @ 5.9% → Ratenkredit €13,000 @ 3.4%
Interest saved vs minimum: €2,840 | Debt-free: Nov 2027
Snowball (smallest balance first):
Same order (happens to match) in this case
Interest saved vs minimum: €1,920 | Debt-free: Feb 2028
→ Avalanche saves €920 more and finishes 3 months earlier.
Choose snowball only if you need the win of a quick first payoff.
Tax Deductions (German)
You: What can I deduct this year?
FA: Profile: angestellt, Berlin, homeoffice 3 days/week
✓ Arbeitnehmer-Pauschbetrag: €1,230 (automatic)
✓ Homeoffice: €6/day × 210 days = €1,260 (at cap)
✓ Pendlerpauschale: €0 (homeoffice replaces commute)
? Gewerkschaftsbeitrag: enter your amount
? Fortbildungskosten: any training expenses this year?
Estimated refund above Pauschbetrag: ~€340
Confidence: Likely (exact figure needs actual receipts)
Running Tests
python3 -m pytest tests/ -v
# 154 tests — all modules, all scenarios
Tests use an isolated .finance/ directory per test via the isolated_finance_dir autouse fixture — they never touch real data.
Key test files:
| File | What it tests |
|---|---|
test_data_safety.py |
Encryption roundtrip, wrong passphrase, unique salts, permissions, git guard, encrypted export, sanitize |
test_session_alerts.py |
Budget warnings, goal deadline alerts, urgency sorting |
test_locale_de.py |
German tax calculation, 2026 parameters all non-null |
test_import_system.py |
CSV/MT940/OFX parsing, bank detection, deduplication |
test_scenario_engine.py |
FIRE, salary comparison, rent-vs-buy, debt-vs-invest |
test_workspace_builder.py |
7-domain health score calculation |
test_investment_tracker.py |
FIRE number, portfolio growth projection, snapshots |
test_debt_optimizer.py |
Avalanche vs snowball, interest savings, debt-free date |
Origin
Finance Assistant was transformed from TaxDE, a German tax assistant for Claude Code. All original TaxDE functionality is preserved in locales/de/.
The transformation kept every proven TaxDE pattern (storage layer, profile deep-merge, claim/insight pipeline, scenario engine, document sorter) while expanding from single-country tax to full personal finance.
TaxDE users are automatically migrated on first session — profile and tax history preserved.
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found