Approach
- Collect foreground app activity and window titles through native macOS APIs.
- Bootstrap up to 90 days of history from an explicitly chosen Chrome profile.
- Take metadata-only Local History and Git-path signals from editors — never file contents.
- Write it all to a local SQLite store with 30-day detailed-activity retention.
- Assemble semantic work threads across app, browser, document, and editor evidence.
- Pack context deterministically, dropping full URLs, absolute paths, and credential-like fields.
- Send only that token-budgeted packet to the provider the user brought a key for.
Architecture
- Desktop app
- A Tauri 2 shell with a Rust core for collection and packing, and a React and TypeScript surface for the dashboard, activity inspection, and profile corrections.
- Store
- Local SQLite, and nothing else. Detailed activity is kept 30 days; imported history past that window is cleaned up automatically.
- Companion
- An optional Chrome MV3 extension adds active-tab timing. It is a post-MVP experiment, not a dependency — the desktop app works without it.
- Providers
- OpenAI, Anthropic, or Amazon Bedrock on bring-your-own-key credentials, held in the macOS Keychain. Exclusion lists drop named apps and domains locally, before they can reach a profile at all.
The decision I would defend
Sanitization is deterministic and happens in the Rust core before any model call — stripping full URLs, absolute paths, credential-like fields, and unrelated raw activity, then enforcing a token budget. Handing the model everything and instructing it to be careful would have been far less work. But a privacy guarantee that depends on a model behaving is not a guarantee. Putting it in the packer makes it a property of the system.
Why it matters
Local-first is a constraint rather than a marketing line: it decides what you can collect, where you can compute, and how much you are ever allowed to send. It also forces honesty about inference — knov presents work threads as inferences rather than confirmed intent and lets you correct them, because a system that quietly guesses at your day and sounds certain is worse than one that asks.