Your Twin
Your Twin is the part of Novaterra that belongs entirely to you. It owns your memory, your profile,
your indexed files, and whatever you connect — mail, browser history, a phone number on Telegram —
and it turns all of that into a small, growing model of who you are, which the rest of the product
(Muse, the omnibar, the desktop’s Now widget, Studio agents) reads from constantly and writes to
almost never without telling you. Route: /twin.
Concretely, your Twin is five things:
- Memory — a searchable, typed store of facts, episodes, preferences, relationships, documents and insights. See The memory model.
- Profile — a compact, structured summary: facts, goals, routines, preferences, tone, timezone. See The profile.
- The learning loop — the machinery that turns raw text (a conversation, an email, a file, a day of browsing) into memories and profile updates, on a schedule, without you asking. See The learning loop.
- Connections — the sources your Twin is allowed to read: files, Chrome/Edge/Brave history, Telegram, Gmail. Each is opt-in, each can be disconnected, and each is documented on its own page: Files, Chrome history, Telegram, Gmail.
- Calendar, to-dos, and the Hush — a committed-intention state machine, a unified agenda, and the restraint discipline that gates every proactive nudge on quiet hours, a daily ceiling, cited evidence, and dedup. See Calendar, to-dos, and the Hush.
GET /api/twin/status
The single place that tells you (and the Settings UI) exactly what your Twin can currently see — what’s configured on the server, what’s connected for you personally, and why not if not:
TwinStatus = { llm: { configured: boolean }, counts: { memories, files, activity, connections }, providers: Array<{ provider: 'files' | 'browser' | 'telegram' | 'gmail', configured: boolean, // credentials/paths present on this server connected: boolean, // you personally have connected it connectionId: string | null, label: string, meta: Record<string, unknown>, lastSyncAt: string | null, sync: { status: 'idle' | 'running' | 'done' | 'error', startedAt, finishedAt, error, detail }, hint: string | null, // e.g. "Set TELEGRAM_BOT_TOKEN in .env" }>,}Nothing here is guesswork: configured for files checks whether a root folder actually exists on
disk; for browser it checks whether a Chrome/Edge/Brave History file is findable; for telegram
and gmail it checks whether the relevant .env credentials are present. hint is always a
plain-language next step, never a raw error.
The Twin’s own screen
/twin (apps/web/src/twin/index.tsx) is built around the Constellation — a searchable map of
every memory, filterable by kind, with a live drawer for reading (and deleting) any single one. Next
to it: the Profile panel (facts, goals, routines, preferences, tone), the Sources panel (this
page’s four connections, with connect/sync/disconnect), the Activity stream (a running,
human-readable log of what the Twin has actually done — “Indexed 12 files”, “Read 3 new email
threads”, “Reflected on 6 new memories and raised 1 signal”), and a Teach box where you can just
tell it something directly.
POST /api/twin/learn { text, source } → Memory[]This runs the exact same extraction the learning loop runs on ingested text — see The learning loop — just triggered by you, immediately, instead of on a schedule.
Reflecting on demand
POST /api/twin/reflect → { ran, signals, widgets, thought }Normally reflection runs automatically every ten minutes and only when at least three new memories
have arrived. The Reflect now button on /twin calls the same function with force: true, so
you can ask “what have you noticed?” at any moment instead of waiting for the tick.