Files
oikos/.agents/skills/runbook-budget-from-csv/SKILL.md
dtoro 5c5016b3c7 docs: reshape runbooks into .agents/skills/<name>/SKILL.md (phase 4)
Problem: runbooks are agent-executable procedures but lived at the repo root,
separate from the other agent instruction now under .agents/.

Change:
- Move runbooks/<name>.md -> .agents/skills/<name>/SKILL.md (folder per skill,
  matching the wiki-hq skills layout). Frontmatter (name, risk_class, inputs,
  verification, docs_update_checklist, transition) preserved.
- Rewrite links (inbound from plans; between-skill siblings) via the move map.
- Update prose references in AGENTS.md, HERMES.md, .agents/OIKOS.md, and the
  operations schema; fix a pre-existing stale link to operations/commands.md.

No code consumed runbooks/ by path, so nothing else changes.

Verification: all SKILL.md frontmatter parses with valid risk_class; every
lifecycle transition resolves to an oikos/ontology.yaml state; broken-link
count 127 -> 126 (fixed one, introduced none).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 14:39:31 +02:00

7.7 KiB
Raw Blame History

name, risk_class, inputs, references
name risk_class inputs references
budget-import-from-csv config_mutation
csv_file
containers/129-house.md

Runbook: Budget import from N26 CSV → Yuvomi

Distil a bank-export CSV into Yuvomi's Budget and Subscriptions modules using the yuvomi-mcp tools. Run this whenever a new CSV period needs to be summarised into targets and fixed costs.


Prerequisites

  • yuvomi-mcp is running on LXC 129 and connected as an MCP server in Claude.
  • The CSV is an N26 export (columns: Booking Date, Value Date, Partner Name, Partner Iban, Type, Payment Reference, Account Name, Amount (EUR), …).
  • API token: homelab secret yuvomi-api-token (decrypts on any enrolled client).
  • Direct API base: https://house.hubris.network/api/v1

API quirks (Yuvomi ≤ 0.77.x)

  • Subscriptions live under /budget/subscriptions, NOT /subscriptions/. A top-level /subscriptions route returns 404.
  • GET /budget/subscriptions{ data: { subscriptions: [...], summary: {...} } }
  • GET /budget/subscriptions/meta{ data: { categories: [...], payment_methods: [...] } }
  • POST /budget/subscriptions → create a subscription (name, amount, billing_cycle, cycle_interval, next_payment_date, currency, category_id, payment_method_id required)
  • GET /budget/ (no month) → returns only non-recurring base entries. Use GET /budget/?month=YYYY-MM to get all entries (recurring + one-time) for a month.
  • GET /budget/categories → expense category keys + income category names (German keys like "Erwerbseinkommen", "Sozialleistungen", "Geschenke & Transfers").
  • Budget entries: amount positive = income, negative = expense.
  • Recurring entries: set is_recurring: 1 + recurrence_interval: "monthly". The date field sets the start month.
  • recurrence_virtual: 1 smooths non-monthly amounts across all months in the summary (e.g. 55.08 € quarterly → shows as ~18.36 €/month).
  • Custom RRULE strings (recurrence_rule) are not accepted by the API — use cycle_interval on the subscription instead, or recurrence_interval on budget entries.

Subscription category IDs (as of 2026-06-26)

id name budget_subcategory_key
1 Entertainment subscription_entertainment
2 Productivity subscription_productivity
3 Utilities subscription_utilities
4 Health subscription_health
5 Education subscription_education
6 Other subscription_other

Payment method IDs

id name
1 Credit Card
2 Debit Card
3 PayPal
6 Bank Transfer / SEPA
7 Other

Step 1 — Categorise the transactions

Skip these as internal/already-covered:

  • Fixed costs you'll enter as subscriptions (Miete, SWM, SYNVIA, Hundefutter, Netflix, Grover, Rundfunk ARD, KuKita, Lillydoo)
  • Internal transfers (The Joy Pot ↔ Cookie, Hauptkonto, Tagesgeldkonto splits)
  • Identified income (Cookie Share, Kindergeld, Pocket Money credits, Distributor)
  • Fun Money pass-throughs (in and out same month → net zero)

Variable expense taxonomy:

