spending-analysis
npx machina-cli add skill peerjakobsen/smartspender/spending-analysis --openclawSpending Analysis
Purpose
Provides rules for analyzing categorized transaction data — aggregating spending by category, comparing month-over-month, detecting unusual transactions, and generating savings recommendations.
Category Aggregation
For a given month, aggregate all categorized transactions:
- Group transactions by
category - For each category, compute:
total: Sum of all transaction amounts (absolute values for expenses)transaction_count: Number of transactionsavg_transaction:total / transaction_count
- Calculate each category's percentage of total spending:
category_total / total_spending × 100 - Sort categories by total (highest first)
Write results to monthly-summary.csv.
Receipt-Level Breakdown
For a given merchant, aggregate spending at the receipt-item level instead of the transaction level. Used when the user asks about spending at a specific merchant (e.g., "Hvad bruger jeg hos Bilka?").
Data Source
- Read
receipts.csv, filter bymerchant(case-insensitive match against normalized merchant name perskills/categorization/SKILL.md) - If
monthargument is provided, also filter bydatecolumn (YYYY-MM prefix match) - Collect all matching
receipt_idvalues and theirdatevalues - Determine which monthly files to read: extract unique YYYY-MM values from the receipt dates
- For each monthly file
receipt-items-{YYYY-MM}.csv: read it if it exists, filter to rows wherereceipt_idis in the collected set. Skip missing files. - Combine all matching rows
Aggregation Rules
Group matching receipt items by subcategory:
- For each subcategory, compute:
total: Sum oftotal_pricefor all items in that subcategoryitem_count: Sum ofquantityfor all items in that subcategoryavg_price:total / item_count
- Calculate each subcategory's percentage of total merchant spending:
subcategory_total / merchant_total × 100 - Sort subcategories by total (highest first)
Top Items per Subcategory
For each subcategory, identify the top 3 most purchased individual items:
- Group items by
item_namewithin the subcategory - For each item, compute:
purchase_count: Sum ofquantityacross all receiptsitem_total: Sum oftotal_priceacross all receipts
- Sort by
purchase_count(highest first), break ties byitem_total - Return top 3
Overall Top Items
Across all subcategories, identify the top 3 most frequently purchased items using the same logic as above but without the subcategory grouping.
Multi-Month Handling
- Month specified: Show totals for that month only. Header:
{Merchant} — Indkøbsoversigt {month_name} {year} - No month specified: Show all-time totals plus a per-month average. Header:
{Merchant} — Indkøbsoversigt samlet- Per-month average:
total / number_of_distinct_months(count distinct YYYY-MM values from matching receipts)
- Per-month average:
Output Format: Merchant Breakdown
## {Merchant} — Indkøbsoversigt {month or "samlet"}
**Antal kvitteringer**: {count}
**Samlet forbrug**: {total} kr
### Fordeling pr. varekategori
| Kategori | Beløb | Andel | Antal varer |
|----------|-------|-------|-------------|
| {subcategory} | {amount} kr | {pct}% | {item_count} |
| ... | ... | ... | ... |
### Hyppigst købte varer
1. {item_name} — {count}x — {total} kr
2. {item_name} — {count}x — {total} kr
3. {item_name} — {count}x — {total} kr
If no month is specified, append a summary line after the table:
**Gennemsnit pr. måned**: {avg} kr ({month_count} måneder)
Month-Over-Month Comparison
Compare the current month's spending to the previous month:
- For each category present in either month:
vs_prev_month:current_total - previous_total(absolute difference in kr)vs_prev_month_pct:(current_total - previous_total) / previous_total × 100
- Flag categories with significant changes:
- Increase > 20%: highlight as notable increase
- Decrease > 20%: highlight as notable decrease
- New category (not in previous month): flag as new spending area
If there is no previous month data (first month of tracking), skip the comparison.
Unusual Transaction Detection
Flag individual transactions that stand out:
By Amount
- Transaction amount > 3× the average for its category
- Single transaction > 5.000 kr (unless the category is Bolig or Indkomst)
By Frequency
- Multiple transactions to the same merchant on the same day (possible duplicate charges)
- Weekend transactions to work-related merchants
By Category Mix
- A merchant that usually falls in one category appearing in a different one
Savings Recommendations
Generate actionable suggestions based on analysis:
Subscription Savings
- Unused subscriptions: Subscriptions where
status: activebut no other transactions to that merchant's category (e.g., Viaplay active but no streaming usage signals) - Duplicate services: Multiple subscriptions in the same subcategory (e.g., Netflix + HBO Max + Viaplay = 3 streaming services)
- Price increases: Subscription amount increased > 10% from the average
Category Savings
- High dining spend: If Restauranter > 15% of total, suggest cooking more
- Transport optimization: If Taxi subcategory > Transport total × 30%, suggest alternatives
- Impulse shopping: If Shopping has many small transactions (> 10 in a month, avg < 200 kr), flag as potential impulse purchases
Formatting Suggestions
Present each suggestion as:
{action} — Spar {amount} kr/år
Example: "Opsig Viaplay — Spar 1.188 kr/år"
Danish Currency Formatting
All user-facing monetary values must use Danish formatting:
- Thousands separator: period (
.) - No decimal places for whole amounts in casual output
- Suffix:
kr(with space before) - Examples:
1.847 kr(one thousand eight hundred forty-seven)28.450 kr(twenty-eight thousand four hundred fifty)149 kr(no thousands separator needed)4.200 kr(four thousand two hundred)
Output Format: Spending Overview
When presenting a spending overview, use this structure:
## {Month} {Year} — Overblik
**Samlet forbrug**: {total} kr
### Fordeling pr. kategori
| Kategori | Beløb | Andel | Ændr. |
|----------|-------|-------|-------|
| {category} | {amount} kr | {pct}% | {change} |
| ... | ... | ... | ... |
### Abonnementer ({count} aktive)
| Tjeneste | Månedlig | Årlig | Status |
|----------|----------|-------|--------|
| {service} | {amount} kr | {annual} kr | {status} |
| ... | ... | ... | ... |
**Total abonnementer**: {total} kr/måned ({annual_total} kr/år)
### Forslag til besparelser
1. {suggestion} — Spar {amount} kr/år
2. {suggestion} — Spar {amount} kr/år
Output Format: Monthly Report
When generating a detailed report, include additional sections:
## {Month} {Year} — Månedlig rapport
### Resumé
{2-3 sentence summary of the month's spending}
### Forbrug pr. kategori
{Category breakdown table as above}
### Sammenlignet med {previous_month}
{Highlight notable changes — increases, decreases, new categories}
### Usædvanlige transaktioner
{List any flagged transactions with amounts and reasons}
### Abonnementer
{Subscription table as above}
{Note any changes: new subscriptions, cancellations, price changes}
### Handlinger i denne måned
{List actions taken from the Action Log: syncs, cancellations, etc.}
### Anbefalinger
{Savings suggestions with estimated annual impact}
Examples
Category Aggregation Example
Given 5 transactions in January 2026:
Netto -347.50 Dagligvarer
Føtex -289.00 Dagligvarer
Netflix -149.00 Abonnementer
DSB -72.00 Transport
Wolt -198.00 Restauranter
Monthly Summary rows:
month: 2026-01, category: Dagligvarer, total: 636.50, count: 2, avg: 318.25
month: 2026-01, category: Restauranter, total: 198.00, count: 1, avg: 198.00
month: 2026-01, category: Abonnementer, total: 149.00, count: 1, avg: 149.00
month: 2026-01, category: Transport, total: 72.00, count: 1, avg: 72.00
Savings Recommendation Example
Detected 3 streaming subscriptions:
- Netflix: 149 kr/måned (1.788 kr/år)
- HBO Max: 149 kr/måned (1.788 kr/år)
- Viaplay: 99 kr/måned (1.188 kr/år)
Total: 397 kr/måned (4.764 kr/år)
Suggestion: "Overvej at konsolidere streamingtjenester? Netflix + HBO Max + Viaplay = 397 kr/måned"
Source
git clone https://github.com/peerjakobsen/smartspender/blob/main/skills/spending-analysis/SKILL.mdView on GitHub Overview
Analyzes categorized transactions to reveal how money is spent by category, track month‑to‑month changes, detect unusual transactions, and generate savings recommendations. It outputs a structured monthly overview (monthly-summary.csv) and supports a receipt‑level breakdown for merchant‑specific insights.
How This Skill Works
Category aggregation for a month groups transactions by category and computes total (absolute for expenses), transaction_count, and avg_transaction; it then calculates each category's share of total spending and sorts by total, writing results to monthly-summary.csv. For merchant insights, the system performs a receipt-level breakdown by filtering receipts.csv for the merchant, optionally narrowing by month, collecting matching receipt_ids, and reading monthly receipt-items-YYYY-MM.csv files to aggregate by subcategory (total, item_count, avg_price) and determine merchant share and top items. It also enables month-over-month comparisons and flags unusual transactions to inform savings recommendations.
When to Use It
- You need a monthly spending overview for a specific month, with category totals, counts, and percentages.
- You want month-over-month comparisons to spot changing trends in spending.
- You want to investigate spending at a specific merchant using a receipt-item breakdown.
- You need a category-level view to identify savings opportunities and top items.
- You want automated savings recommendations based on unusual transactions and patterns.
Quick Start
- Step 1: Load your categorized transactions and receipts.csv data into the system.
- Step 2: Run category aggregation for the target month to generate monthly-summary.csv.
- Step 3: Optionally run a receipt-level breakdown for a merchant to see subcategories, top items, and savings recommendations.
Best Practices
- Normalize and validate category mapping to ensure consistency across months.
- Use absolute values for expense totals to avoid sign confusion.
- Filter by YYYY-MM when narrowing data to a specific period and handle missing files gracefully.
- Sort categories by total descending to surface the largest spend areas.
- For merchant analyses, rely on the receipt-item granularity to identify top items and price-sensitive patterns.
Example Use Cases
- Generate a monthly overview for June 2026 with category totals, percentages, and top spending categories.
- Use month-over-month comparison to highlight groceries increasing from 32% to 38% of total spend.
- Hvad bruger jeg hos Bilka? — receipt-level breakdown showing subcategories and top items.
- All-month totals for a merchant with per-month average to benchmark performance over a year.
- Flag unusual transactions and generate savings recommendations based on spending patterns.