Configuration
Configuration should be the most boring part of a product. If you have to study configuration before the software runs, that's the software's failure, not yours. So Previously's attitude toward configuration is: defaults are responsible for being correct, the doctor is responsible for self-healing, and your hands are the exception.
Two layers, deliberately separate
Previously splits configuration into two layers, and the dividing line isn't technical — it's ownership.
The machine layer answers "how does the product run on this machine": port, hostname, kernel location, whether the brain is a subscription bridge or bring-your-own-key. These facts belong to this machine — on a new computer, they have no reason to follow you. They live in ~/.previously/config.json (mode 0600 on POSIX systems — readable by you alone). The machine layer is a concept of the local (npm) form; deployed to Vercel, the same facts are carried by environment variables — see Deploy on Vercel.
The memory layer answers "what do you, the person, prefer": which model, whether thinking is on, what reasoning effort, how long a time slice may run. These preferences belong to you — not to this machine, and certainly not to our database. So they aren't written into the local config; they live inside the memory repo itself, in memory/user/config.json and memory/user/profile.md — your preferences are part of your memory, and wherever the memory goes, they go. This layer is identical across both forms: in a Vercel deployment they are the same files in the repo. This also explains a detail you may have noticed: model choice and thinking effort persist server-side, not in the browser's localStorage. Switch browsers, switch devices — your preferences are still there.
profile.md is the most human file of the bunch: name, pronouns, timezone, locale, plus a stretch of free text. It's read live on every request — the name that follows "Previously on" in the chat title comes from here.
The config doctor
Previously ships with a config doctor, and it runs on every previously init and every previously start. What it does is plain: audit the config for illegal values (storage, port, backend, brain shape) and repair them; audit and repair the memory repo itself; write a config.json.bak backup before touching anything; and stay idempotent — running it a hundred times produces the same result as running it once.
It has one restraint worth stating out loud: if you picked a backend, it will derive the matching bridge brain for you; but if you deliberately chose to bring your own key (BYOK), it will never "helpfully" resurrect a bridge over that choice. The doctor repairs damage, not your decisions.
Which means hand-editing a config file barely exists on the normal path. The file is right there, its format is listed at the end of this page — but opening it should be the exception, not the routine.
The honest part
Two things we choose to say plainly. First, apiKeys is currently stored in plaintext — that's an MVP-stage trade-off, and the 0600 file permission is the current line of defense, so treat the file accordingly. Second, a batch of environment-variable knobs exists (relocating the home directory, skipping the automatic browser launch, bridge timeouts, and the like). They're listed at the end, but you'll likely never need them — they exist for unusual environments, not for you.
In one line: Previously wants there to be exactly one reason you ever open a config file — curiosity, not distress.
Reference: the keys
Machine layer, ~/.previously/config.json:
| Key | Default | Effect |
|---|---|---|
storage | "local" | Storage backend. |
memoryRoot | set at init | Location of the memory repo. |
port | 3210 | Port the kernel listens on. |
hostname | 127.0.0.1 | Listen address — local-only by default. |
executionBackend | — | Default bridge agent when a call doesn't specify one. |
brain | derived from backend | The brain: { "type": "bridge", "agent": "claude" | "codex" | "kimi" } for a subscription bridge, or { "type": "api-key", "env": "...", "model": "..." } for bring-your-own-key. |
apiKeys | — | Manually entered keys, stored in plaintext (MVP status); injected into the kernel's environment at start. |
agents | — | Per-CLI model and effort tuning; kimi supports model only. |
byok | — | Owned by the kernel's Web UI settings page; the client preserves it untouched. |
kernelDir | — | Explicit override for the kernel directory; not needed on the normal path. |
Memory layer (inside the memory repo):
| Location | Effect |
|---|---|
memory/user/config.json → maxSliceMinutes | Maximum length of one time slice; default 30 minutes. |
memory/user/config.json → maxTurnsPerSlice | Maximum turns per slice; default 50 — purely a safety valve. |
memory/user/config.json → model choice, thinking on/off and effort | Persisted server-side, travels with the memory. |
memory/user/profile.md | Frontmatter: name, pronouns, timezone, locale, address_as, plus free text; read live on every request. |
Environment variables (rarely needed):
| Variable | Effect |
|---|---|
PREVIOUSLY_HOME | Override the client home (default ~/.previously). |
PREVIOUSLY_NO_OPEN | Don't auto-open the browser after start. |
PREVIOUSLY_HEALTH_TIMEOUT_MS | Timeout for waiting on the kernel's health check. |
PREVIOUSLY_BRIDGE_<AGENT>_CMD / PREVIOUSLY_BRIDGE_<AGENT>_TIMEOUT_MS | Override the CLI command and call timeout for a bridge agent. |
PREVIOUSLY_GIT_AUTHOR_NAME / PREVIOUSLY_GIT_AUTHOR_EMAIL | Author identity for git commits in the memory repo. |
PREVIOUSLY_READER_SCOPE | Memory read scope. |
Related links
- Local First — why configuration and memory both live on your machine
- Your Memory Is a Folder — where the memory-layer config files sit
- Two Engines — the difference between the bridge and BYOK brains
- The Kernel Supply Chain — the version discipline behind
kernelDir - Deploy on Vercel — where the machine-layer configuration goes in a cloud deployment