Deeshan Sharma

Life OS: AI-Native Personal Ops

A single-user universal inbox running on one machine at home. Anything I send it — a voice note, a photo of a receipt, a forwarded bank email — is transcribed, classified, extracted into typed records and filed. Local models, no cloud. 66 spec files and 561 test cases against 149 source files.

NestJS
Drizzle ORM
PostgreSQL
pgvector
BullMQ
Redis
Ollama
Docker

Overview

Everything goes to one place. I send a voice note, a photo, a PDF or a forwarded email to a Telegram bot, and a pipeline on my own machine transcribes it, works out what it is, pulls typed records out of it, and files them into the right domain — tasks, expenses, notes, journal, health, documents. The problem it actually solves is unattended capture: bank alerts and card statements land in one spend ledger without me touching a spreadsheet.

The pipeline

A NestJS modular monolith over five BullMQ stages on Redis — transcribe, classify, extract, route, embed — plus repeatable jobs for mail, calendar and repository syncs, briefings and backups. Storage is Postgres with pgvector: twenty-six tables, seven migrations, and a set of hand-written SQL views applied idempotently after migration. Nothing listens on a public port; the bot long-polls and the other ingress lanes sit behind a private network and a shared secret.

One gate for every model call

Exactly one service is allowed to talk to a model, and every call writes a ledger row even when it costs nothing — because the moment a second call site exists, you have lost the ability to answer what ran, how often, and at what price. It sets the SDK's own retries to zero so the queue owns retry policy rather than two systems fighting over it, and on a schema violation it re-sends once with the validation errors appended. Both attempts hit the ledger.

Schemas written around a grammar compiler

The extraction schema is both the constrained-decoding grammar and the validation boundary, which means it has to survive a schema-to-grammar conversion that does not support everything the validator does. Two constructs break it and are avoided deliberately; a confidence value is rescaled in a preprocessing step because the grammar cannot enforce a numeric range. Those are the kind of constraints you only find by bisecting a live failure, and they are commented as such.

Idempotency by construction

The job id is the item id at every hand-off, so a duplicate enqueue is a no-op rather than a duplicate record. Processors check their own stage marker and return early on a stalled re-entry. A failure is only recorded as final on the last attempt or an explicitly unrecoverable error. Orphans are re-enqueued at boot, and the mail poller guards twice — once on a watermark, once per message id — because a watermark alone loses anything that arrives out of order.

The hardest part: money

Three sources describe the same rupee and none of them agree: the instant alert, the bank statement and the card statement. The deduplication puts card identity in the match key, because the same amount at the same merchant on a card and by direct transfer are two different events. It drops the merchant test for statement rows, because an issuer's own narration does not match its own alert. It carries a set of already-matched ids so two identical purchases on the same day pair one-to-one instead of collapsing. And a SQL view chains statements by period so a whole missing billing cycle shows up as a gap rather than as a quiet under-count. Every one of those rules exists because of a specific transaction that went wrong.

Honest scope

Seventy-eight commits over six weeks, effectively single-author, still being built. The assistant can read and propose but cannot write — its write tools only create proposals that I approve from the bot — and there is no delete or send tool at all. Cloud escalation is designed and never wired, so the budget and redaction paths around it have not run against a hosted model in anger. There is no CI; the tests run locally. It is a personal system, and I would rather describe it as one than dress it up as a product.

Other Projects