This file is a context document you can give to an AI coding assistant (Claude, ChatGPT, Copilot, etc.) so it understands the Quicken Amazon Matcher project and can help you set it up, troubleshoot it, or extend it.
How to use this file: Copy its contents into a conversation with your AI assistant, or upload it as an attachment. Then ask your question. The AI will have everything it needs to give you specific, accurate help.
When you buy things on Amazon and they show up in Quicken (macOS), the transactions just say "Amazon.com" or "AMZN Mktp US" with no indication of what you bought. If you have hundreds or thousands of Amazon transactions, it's impossible to know what any of them were for without logging into Amazon and cross-referencing manually.
Amazon lets you export your complete order history as a CSV file. That CSV contains the product name, order date, and amount for everything you've ever purchased.
This project matches those two data sources — Quicken transactions and Amazon order history — by date and dollar amount, then writes the actual product names into Quicken's memo field automatically.
You need a CSV file with your Amazon order history. There are a few ways to get this:
- Amazon's built-in export: Go to amazon.com → Your Account → Download order reports. This gives you a CSV but may be limited in date range.
- Request Your Data: Go to amazon.com → Your Account → Request Your Data → Select "Your Orders." Amazon will email you a download link within a few days. This is the most complete option.
- Browser extensions: There are extensions like "Amazon Order History Reporter" that can export your history. These vary in reliability.
The CSV must have these columns (the names must match exactly):
Order Date— when the order was placed (e.g.,2024-01-15or2024-01-15T19:18:06Z)Order ID— Amazon's order identifier (e.g.,113-1234567-8901234)Product Name— the item nameTotal Amount— the price charged (e.g.,29.99or$29.99)
An optional but helpful column:
Order Status— if present, cancelled orders are automatically skipped
On macOS, Quicken stores its data as a SQLite database inside a .quicken package. The typical path is:
~/Library/Application Support/Quicken/Documents/YOUR_FILE_NAME.quicken/data
If you use Quicken Beta, the path uses "Quicken Beta" instead of "Quicken":
~/Library/Application Support/Quicken Beta/Documents/YOUR_FILE_NAME.quicken/data
To find your exact path:
- Open Finder
- Hold Option and click the Go menu → Library
- Navigate to: Application Support → Quicken (or Quicken Beta) → Documents
- You'll see a file ending in
.quicken— that's a package - Right-click it → Show Package Contents
- Inside you'll find a file called
data— that's the SQLite database
Or ask your AI assistant to run:
find ~/Library/Application\ Support -name "data" -path "*.quicken/*" 2>/dev/nullThe script requires Python 3.7 or later. macOS usually has this pre-installed. Check by running:
python3 --versionNo additional packages need to be installed — the script uses only Python's standard library.
Understanding this section isn't required to use the script, but it's essential context if the AI needs to troubleshoot or modify anything.
Quicken on macOS uses Apple's Core Data framework, which stores its data as a SQLite database. This means:
- Every table name starts with
Z(e.g.,ZTRANSACTION,ZUSERPAYEE) - Every table has special columns:
Z_PK— the primary key (unique ID for each row)Z_ENT— entity type identifier (which "kind" of thing this row represents)Z_OPT— optimistic locking counter (critical for writes — see below)
ZTRANSACTION — One row per transaction (the main table)
├── Z_PK — Unique identifier
├── ZENTEREDDATE — Transaction date (Core Data epoch, see below)
├── ZAMOUNT — Amount (negative = debit/purchase, positive = credit/return)
├── ZNOTE — The memo/note field (this is what we write to)
├── ZUSERPAYEE — Foreign key → ZUSERPAYEE.Z_PK (who you paid)
└── Z_OPT — Version counter (MUST increment on writes)
ZUSERPAYEE — One row per payee name
├── Z_PK — Unique identifier
└── ZNAME — Payee name (e.g., "Amazon.com", "AMZN Mktp US")
ZCASHFLOWTRANSACTIONENTRY — Split lines within a transaction
├── Z_PK — Unique identifier
├── ZPARENT — Foreign key → ZTRANSACTION.Z_PK
├── ZAMOUNT — Split amount
├── ZCATEGORYTAG — Foreign key → ZTAG.Z_PK (category)
└── ZNOTE — Split-level memo (may have product info even when
the transaction-level memo is empty)
ZTAG — Categories and tags
├── Z_PK — Unique identifier
└── ZNAME — Tag/category name (e.g., "Groceries", "Recreation")
Every time you update a row, you must increment Z_OPT by 1. This is Core Data's optimistic locking mechanism. The correct update pattern is:
UPDATE ZTRANSACTION SET ZNOTE = 'your memo', Z_OPT = Z_OPT + 1 WHERE Z_PK = 12345If you forget to increment Z_OPT, Quicken may:
- Silently discard your changes on next launch
- Crash or show a Core Data conflict error
- Corrupt the optimistic lock state for that row
Core Data stores dates as seconds since January 1, 2001 (not 1970 like Unix). To convert:
unix_timestamp = core_data_timestamp + 978307200Or in SQL:
date(ZENTEREDDATE + 978307200, 'unixepoch') -- gives you a YYYY-MM-DD stringThe SQLite database is actively used by Quicken when it's open. Writing to it while Quicken is running can cause data corruption or lock conflicts. Always:
- Quit Quicken completely
- Run the script
- Reopen Quicken
The script creates a timestamped backup before every write operation, so you can always recover.
For each Quicken Amazon transaction that has no memo, we search the Amazon CSV for an order at the same dollar amount near the same date.
Quicken records a purchase as a negative ZAMOUNT. The script looks for Amazon orders:
- At the exact same dollar amount (within $0.01 tolerance)
- Within ±14 days of the Quicken transaction date (first pass)
- Expanding to ±30 days for MED/LOW certainty matches
The date window accounts for the delay between when Amazon charges your card and when the transaction posts in Quicken.
Returns are positive ZAMOUNT in Quicken. The critical insight here: returns must be matched backwards in time. When Amazon refunds you on September 10, the original purchase might have been in July or August. The script looks for:
- Amazon orders at the same dollar amount
- Placed 0 to 120 days before the Quicken credit date
This was one of the biggest bugs we had to fix during development — initially the script searched ±14 days for everything, which meant returns almost never matched because the purchase was weeks or months earlier.
Sometimes Amazon charges a single total for multiple items. For example, you buy a $15 book and a $10 charger, and Quicken shows a $25 transaction. The script handles this by:
- Grouping all Amazon CSV lines by Order ID
- Summing the individual item amounts within each order
- Matching the order total against the Quicken transaction
- Writing all item names joined with semicolons as the memo
Every match is classified by confidence:
| Tier | Criteria | Recommendation |
|---|---|---|
| HIGH | Single match within 7 days | Safe to auto-apply |
| MED | Single match within 8–30 days, or clear winner among multiple | Review a sample, then apply |
| LOW | Multiple different products at same price in time window | Needs human judgment |
Quicken transactions can have "splits" — sub-entries that break a transaction into categories. These splits have their own memo field. A transaction might have an empty memo at the top level but detailed product names in its splits (e.g., if someone previously categorized the splits by hand).
The script distinguishes between:
- Truly empty: No memo at transaction level AND no memos in splits → needs matching
- Split-documented: Empty transaction memo but splits have memos → already documented, skip
This prevents overstating the number of "missing" memos and avoids unnecessary work.
Open quicken_amazon_matcher.py in any text editor. Near the top, you'll see a CONFIG section. Edit these values:
QUICKEN_DB_PATH = os.path.expanduser(
"~/Library/Application Support/Quicken/Documents/My Finances.quicken/data"
)
AMAZON_CSV_PATH = os.path.expanduser(
"~/Downloads/Amazon Order History.csv"
)
AMAZON_PAYEE_NAMES = [
"Amazon.com",
"Amazon",
"AMZN Mktp US",
# ... add your payee names
]If you're not sure what Amazon appears as in your Quicken, run:
python3 quicken_amazon_matcher.py --discover-payeesThis searches your Quicken database for any payee containing "amazon" or "amzn" and shows you the exact names and how many transactions each has. Copy these names into the AMAZON_PAYEE_NAMES list.
python3 quicken_amazon_matcher.py --coverageThis shows how many Amazon transactions already have memos vs. how many are empty.
python3 quicken_amazon_matcher.py --scanThis runs the full matching engine and prints every match with its confidence tier, but writes nothing. Review the output, especially the HIGH matches — these should be essentially perfect.
Close Quicken, then:
python3 quicken_amazon_matcher.py --apply HIGHThis writes only HIGH certainty matches and creates a backup first. Reopen Quicken and verify a few transactions look correct.
If HIGH looked good:
python3 quicken_amazon_matcher.py --apply MEDThis applies both HIGH and MED matches. (It's safe to run after Step 5 — the script checks each memo is still empty before writing, so HIGH matches from the previous run won't be touched again.)
LOW matches have multiple candidate products at the same price. The --scan output shows you all the candidates. You can:
- Use Quicken's category tags to disambiguate (e.g., a transaction categorized as "Groceries" is more likely to be food than electronics)
- Check the Amazon website for the specific order
- Decide that an approximate memo is better than no memo at all
To apply LOW matches: --apply ALL (but review the scan output first).
The path in QUICKEN_DB_PATH is wrong. Use the Finder method described above to find the correct path, or run:
find ~/Library/Application\ Support -name "data" -path "*.quicken/*"Your Amazon CSV may have different column names. Open the CSV in a text editor and check the first line (the headers). The script expects exactly: Order Date, Order ID, Product Name, Total Amount. If yours are different, you can either:
- Rename the columns in the CSV
- Ask the AI to modify the
load_amazon_orders()function
This usually means the Amazon CSV dates aren't being parsed. The script handles several date formats (2024-01-15, 2024-01-15T19:18:06Z, 01/15/2024), but yours might be different. Check a few rows of the CSV and tell the AI what format the dates are in.
You may not have quit Quicken before running. Quicken caches data in memory. Quit completely (Cmd+Q, not just close the window) and reopen.
This happens when two different products cost exactly the same and shipped around the same time. The MED and LOW tiers flag these ambiguous cases. For HIGH matches this is extremely rare, but if you find one, you can manually edit the memo in Quicken.
If your Amazon order history CSV doesn't go back far enough, returns from older purchases won't find their original order. You may need a more complete CSV export. Also, Amazon sometimes combines multiple items into a single refund at an amount that doesn't correspond to any individual item — these can't be auto-matched.
Here are things you might want to ask your AI assistant to help with:
-
Add more payee sources: The same matching logic works for any retailer that gives you order history exports (Walmart, Target, etc.). You'd add a new CSV loader and payee name list.
-
Category-based disambiguation: If your Quicken transactions are already categorized (e.g., "Groceries", "Clothing"), the AI can write logic that uses those categories to pick the most likely candidate from LOW matches. For example, if a $15 transaction is categorized as "Groceries" and the two candidates are a protein bar vs. a phone case, the protein bar wins.
-
Batch manual overrides: Create a simple CSV of
PK,memopairs for transactions you've manually identified, and have the script apply them in bulk. -
Recurring purchases: If you buy the same item regularly (e.g., a subscription snack box at $12.30 every month), the AI can identify the pattern and apply a generic memo to all of them at once.
-
Undo support: The script creates backups, but you could add a
--rollbackcommand that restores from the most recent backup.
Find all Amazon payees:
SELECT Z_PK, ZNAME FROM ZUSERPAYEE
WHERE ZNAME LIKE '%amazon%' OR ZNAME LIKE '%amzn%';Count empty-memo Amazon transactions:
SELECT COUNT(*) FROM ZTRANSACTION
WHERE ZUSERPAYEE IN (your_payee_pks)
AND (ZNOTE IS NULL OR ZNOTE = '');See a transaction with its splits:
SELECT t.Z_PK, date(t.ZENTEREDDATE + 978307200, 'unixepoch') as dt,
t.ZAMOUNT, t.ZNOTE,
cfte.ZAMOUNT as split_amt, cfte.ZNOTE as split_memo, tag.ZNAME as category
FROM ZTRANSACTION t
LEFT JOIN ZCASHFLOWTRANSACTIONENTRY cfte ON cfte.ZPARENT = t.Z_PK
LEFT JOIN ZTAG tag ON tag.Z_PK = cfte.ZCATEGORYTAG
WHERE t.Z_PK = 12345;Safe memo update (always use this pattern):
UPDATE ZTRANSACTION SET ZNOTE = 'Your Memo Here', Z_OPT = Z_OPT + 1 WHERE Z_PK = 12345;Check coverage:
SELECT
COUNT(*) as total,
SUM(CASE WHEN ZNOTE IS NOT NULL AND ZNOTE != '' THEN 1 ELSE 0 END) as with_memo,
SUM(CASE WHEN ZNOTE IS NULL OR ZNOTE = '' THEN 1 ELSE 0 END) as empty
FROM ZTRANSACTION
WHERE ZUSERPAYEE IN (your_payee_pks);This script was developed over multiple sessions working with Claude (Anthropic) in Quicken's Cowork mode. The process involved:
- Reverse-engineering the Quicken Core Data schema
- Building the matching engine iteratively — starting with exact date+amount, then adding multi-item order support, backward-looking return matching, and confidence tiering
- Applying matches in waves: HIGH first (safest), then MED, then manually-reviewed LOW
- Discovering the split-memo distinction (transactions with empty top-level memo but documented splits)
- Using Quicken category tags to disambiguate LOW-confidence matches
The approach went from ~5% memo coverage to 98%+ across 4,150 Amazon transactions spanning 2002–2026.
Thank you. This solves a big problem