Rules

Rules System

Automatic transaction categorization via YAML rules.

How It Works

graph LR
    Txn[Transaction] --> Normalize[Normalize]
    Normalize --> Merchant[Match Merchant]
    Merchant --> Rules[Apply Rules]
    Rules --> Result[Category + Type]

Precedence

  1. User rules — per-user overrides in data/users/{id}/
  2. Merchant defaults — auto-category from matched merchant
  3. System rules — global rules in data/rules/system/
  4. Fallback — uncategorized

Rule Structure

- id: netflix-subscription
  match:
    merchant: "Netflix"
    amount: { gt: 10 }
  set:
    direction: expense
    group: fun_lifestyle
    category: entertainment
    subcategory: streaming
    confidence: 0.9

Match Conditions

Field Syntax Example
merchant string or list "REWE" or ["REWE", "Aldi"]
text contains/regex { contains: "aws" }
amount comparison { gt: 10, lt: 100 }

Logical Operators

match:
  all:                    # AND
    - text: { contains: "amazon" }
    - amount: { gt: 0 }
  any:                    # OR
    - merchant: "Amazon"
    - text: { matches: "amzn" }
  not:                    # negation
    - text: { contains: "refund" }

Set Fields

Field Description
direction income, expense, transfer_out, transfer_in, refund
group Budget group (see below)
category Specific area
subcategory Detail
confidence 0.0 - 1.0
tags List of tags

Groups

Group Purpose
fixed_costs Rent, insurance, tax, telecom
daily_life Groceries, transport, food
family Kids, education
fun_lifestyle Leisure, sports, gifts
finance_misc Income, transfers, savings

File Location

data/rules/
├── manifest.yaml        # Entry point
├── merchants/           # Merchant catalog (see merchants.md)
└── system/              # System rules by group
    ├── 10_fixed_costs/
    ├── 20_daily_life/
    ├── 30_family/
    ├── 40_fun_lifestyle/
    ├── 50_finance_misc/
    └── 99_fallback.yaml

See merchants.md for merchant normalization.


[!NOTE] The UI has a user-facing explainer in
app/templates/rules/_rules_explainer.html
Keep it in sync when updating this documentation.