# Finances Agent — Plaid + Claude

Auto-pull US Bank transactions, categorize, find recurring/wasteful charges, build a dashboard. Started 2026-06-22.

## What it does

1. **Connects to US Bank** via Plaid (one-time OAuth flow Cameron does once)
2. **Pulls transactions** every 6 hours (cron) — or instantly via Plaid webhook
3. **Stores all transactions** in a local SQLite DB
4. **Claude analyzes monthly:**
   - Categorizes transactions (refines Plaid's defaults)
   - Identifies recurring charges (subscriptions audit — "what can I cancel?")
   - Flags overspending categories
   - Suggests savings opportunities (idle cash → HYSA, etc.)
   - Anomaly detection (unusually large or unexpected transactions)
5. **Dashboard** — web UI showing income, spending by category, trend over time, recurring spend, savings rate

## Architecture decisions

### Plaid is the right stack
- Industry-standard aggregator. US Bank is fully supported.
- Plaid handles all credential security + OAuth + token rotation
- Alternative: Teller.io (smaller, more dev-friendly, US-only) — viable backup. Mint shut down; Tink is EU-focused.
- **Verdict: use Plaid.**

### Webhooks vs polling
- Plaid sends webhooks on `DEFAULT_UPDATE` when new transactions are available (within ~6 hrs of posting)
- Webhooks need a public URL → ngrok tunnel or Cloudflare Tunnel
- **MVP: skip webhooks, use 6-hour cron polling.** Simpler. Add webhooks later.

### Storage: SQLite
- Cameron's stack is already file-based
- One file, easy to back up
- Plenty fast for personal-scale data
- Easy to query for analysis

### Analysis: Claude (Sonnet 4.6)
- Monthly batch pass over transactions
- Outputs structured JSON: categorizations + insights
- Could iterate to streaming/agentic later

### Dashboard: Streamlit OR simple Flask
- **Streamlit** = fastest to build (Python-only, instant charts, ~1hr to working dashboard)
- **Flask + HTMX + Chart.js** = more flexible long-term
- **MVP: Streamlit.** Pivot to Flask if it doesn't scale.

## File structure

```
/data/cameron/life/projects/finances/
├── README.md                  ← this file
├── requirements.txt
├── .env.template              ← API key + Plaid config template
├── plaid_link.py              ← one-time OAuth Flask app — Cameron visits in browser
├── templates/
│   └── link.html              ← Plaid Link UI page
├── pull_transactions.py       ← cron-runnable: fetches new transactions, stores in DB
├── analyze.py                 ← Claude analysis pass: categorize, find recurring, suggest
├── subscriptions_audit.py     ← standalone: list all recurring charges with cancel-link guesses
├── dashboard.py               ← Streamlit dashboard
├── db.py                      ← SQLite helpers
├── schema.sql                 ← DB schema
├── tokens.json                ← stored access_token after Plaid Link (chmod 600, auto-created)
└── data/
    └── transactions.db        ← SQLite store (auto-created)
```

## What Cameron has to do (~30 min)

### 1. Sign up for Plaid (free)
- Go to https://dashboard.plaid.com/signup
- Create account
- **Important:** start in **Sandbox** mode (free, fake data) to verify everything works
- Then request **Production** access for real US Bank — free up to 100 Items (more than you need)

### 2. Get API credentials
- From Plaid Dashboard → Team Settings → Keys
- Copy `client_id` and `secret` (use Sandbox keys first, swap to Production once you're ready)

### 3. Fill in `.env`
```
PLAID_CLIENT_ID=
PLAID_SECRET=
PLAID_ENV=sandbox  # change to "production" after testing
ANTHROPIC_API_KEY=
```

### 4. Run the Plaid Link flow (one-time)
- `python plaid_link.py` → opens at http://localhost:5002
- Visit in browser → "Connect US Bank" button → Plaid Link modal appears
- Sandbox: use Plaid's test credentials (user `user_good`, pass `pass_good`)
- Production: real US Bank OAuth flow
- On success: `tokens.json` is created (chmod 600), contains `access_token`

### 5. Pull initial transactions
- `python pull_transactions.py` — pulls last 90 days from US Bank
- Stores in `data/transactions.db`

### 6. Set up cron (auto-pull)
```bash
crontab -e
# Add:
0 */6 * * * cd /data/cameron/life/projects/finances && python pull_transactions.py >> pull.log 2>&1
0 9 1 * * cd /data/cameron/life/projects/finances && python analyze.py monthly >> analyze.log 2>&1
0 9 * * 1 cd /data/cameron/life/projects/finances && python analyze.py weekly >> analyze.log 2>&1
```

### 7. View dashboard
- `streamlit run dashboard.py` → opens at http://localhost:8501
- Shows: balance, monthly spending by category, recurring charges, savings rate, anomalies

## Webhooks (v2, optional)
- Get a public URL via ngrok: `ngrok http 5002`
- Update webhook URL in Plaid Dashboard → Webhooks
- The Flask app handles `POST /webhook` → triggers `pull_transactions.py`

## Cost projection
- Plaid Production: ~$0.30/account/mo (one account = ~$3/yr)
- Claude API: ~$2-5/mo for monthly analysis pass
- Total: < $5/mo

## Analysis prompt scope (what Claude should look for)

The system prompt for `analyze.py` should ask Claude to:
1. **Categorize** every transaction (food/dining, groceries, subscriptions, transport, rent, utilities, etc.)
2. **Identify recurring charges** — same merchant + same amount + monthly/yearly pattern
3. **Flag potential cancels** — services you might not need (multiple streaming, forgotten subscriptions, etc.)
4. **Compute** monthly totals by category, savings rate, income, net flow
5. **Flag anomalies** — single transactions >2x category average
6. **Recommend savings moves** — if checking balance >> typical month's spending, suggest moving excess to HYSA (mention specific high-yield savings options at the time of analysis)

The monthly output goes to `analysis_YYYY-MM.md` in the project dir.

## Roadmap

### v0 (MVP — this scaffold)
- Plaid Link works
- Transactions pull into DB
- Streamlit dashboard shows basic charts
- Monthly Claude analysis runs

### v1
- Subscription audit with auto-cancel-link generator
- Weekly digest sent to glasses or email
- "Notify me when X happens" rules (large purchase, new merchant, etc.)

### v2
- Multi-account support (Cameron may have multiple bank accounts, brokerage, etc.)
- Investment account integration (Plaid Investments product)
- Tax prep helper (categorize for tax buckets)

### v3
- Spin out into a separate Claude agent (`finance_agent`)
- Glasses UI integration ("hey what's my spending this week")
