A CLI for your financial
data, built for the AI era.
fin connects your banks, cards and brokerages through Plaid and brings in your Amazon and Costco purchases. It runs locally on your laptop, keeps its keys in your Keychain, and costs nothing on Plaid's free Trial plan. Ask your agent, open it all as pages in your browser, query your transactions with SQL, or keep them in a Google Sheet.
Help me set up fin, a local command-line tool that reads my own bank and brokerage data through Plaid. fin is already installed; run `fin help` to see its commands. Use my web browser to do the navigating, clicking and form-filling for me, and leave me only the parts that need me personally. Ground rules: - Never type my passwords, verification codes or API secrets, and never accept terms, agreements or attestations for me. When one is needed, stop, tell me exactly what to click or paste and where, and wait. - Never put my Plaid secret in this chat, in a file, or anywhere except the hidden field of `fin setup` in my terminal. - Each institution I connect permanently uses one of my 10 free Plaid slots. Ask me before every `fin link`. Steps: 1. Open https://dashboard.plaid.com/signup. Fill in the non-secret fields (ask me for anything you don't know). When asked how I'll use Plaid, choose personal use (building something for myself). Let me set the password, accept the terms and verify my email. 2. Open https://dashboard.plaid.com/trial-plan and fill in the free Trial plan application. Describe the use as: "Personal, read-only access to my own bank and brokerage accounts with a local command-line tool." Let me review and submit it. It is usually approved right away and allows 10 connected institutions. Do NOT apply for full Production access: once that is submitted, the Trial plan is no longer available. 3. Open https://dashboard.plaid.com/developers/keys. Run `fin env production`. Then have me run `fin setup` in my terminal (it needs my keyboard): it opens a full-screen form where I paste the Client ID and the Production secret. fin checks them with Plaid and saves them only in my macOS Keychain. 4. Brand Plaid Link with fin's look, so the consent screen I see when connecting shows fin's mascot and colors. Download https://raw.githubusercontent.com/kilianc/fin/main/mascot-plaid.png, the 1024 x 1024 square logo with an opaque background. Open https://dashboard.plaid.com/link and edit the customization named "default" (fin uses the default). In its settings (gear icon, upper right), set language English and countries United States only, or Plaid will ignore it. On the Consent pane choose co-branded, upload mascot-plaid.png as the logo (ask me to pick the file if you can't upload it yourself), set the brand color to #81B1CF and the background color to #203A52, then click Publish. 5. Ask me which banks, credit cards and brokerages I want to connect. For each, run `fin institutions <name>` to confirm Plaid supports it, and tell me which slot count that leaves. 6. For each one I approve, run `fin link --yes --open` in the background. It opens Plaid Link in my browser, where I pick the institution and sign in; fin collects transactions and investments, whichever the institution supports. Only if `fin institutions` shows an institution as brokerage-only, use `fin link brokerage --yes --open` instead. 7. Run `fin sync` to save my transactions on this Mac, then finish with `fin items` and `fin accounts` and summarize what is connected and healthy. 8. Tell me I can now ask you about my money in plain words, or query it myself with `fin sql`. Ask whether I'd also like my transactions in a Google Sheet; if so, run `fin sheet --open` in the background and let me sign in to Google in the browser. 9. Ask whether I shop on Amazon and want each order broken into its items (experimental). If so, ask me for a name for the account and run `fin amazon login <name>`; macOS will ask me to allow Chrome Safe Storage. 10. Ask whether I shop at Costco and want my receipts and costco.com orders broken into their items (experimental). If so, ask me for a name for the account and run `fin costco login <name>`; macOS may ask me to allow Chrome Safe Storage.
you › Build me a monthly spending review. Compare it to the month before. ran fin transactions --since 2026-08-01 --json ✓ 412 transactions from 6 connections agent › September spending was $6,482, down 9% from August ($7,121). Rent and utilities held at $2,850. Dining out rose +31% to $694, mostly six weekend orders from Sushi Ota. Shopping fell $1,216 because August included a $1,180 standing desk. You saved $3,368, 34% of what came in.
$ fin accounts Accounts · 7 across 6 Items ╭───────────┬────────────────────┬──────┬──────────────────────┬──────────┬───────────┬──────────┬─────╮ │ Item │ Account │ Mask │ Type │ Current │ Available │ Limit │ Ccy │ ├───────────┼────────────────────┼──────┼──────────────────────┼──────────┼───────────┼──────────┼─────┤ │ chase │ Sapphire Preferred │ 4242 │ credit card credit │ 1834.12 │ 13165.88 │ 15000.00 │ USD │ │ chase │ Total Checking │ 8810 │ checking depository │ 6120.40 │ 6120.40 │ │ USD │ │ amex │ Gold Card │ 1005 │ credit card credit │ 912.77 │ │ │ USD │ │ citi │ Savings │ 3127 │ savings depository │ 24500.00 │ 24500.00 │ │ USD │ │ fidelity │ Roth IRA │ 0917 │ roth investment │ 48210.57 │ │ │ USD │ │ schwab │ Brokerage │ 3301 │ brokerage investment │ 96215.00 │ 42680.00 │ │ USD │ │ robinhood │ Individual │ 7712 │ brokerage investment │ 18440.10 │ │ │ USD │ ╰───────────┴────────────────────┴──────┴──────────────────────┴──────────┴───────────┴──────────┴─────╯ Balances from Plaid's daily refresh. Use --live to ask each bank now (billed per call).
$ fin accounts --json { "accounts": [ { "item": "chase", "institution": "Chase", "name": "Sapphire Preferred", "mask": "4242", "type": "credit", "subtype": "credit card", "balances": { "available": 13165.88, "current": 1834.12, "limit": 15000, "iso_currency_code": "USD" } }, … ], "env": "production", "errors": [], "live": false }
$ fin transactions --since 2026-10-01 Transactions · 2026-10-01 → 2026-10-09 · 8 ╭────────────┬───────┬────────────────────┬────────────────────┬──────────┬─────┬────────────────────╮ │ Date │ Item │ Account │ Description │ Amount │ Ccy │ Category │ ├────────────┼───────┼────────────────────┼────────────────────┼──────────┼─────┼────────────────────┤ │ 2026-10-09 │ chase │ Sapphire Preferred │ Sushi Ota │ -86.40 │ USD │ food and drink │ │ 2026-10-08 │ amex │ Gold Card │ Whole Foods Market │ -142.18 │ USD │ food and drink │ │ 2026-10-08 │ chase │ Total Checking │ ACME Corp Payroll │ 4925.00 │ USD │ income │ │ 2026-10-07 │ chase │ Sapphire Preferred │ Uber │ -23.90 │ USD │ transportation │ │ 2026-10-05 │ amex │ Gold Card │ Netflix │ -24.99 │ USD │ entertainment │ │ 2026-10-03 │ chase │ Total Checking │ Rent · October │ -2600.00 │ USD │ rent and utilities │ │ 2026-10-02 │ citi │ Savings │ Interest payment │ 31.20 │ USD │ income │ │ 2026-10-01 │ chase │ Sapphire Preferred │ United Airlines │ -540.00 │ USD │ travel │ ╰────────────┴───────┴────────────────────┴────────────────────┴──────────┴─────┴────────────────────╯ Money out 3417.47 · money in 4956.20. Shown here as negative = spent, positive = received; JSON keeps Plaid's sign.
$ fin transactions --since 2026-10-01 --json { "env": "production", "errors": [], "since": "2026-10-01", "transactions": [ { "item": "chase", "institution": "Chase", "account_name": "Sapphire Preferred", "account_mask": "4242", "date": "2026-10-09", "authorized_date": "2026-10-08", "name": "SUSHI OTA SAN DIEGO", "merchant_name": "Sushi Ota", "amount": 86.4, "iso_currency_code": "USD", "pending": false, "category": "FOOD_AND_DRINK", "category_detailed": "FOOD_AND_DRINK_RESTAURANT" }, … ], "until": "2026-10-09" }
$ fin amazon categorize --all Amazon items · 5 ╭───────────────────────┬────────────┬───────────────────────┬─────┬────────┬─────────────────────╮ │ Item │ Date │ Title │ Qty │ Cost │ Category │ ├───────────────────────┼────────────┼───────────────────────┼─────┼────────┼─────────────────────┤ │ 114-2290017-6612408#1 │ 2026-10-06 │ Cordless drill kit │ 1 │ 129.84 │ HOME_IMPROVEMENT │ │ 114-2290017-6612408#2 │ 2026-10-06 │ Ground coffee, 2 lb │ 2 │ 38.90 │ FOOD_AND_DRINK │ │ 114-2290017-6612408#3 │ 2026-10-06 │ Vitamin D3, 240 count │ 1 │ 18.62 │ MEDICAL │ │ 113-8805213-0147729#1 │ 2026-10-02 │ Kids' rain boots │ 1 │ 34.17 │ GENERAL_MERCHANDISE │ │ 113-8805213-0147729#2 │ 2026-10-02 │ Catan board game │ 1 │ 46.03 │ │ ╰───────────────────────┴────────────┴───────────────────────┴─────┴────────┴─────────────────────╯ Set one with fin amazon categorize --set ITEM CATEGORY [--product].
$ fin amazon categorize --all --json { "categories": [ "INCOME", … ], "items": [ { "item": "114-2290017-6612408#1", "order_id": "114-2290017-6612408", "date": "2026-10-06", "product": "B0C7KQ3X1M", "title": "Cordless drill kit", "quantity": 1, "cost": 129.84, "category": "HOME_IMPROVEMENT", "category_detailed": "HOME_IMPROVEMENT_HARDWARE", "category_source": "item", "account": "home", "bank_transaction": "AMAZON MKTPL*BB4L09 · 2026-10-07" }, … ] }
$ fin holdings Holdings · 7 positions · 162865.67 ╭───────────┬────────────┬────────────┬──────────┬────────┬──────────┬────────────┬──────────┬──────╮ │ Item │ Account │ Security │ Quantity │ Price │ Value │ Cost basis │ Gain │ Lots │ ├───────────┼────────────┼────────────┼──────────┼────────┼──────────┼────────────┼──────────┼──────┤ │ fidelity │ Roth IRA │ VTI │ 120 │ 288.10 │ 34572.00 │ 26400.00 │ 8172.00 │ 4 │ │ fidelity │ Roth IRA │ FXAIX │ 61.05 │ 223.40 │ 13638.57 │ 11020.00 │ 2618.57 │ 3 │ │ schwab │ Brokerage │ AAPL │ 150 │ 241.30 │ 36195.00 │ 21300.00 │ 14895.00 │ 5 │ │ schwab │ Brokerage │ SCHD │ 600 │ 28.90 │ 17340.00 │ 16200.00 │ 1140.00 │ 2 │ │ schwab │ Brokerage │ U S Dollar │ 42680 │ 1.00 │ 42680.00 │ 42680.00 │ 0.00 │ 0 │ │ robinhood │ Individual │ NVDA │ 80 │ 182.50 │ 14600.00 │ 9100.00 │ 5500.00 │ 6 │ │ robinhood │ Individual │ TSLA │ 10 │ 384.01 │ 3840.10 │ 4400.00 │ -559.90 │ 2 │ ╰───────────┴────────────┴────────────┴──────────┴────────┴──────────┴────────────┴──────────┴──────╯ Total value 162865.67, cost basis 131100.00 where known.
$ fin holdings --json { "env": "production", "errors": [], "holdings": [ { "item": "fidelity", "institution": "Fidelity", "account_name": "Roth IRA", "ticker": "VTI", "security_name": "Vanguard Total Stock Market ETF", "security_type": "etf", "quantity": 120, "price": 288.1, "price_as_of": "2026-10-08", "value": 34572, "cost_basis": 26400, "iso_currency_code": "USD", "tax_lots": [ { "quantity": 30, "purchase_price": 212.4, "original_purchase_datetime": "2022-03-14T00:00:00Z", "position_type": "LONG" }, … ] }, … ] }
$ fin sql "select category, sum(amount) filter (month(date) = 8) as aug, sum(amount) filter (month(date) = 9) as sep, round(100 * (sep - aug) / aug) as pct from transactions where amount > 0 and date between '2026-08-01' and '2026-09-30' group by category order by sep desc" 6 rows ╭─────────────────────┬────────┬────────┬─────╮ │ category │ aug │ sep │ pct │ ├─────────────────────┼────────┼────────┼─────┤ │ RENT_AND_UTILITIES │ 2850 │ 2850 │ 0 │ │ FOOD_AND_DRINK │ 1153.8 │ 1318 │ 14 │ │ TRAVEL │ 814.6 │ 1203.6 │ 48 │ │ GENERAL_MERCHANDISE │ 1700.4 │ 484.4 │ -72 │ │ TRANSPORTATION │ 412.3 │ 389.6 │ -6 │ │ ENTERTAINMENT │ 189.9 │ 236.4 │ 24 │ ╰─────────────────────┴────────┴────────┴─────╯ From ~/.local/share/fin/production.duckdb, synced Oct 9, 09:12. Run fin sync to refresh.
$ fin sql --json "select category, sum(amount) filter (month(date) = 8) as aug, sum(amount) filter (month(date) = 9) as sep, round(100 * (sep - aug) / aug) as pct from transactions where amount > 0 and date between '2026-08-01' and '2026-09-30' group by category order by sep desc" { "columns": ["category", "aug", "sep", "pct"], "env": "production", "rows": [ { "aug": 2850, "category": "RENT_AND_UTILITIES", "pct": 0, "sep": 2850 }, { "aug": 1153.8, "category": "FOOD_AND_DRINK", "pct": 14, "sep": 1318 }, … ], "synced": [ { "item": "chase", "item_id": "eVBnVMp7zdTJLkRNr33Rs6zr7KNJqBFL9DrE6", "transactions_update_status": "HISTORICAL_UPDATE_COMPLETE", "last_sync": "2026-10-09T16:12:00Z" }, … ] }
Made-up numbers in fin's real output format. In a terminal fin prints tables; when an agent runs it, JSON.
// fin ui · illustrative data
Or open it in your browser.
fin ui turns the local file into pages: net worth day by day, spending against last month, your portfolio, and a SQL editor that charts what it returns. fin serves them from 127.0.0.1 behind a random token, and they load nothing from the internet.
fin ui
fin transactions --ui
fin holdings --ui
fin sql "…" --ui// works with the banks, cards and brokerages Plaid connects to
Logos are trademarks of their owners. fin is independent and not affiliated with them or with Plaid.
// AI-generated reports · illustrative data
Ask in plain words. Get a report.
fin supplies the data. Your agent creates the layout, charts, and analysis.
“Build me a monthly spending review.” Compare it to the month before.
Try this prompt→
“How many Costco chickens and hot dogs did we buy?” Count rotisserie chickens and hot dog combos from our receipts over the last six months.
Try this prompt→
“Break down my Amazon spending item by item.” Use my order history to categorize purchases, unpack card charges, and track refunds.
Try this prompt→
“Find the subscriptions worth reviewing.” Find subscriptions, price increases, and anything I’m paying for twice.
Try this prompt→
“Put all my investments in one report.” Show my allocation and unrealized gains across brokerages.
Try this prompt→
“Show how my net worth changed this year.” Chart it month by month and explain what moved it.
Try this prompt→
// fin help security
Local and yours.
- reads
- Balances, transactions, holdings with tax lots, investment activity.
- never requests
- Plaid Auth or Identity: no account numbers, no personal details. Cannot move money.
- secrets
- macOS Keychain, service
fin. State in~/.config/fin/state.json, mode 0600. - data
- Transactions, a balance per account for each day you sync, and holdings in a DuckDB file in
~/.local/share/fin; query it withfin sqlor browse it withfin ui.fin sheetcopies them to a spreadsheet in your Google Drive, the only file there fin can see. - amazon
- Experimental and off until you run
fin amazon login: it reads your Amazon payments and order pages with your Chrome sign-in, so each charge opens into its items. - costco
- Experimental and off until you run
fin costco login: it reads your warehouse and gas receipts and costco.com orders with your Chrome sign-in, so each trip opens into its items. - servers
- No hosted service. fin calls Plaid's API from your laptop and prints the answer.
fin uiserves its pages on 127.0.0.1 only, behind a random token, with every font and script built into fin. - cost
- Free on Plaid's Trial plan, up to 10 institutions. MIT licensed.