Category key Subcategory key Examples
food groceries E-Center, Knuspr, EDEKA, Tegut, VollCorner, Lidl, Netto, REWE, KoRo, Roast Market
food restaurants_bars Restaurants, Lieferando, Cafes, Zeit für Brot, Baobab, Höflinger
personal_health beauty_cosmetics DM, Rossmann
personal_health pharmacy Apotheke, MVZ Dermatologie
transport apps_taxi Uber, RYD GMBH, MVG, Handyparken
shopping_clothing gifts Children products: Schlummersack, Catchy Kids, SP EVERY., Dukal, Berger-Lernwelt
shopping_clothing clothes_shoes Zalando, Ernsting's, Schuhmair, Thalia, Vinted, Airbnb, Hotel at Booking.com
shopping_clothing electronics Amazon, AMZN Mktp DE
housing renovation_maintenance IKEA, Markus Festl, Granit, Sostrene Grene, Mol* tischdecken, Gaertnerei, Dehner
education courses_college Kathrin Orlob (PEKiP), Nerina Aupperle
leisure streaming WOW wowtv.de
financial_other bank_fees Unidentified PayPal, Ratepay, N26 fees
Geschenke & Transfers (income) One-off incoming transfers

Step 2 — Create subscriptions

get_subscriptions_meta()    ← get category_id and payment_method_id

Standard Cookie household subscriptions (as of 2026-07):

Name Amount billing_cycle cycle_interval category_id payment_method_id
Miete 1080.00 monthly 1 6 (Other) 6 (Bank Transfer)
Strom (SWM) 79.00 monthly 1 3 (Utilities) 6
Internet / TV / Telefon 29.99 monthly 1 3 (Utilities) 6
Hundefutter 75.00 monthly 1 6 (Other) 6
Netflix 8.00 monthly 1 1 (Entertainment) 6
Grover 16.90 monthly 1 6 (Other) 2 (Debit Card)
Rundfunk ARD / ZDF 55.08 monthly 3 1 (Entertainment) 6
KuKita Daycare (Leon) 503.00 monthly 1 5 (Education) 6
Lillydoo diapers 56.70 monthly 2 4 (Health) 3 (PayPal)

Monthly equivalent total: 1,838.60 € (Yuvomi applies cycle_interval to prorate).


Step 3 — Add recurring income entries

stage_add_budget_entry(
    title="Kindergeld",
    amount=55.00,
    category="Sozialleistungen",
    date="YYYY-MM-01",
    is_recurring=True,
    recurrence_interval="monthly",
)
commit_pending(pending_id)

Standard recurring income:

Title Amount category
Kindergeld +55.00 Sozialleistungen
Cookie Share +2650.00 Erwerbseinkommen (see recommended amount below)

Step 4 — Post variable transactions

For each non-skipped CSV row, call stage_add_budget_entry with the mapped category/subcategory and the actual transaction amount and date. Use the Partner Name + Payment Reference as the title (truncate to 100 chars).


Step 5 — Verify

get_budget_summary("YYYY-MM")
list_subscriptions()

Expected for a full month with KuKita:

  • Fixed expenses ≥ 1,838 € (subscriptions)
  • Variable expenses ≥ 500 € (groceries alone)

Calculated from JanJun 2026 data (Cookie account, one-offs stripped):

€/month
Fixed costs (subscriptions) 1,839
Miete 1,080
KuKita (permanent from Jul 2026) 503
Strom + SYNVIA + Rundfunk + Netflix + Grover + Hundefutter + Lillydoo 256
Variable (6-month averages) 1,032
Groceries 595
Children products 142
Dining & cafes 100
Transport 66
Drugstore 52
Clothing, Amazon, Pharmacy 77
Total monthly spend ≈ 2,871
Minus Kindergeld (fixed income) 55
Minus Pocket Money (conservative ~600 €) 600
→ Recommended Cookie Share ≈ 2,650 €
With 200 € buffer ≈ 2,850 €

Current Cookie Share (Jun 2026): 1,995 € — shortfall ~655 €.

The gap was covered by irregular Pocket Money top-ups (avg 962 €/mo over 6 months, but highly variable: 121 €3,000 €). KuKita starting in June is the biggest step-up; raising Cookie Share to 2,650 € makes the budget self-sufficient without relying on top-ups.


Changelog

2026-06-29 — Corrections from first real import

  • Subscriptions endpoint is /budget/subscriptions, NOT /subscriptions/ (404).
  • recurrence_rule RRULE strings are rejected by the API; use cycle_interval instead.
  • GET /budget/ (no filter) returns only non-recurring entries; use ?month= for full view.
  • Added Cookie Share recommendation (2,650 €/month) based on 6-month expense analysis.
  • Added full category taxonomy table.

2026-06-29 — Initial runbook

Created from JanJun 2026 N26 Cookie account analysis.