LifeOS
Personal commitment system: Telegram-first capture, AI structuring, relationship memory, weekly review. PWA with push, everything modelled on a single commitment table.

Key engineering call
One commitment data model for everything — tasks, reminders, promises, events, habits, goals, areas and projects are just type flags on the same table, hierarchy via parent self-reference. One recurrence engine, one status machine, one set of safety rules. Cost: type-flag polymorphism everywhere, queries occasionally get clunky. Pays off because no schema migration is ever needed when a new commitment type shows up.
Not a todo app, not a CRM — a personal operating system for commitments: to yourself (goals, routines), to others (promises, follow-ups) and to reality (events, tasks). Capture is primarily over Telegram in natural language; Claude structures input and asks for clarification instead of guessing. Recurrence is stored as RRULE; reminders run through BullMQ + web push. People are first-class objects with an interaction timeline and configurable follow-up cadence.
Vision in one sentence
Everything in life is a commitment — to yourself, to others, to reality. LifeOS captures, structures and surfaces them at the right time. Not a todo app, not a CRM — a personal operating system.
Capture channels
Phone-first, always. Telegram is the front door — a fast capture line you use on the move to park a thought without opening the app.
| Channel | Role |
|---|---|
| Telegram | Primary capture channel. Natural language in, inline buttons for disambiguation out. Replying to old bot messages revives that thread. |
| PWA Quick-Add | Secondary capture slot when already in the app. Same AI parsing pipeline as Telegram. |
| Web Push (PWA) | Passive reminders, scheduled notifications, gentle nudges — works on iOS thanks to the service worker. |
| Telegram-Reminder | Actionable notifications with inline buttons: done, snooze, reschedule. |
Sample captures
What the AI turns messy input into:
- 'call mom tomorrow'
- 'remind me in 2 weeks to ask Jonas about the move'
- 'Anna birthday April 12, need gift and dinner'
- 'every other Tuesday yoga'
Commitment — the core object
Everything that requires action is a commitment. A single table with a type flag and a parent self-reference — areas, projects, tasks and habits are just different views of the same data type.
| Field | Description |
|---|---|
| type | task, reminder, promise, event, habit, goal, area, project — one data type. |
| dueDate / scheduledDate | Hard deadline vs. planned work date. Both on the calendar, treated differently. |
| recurrence (RRULE) | iCal standard. Claude parses natural language into RRULE: 'every 2nd Tuesday' → a real recurrence rule object. |
| parent | Area → Goal → Project → Task → Subtask. Arbitrary depth, one data model. |
| linkedPeople | Who is involved / whom it was promised to. Direct join to the person. |
| linkedGoal | Which long-term goal this commitment serves. |
| commitmentStrength | Hard promise / soft intention / idea. Affects sorting and UI weight. |
| status + snoozeUntil | open / in_progress / done / snoozed / deferred / cancelled. Snoozed items resurface automatically. |
Architecture
Classic monorepo: React PWA, Express API, Postgres with Prisma. Alongside it: Telegram webhook, BullMQ on Redis and the Anthropic API.
┌──────────────┐ ┌──────────────┐ ┌──────────────────┐
│ React PWA │────▶│ Express API │────▶│ PostgreSQL │
│ (Tailwind) │◀────│ (Node.js) │ │ (Prisma ORM) │
└──────────────┘ └──────┬───────┘ └──────────────────┘
│
┌───────┼────────┐
│ │ │
┌─────▼──┐ ┌─▼─────┐ ┌▼──────────┐
│Telegram│ │BullMQ │ │Claude API │
│Webhook │ │(Redis)│ │(Anthropic)│
└────────┘ └───────┘ └───────────┘
│
┌─────▼──────┐
│ Web Push │
│ Service │
└────────────┘Dashboard — what matters right now?
The home screen answers exactly one question. Seven sections, all structured the same way, all derived from the single commitment table.
Today
Scheduled commitments, due items, events, routines.
Overdue
Missed deadlines, unresolved items.
Upcoming
Preview of the next few days.
Open loops
Promises to / from others, outstanding items.
People
Who needs attention, follow-ups due.
Goals
Progress, streaks, drift warnings.
Inbox count
Unprocessed captures needing triage.
Weekly review — guided flow
Appears in the dashboard on Monday, triggered by a scheduled push. Six steps; also manually accessible any time.
- 1
Clear the inbox — process all unstructured items.
- 2
Review commitments — overdue, stale, reschedulable.
- 3
Someday / maybe — deferred items worth reconsidering.
- 4
Relationships — who needs attention, outstanding promises.
- 5
Goals — progress check, drift detection, AI-suggested next actions.
- 6
Plan the week ahead — schedule key commitments.
Key engineering decisions
One data model for everything
Tasks, reminders, promises, events, habits, goals, areas, projects — all the same Commitment table with a type flag. Parent relations build the hierarchy. One schema, one recurrence engine, one status machine.
Capture-first, structure-second
Inputs are allowed to be messy. 'Anna birthday April 12, need gift and dinner' lands in the inbox; the AI extracts a person, a date and two follow-up commitments. What stays unclear gets asked — not guessed.
AI assists, never decides
On ambiguity the system asks via inline-button multi-choice or free text. Important data is never silently changed. Haiku handles fast micro-operations, Sonnet does the heavy parsing.
RRULE instead of a custom recurrence format
iCal RRULE covers everything — daily, weekly, biweekly, 'every 2nd Tuesday', custom cron. Widely supported, compatible, no custom recurrence engine to maintain. On completion the next instance is auto-created; completed instances are archived, not deleted.
Relationships as first-class objects
A person has context, an interaction timeline (manual + auto from commitment completion), a follow-up cadence, open loops. The system actively surfaces who needs attention — not a CRM data grave.
Ephemeral AI conversations
Conversation is ephemeral per interaction session; context ends after successful extraction. Only replying to old bot messages revives the original thread. History is kept for 24h then pruned — only the extracted commitments persist.
SSE instead of WebSockets
Live dashboard updates run over Server-Sent Events. Simpler than WebSocket, sufficient for 'unidirectional + reconnect', saves complexity on both server and client.
Notification batching with hard caps
Quiet hours, per-category mute, frequency caps, smart batching of low-priority items into digests. Sensible defaults, fully configurable — nobody gets spammed.
Deployment
Self-hosted on a VPS, Docker Compose for Postgres and Redis. The Telegram bot runs in webhook mode on the same server. VAPID keys are server-generated, JWT has no expiry for persistent sessions, simple username/password auth via bcrypt. Online-only — no offline sync, no sync-headache.