Skip to content

kumulativ Docs smartdiary

smartdiary A private diary in one book, with activities you tag, companions that answer from your own words, and mentors that count.

smartdiary

A private diary with a local model beside it. Write the day down and tag what you did. Companions answer from what you have actually written, and mentors hold you to the goals you set out loud — with the countable part counted in code, never estimated by a model. Everything, the model included, runs on your machine. Nothing you write ever leaves it: there is no account, no sync, no sharing, and no cloud provider to switch on.

Built with Wails v2 (Go) · Svelte 5 + TypeScript · Tailwind v4 · GSAP (motion) · D3 (insights), with a local Qwen3.5 model served by the runtime every kumulativ app shares (kumulativ-core). It shares its stack and its design language with smartreader and smartwriter.

smartdiary used to be called kumulativ and used to have a networked half — an end-to-end-encrypted sharing service, exchanges between peers, multi-device sync. All of that is gone, and the name now belongs to the family of apps. A profile written under the old name is picked up on first launch (see Upgrading from kumulativ). The likes deck, the questionnaire, the finance ledger and the network graph that earlier versions carried are gone too; a document that still holds them opens fine, and those parts are simply no longer read.

Two more things went the same way. There used to be five books — a diary plus fitness, food, stretching and meditation logs — and a memory ladder that compressed each of them into day, week, month and year summaries. Both are gone. A day is a day, and whether it had a run in it is a property of the day rather than a separate diary; what an entry was about is now carried by the activities tagged on it. An existing profile is migrated on first launch: every entry becomes an entry, and the structured fitness, practice and food logs each become an activity tag carrying the minutes they recorded.

What it does

  • Onboarding — on first run, one screen asks your name, date of birth, height and weight. Only the name is required; everything else is skippable and editable later in Profile and Settings. Age is derived from the birth date from then on, so the profile doesn’t quietly go stale.
  • Talk — the app opens here, and it is both the chat and the way most writing happens. Ask something and it is answered from your own diary; or just write, and the message goes into today’s entry by itself, in your own words, tagged with whatever activity it named — a gym session, a sit, an hour of cooking. It only ever tags an activity you have already defined: nothing is invented. The composer has three buttons — Auto, Write it down, Just talk — for when you would rather decide. Type @ and pick a person to ask a question that is only about them. Whatever was written appears as a chip under the message that wrote it, so nothing is ever recorded invisibly.
  • Journal — one book. A single timeline rail with date markers, a serif editor that fills the page, a five-dot mood scale, tags, and one way to write an entry; what it was about comes from the activities on it rather than from which log it was filed in. Photos go under the entry — picked, pasted, or dropped anywhere on the window. An entry is a day by default, but it can cover a period — a trip, a hospital week, a summer — and it can be marked a memory: written now, about a time before the diary existed. Ask for a reflection under any entry.
  • Activities — the things you do and want counted, defined once: a name, a description, a photo if you like, a usual length, and one of eleven categories — food, social, spiritual, cardio, strength, stretching, study, work, art, clean, other — which gives it its colour everywhere. Added to entries with the minutes it took that day. The list starts empty: an activity you did not define is one the app will never count for you.
  • People — the people in your life, each with a name, a date of birth, a relation, a line about them and a photo. Tag them in entries and in the chat; a person’s card gathers every entry they are tagged in, and the ones that merely name them, and the app can write a portrait of the relationship from it — marked when the diary has moved on since.
  • Biography — your life as the diary tells it, in chapters written by the model, cut by density rather than by the calendar. Memories dated before the diary began count — that is what they are for. Each chapter stores a hash of the entries it was written from and is rewritten only when those change. Your mentors comment on any chapter, and on the whole arc.
  • Mentors — companions with a job. A fitness coach that tracks whether the three sessions a week actually happened; a mobility keeper that adds up the stretching minutes; a burnout watch that says so before the crash. Each holds the goals you set in your own words and writes a check-in on its own cadence with a coarse verdict and the evidence behind it. The countable part of a goal is counted in Go and handed to the model as fact — a goal naming one of your activities counts the days it was tagged, or the minutes if the unit is minutes; anything else counts the entries whose text carries the goal’s own words.
  • Companions — chat with AI characters (Sage, Ember, Aria, Atlas, Nova built-in; create your own). Replies stream token by token. Mentors are in the same roster, so a question about training can reach the coach that tracks it without being invited.
  • Patterns — your most-tagged activities over four weeks as days and minutes, time by activity category, mood over 30 days, a writing heatmap, most-written-about people, and an AI weekly note.
  • Profile — self-reported health stats companions quietly use (toggle in Settings); the date of birth is what puts an age on each chapter of the biography. Light & dark, system-following by default.

