Oct 27
Roles, situations and a calendar feed
Over the last two days freundebuch learned the difference between who someone is to us and what's going on in their life. It also got a calendar feed, and Claude now gets told what to do after each call.
Roles are relationships now
"Our landlady" used to be filed as a fact, right next to the news about her new sink. Now it's a relationship to the household: to "me" or to "us". It's written in plain German words for both ends ("Vermieterin" / "Mieter:in") instead of a fixed type. People can have an optional gender, so the page reads "Unsere Vermieterin". Claude only sets a gender when I say it or use a pronoun, never from the name. When a gender changes, Claude is told which words need regendering. That's now only the neutral ones: setting 11 genders on my data listed 2 words to fix instead of 18.
Situations that nudge
Facts are split into two kinds. Gut zu wissen holds lasting ones (job, kids, allergies). Gerade los holds situations (a trip, a renovation). Each situation has a day to check in again. On that day it moves to the top of the page and into the daily push: "💬 Frag mal nach: Anna – sucht ein Auto". Without a date it's six weeks. When there's news, Claude suggests a new day and agrees it with me before filing.
The person page also draws a small network: the household on top, the person in the middle, their people below, with a label on every line.
Tool results say what's next
Every MCP tool result now carries
next: short instructions built from what the call actually did. One example: "this situation nudges on 8 December, a default; tell the user." Another: "two people match, ask which one." Before, that guidance lived in the tool descriptions, where Claude had to remember it before it knew what the call had done. Now it arrives right after the call.Also new
- Calendar feed: birthdays (with the age when the year is known), other dates, and your own promises that have a due date, as an ICS URL you can subscribe to. Google refreshes it only every few hours, sometimes once a day.
- Either of us can fix a shared item, not just whoever recorded it. Making an item private stays with the person who recorded it.
- Softer background: slow colour bubbles that stand still if you've turned motion off.
Changelog on GitHub. Tell me what you'd want from the nudges.
freundebuch: a personal CRM you talk to
You meet a friend and can't remember whether her new job has started, what her kid is called, or that you promised to send her a contact. I wanted something for that moment that doesn't ask me to fill in forms. So I built freundebuch, a personal CRM for one household, where Claude does all the typing.
How it works
After a dinner I ramble about it to the Claude app, by voice or text. Claude files it through freundebuch's built-in MCP endpoint: who was there, what's new, what I promised, gift ideas, birthdays, who is related to whom. The full transcript is kept. Before I see someone again I ask "I'm seeing Anna tomorrow, what's new?" and get a briefing: the last meetings, what's going on, open promises, upcoming dates.
MCP is the main interface. Every feature works there first. A REST API (with OpenAPI) and a German web app sit on the same domain layer. The web app is mostly for looking things up on my phone:
- The orbit: me in the middle, friends on rings by how long it's been. Anyone overdue for their check-in interval drifts outward.
- A page per person: what's going on, what's good to know, promises, dates, and the people around them.
- Erzählen: a chat with Claude inside the app, using the same tools, for when I'm not in the Claude app.
- Reminders once a day to a webhook such as ntfy: birthdays, promises, overdue friends.
Shared, with private parts
Two people in a household share one freundebuch. Anything said in confidence can be private to whoever recorded it, down to a single fact. Claude asks before filing when something sounds sensitive (health, money, relationship trouble). In the code, privacy is one function that every read goes through, so a private item can't leak through a count or a summary. Tests check that by seeding a household.
What's in it so far
I started on 23 October, and 44 PRs are merged as of today. Besides the core:
- Groups with other names ("Kollegen" is "Arbeit").
- Screenshots from social media: share a friend's Instagram or LinkedIn post and it lands on their page ("Urlaub in Lissabon · Instagram, 12. Oktober"). If Claude isn't sure who it is, or it looks sensitive, it waits for me to check.
- A calendar feed of birthdays and dates that Google Calendar can subscribe to.
- Roles and situations: "our landlady" is a relationship to us, not a fact. "Renovating the bathroom" is a situation that nudges me to ask about it later.
What it isn't
It isn't a contact book (no phone numbers or addresses) and it isn't multi-tenant: one instance per household, signed in through your own identity provider (authentik). It's one container with one SQLite file, and it's licensed AGPL-3.0.
The code is on GitHub, and the docs explain self-hosting. This feed is where I'll post what changes. If you try it, I'd like to hear how the rambling feels.