Phase 1 — fix stale state after strong migration (Phase 1+2, 2026-07-05)
- README: corrected IPs (jellyfin 206→246, arriman 132→245, etc.),
added missing containers (128 trmnl, 129 house, 133 seanime, 134 romm,
124 authentik), updated last-refreshed date, added strong host context
- containers/101-jellyfin.md: IP 206→246, host hubris→strong, mount
/mnt/library→/mnt/media_local, GPU 760M→680M+RX7600, privilege→priv
- containers/118-elementsynapse.md: IP 239→242, added Host: strong
- containers/122-arriman.md: IP 132→245, mount→/mnt/media_local, added Host
- containers/129-house.md: IP 212→244, added Host: strong
- containers/130-grimmory.md: IP 213→247, mount→/mnt/media_local, added Host
- containers/121-caddy.md: fixed site list (books→grimmory, removed auth→VPS,
added house, roms, teddy, trmnl)
- hosts/strong.md: updated At-a-glance to reflect 7 LXCs hosted
- containers/123-claudio-bot.md, 127-mule-photos-new.md: archived to
containers/archive/ (were destroyed LXCs with living pages)
- inventory.yaml: verified correct — no changes needed
Phase 2 — structural cleanup
- infrastructure/index.md: one-page overview of all cross-cutting systems
- runbooks/: moved runbook-budget-from-csv.md and runbook-dpkg-interrupted.md
from operations/ with YAML frontmatter added
- plans/done/: moved 4 completed plans out of active view; updated index
- vms/index.md: added VM index page
Phase 3 — navigation & discoverability
- GLOSSARY.md: term definitions (Authentik, Caddy, LXC, VAAPI, etc.)
- README: added table of contents, links to glossary + infrastructure index
- investigations/: archived 2 resolved cases (crash-loop, authentik-migration)
to investigations/archive/; updated index with active vs archived sections
Phase 4 — ongoing discipline
- CONTRIBUTING.md: documented same-session update rule with explicit checklist
- README: replaced full LXC table with summary + link to containers/index.md
(single source of truth; de-duplication)
7.7 KiB
name, risk_class, inputs, references
| name | risk_class | inputs | references | ||
|---|---|---|---|---|---|
| budget-import-from-csv | config_mutation |
|
|
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-mcpis 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/subscriptionsroute 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. UseGET /budget/?month=YYYY-MMto 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:
amountpositive = income, negative = expense. - Recurring entries: set
is_recurring: 1+recurrence_interval: "monthly". Thedatefield sets the start month. recurrence_virtual: 1smooths 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 — usecycle_intervalon the subscription instead, orrecurrence_intervalon 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)
Cookie Share: how much to transfer monthly
Calculated from Jan–Jun 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_ruleRRULE strings are rejected by the API; usecycle_intervalinstead.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 Jan–Jun 2026 N26 Cookie account analysis.