What the model is told

The model on this machine cannot read years of diary — it does not fit in the context window, this year or any other. So it never does.

There is no summary ladder and no living profile. Earlier versions kept both; they were a lot of machinery, and a lot of generated text standing between a companion and the thing you actually wrote. What a companion gets now is assembled in one function, so “what does it know about me” has a single readable answer:

  1. The flat facts — your name, age, the health profile, if sharing is on.
  2. The last three weeks, one short line per entry: the date, the title, how you said it went, who was there, what you logged doing, and the opening of what you wrote.
  3. The entries the question reaches for, in full — found by term overlap against the title, the text, the tags, the activities and the people, with a mild preference for recency.
  4. Anyone the question named, so “how is it going with Marcus” answers about the right Marcus.

The whole thing is capped at about five thousand characters, which fits beside the conversation and the reply.

Retrieval is lexical rather than embedded: no second model, no index, no extra download, and over a diary — where the query is in the writer’s own vocabulary — it finds what the search box would have found.

None of it is a paraphrase. Every line a companion reads is something you typed, which is also why capture refuses a model’s rewrite of your sentence and files your own words instead.

Settings has a box where you type a question and see the exact text a companion would be given before answering it.

The lock

Everything the app keeps is encrypted on disk. On first run you choose a password; it is stretched with Argon2id and used to unwrap a random data key that seals data.enc. Changing the password rewraps 48 bytes rather than re-encrypting a journal that may be years long.

While the app is locked it holds nothing — not a hidden view, not a cached document. The store is empty until a password (or the OS keychain entry, which holds the data key and never the password) unlocks it.

There is no reset. Nothing about the password leaves the machine, so nobody can recover it.

The local model

The model runs in the runtime every kumulativ app shares: kumulativ-core. One store of weights and engines under <UserConfigDir>/kumulativ, one llama-server in router mode started by whichever app first needs it, at most one model resident across all the apps, asleep after a quiet minute. smartdiary runs Qwen3.5 — the 9B where it fits, the 4B where it would not — the same family smartreader and smartwriter run, so a machine with more than one of them downloads the weights once.

On first run the app sets itself up without intervention: it detects the machine, downloads the pinned llama.cpp release and the weights (resumable) into the shared store — or finds them already there — and from then on the model loads on the first question and sleeps again when nothing is asked. Nothing is warmed at launch: several gigabytes are not loaded on the off-chance that a message is coming.

Where things live

<UserConfigDir>/smartdiary/
  data.enc           everything you write, sealed
  profile.json       the (non-secret) parameters needed to unwrap it
  images/            photos on entries, activities and people

<UserConfigDir>/kumulativ/    shared with every kumulativ app — see kumulativ-core
  models/            the Qwen weights, one copy for every app
  engines/           the llama.cpp build for this machine
  run/               the one running server: registry, lock, presets

Upgrading from kumulativ

The first launch after the rename moves data.enc, profile.json, any pre-lock data.json and the images/ folder from <UserConfigDir>/kumulativ into <UserConfigDir>/smartdiary, once, and reads a device remembered in the keychain under the old name. The old directory stays, because it is also the shared model store now. Two things in it are no longer used and can be deleted by hand: keys.enc (the cloud API keys and the vault session the app no longer has) and any Gemma 3 weights under models/, which the catalog no longer knows.

Env overrides

Variable Effect
SMARTDIARY_CONFIG_DIR Override the profile directory entirely (portable installs, tests)
SMARTDIARY_GGUF Path to a specific .gguf; skips model download
KUMULATIV_HOME Move the shared model store
KUMULATIV_BIN_DIR Look for llama-server here first
KUMULATIV_IDLE_UNLOAD_MIN Minutes of quiet before the model is put to sleep (default 1; 0 = never)
KUMULATIV_LLAMA_ASSET / KUMULATIV_LLAMA_RELEASE Pick a different llama.cpp asset/release
KUMULATIV_LLAMA_EXTRA_ARGS Extra flags for the llama-server command line
KUMULATIV_FORCE_CPU Never use the CUDA build
KUMULATIV_NO_ENGINE_FETCH Disallow engine auto-download (staged binary required)
KUMULATIV_DEBUG Forward the server’s output to stderr