Docs › Reference › Configuration keys
Every key Continuity reads from ~/.continuity/config.toml, every CONTINUITY_* environment variable, and which one wins.
Audience: operator · Read time: ~6 min
- Environment variables beat
config.toml. Always. config.tomlis optional. Every setting has a working default, and a missing file is not an error.- Continuity only writes
config.tomlin one place:continuity embedder use, which rewrites[embedder].backendand leaves every other line untouched. - Hooks are not configured here. They live in
~/.claude/settings.json. There is no[hooks]section.
For why you would change any of this, see Configuration and Embedding backends.
| Key | Type | Default | Notes |
|---|---|---|---|
bind |
string | 127.0.0.1 |
Address continuity serve listens on. Loopback by default — Continuity has no authentication. |
port |
integer | 37777 |
Port continuity serve listens on. |
These do not affect the CLI. continuity search, restart, and the hooks
work out which server to talk to from CONTINUITY_URL / CONTINUITY_BIND /
CONTINUITY_PORT only. If you change [server].port in config.toml, you must
also set CONTINUITY_PORT in your environment or the CLI will keep knocking on
37777.
| Key | Type | Default | Notes |
|---|---|---|---|
path |
string | ~/.continuity/continuity.db |
Where the SQLite database lives. |
This only affects continuity serve. Commands that open the database
directly — tree, profile, dedup, doctor, embedder status,
embedder use, snapshot list, snapshot prune — use CONTINUITY_DB if set,
otherwise the default path. They never read [database].path. If you move the
database, set CONTINUITY_DB too or those commands will operate on a different
file than the server.
Governs the language model used for extraction and merge decisions. If no
provider can be constructed, serve prints a warning and runs with extraction
disabled — everything else, including remember, search, and retention, works
normally.
| Key | Type | Default | Accepted values |
|---|---|---|---|
provider |
string | claude-cli |
claude-cli, anthropic, ollama. Anything else fails at startup with unknown LLM provider. |
model |
string | haiku |
Model name for claude-cli and anthropic. Empty falls back to haiku for claude-cli, claude-haiku-4-5-20251001 for anthropic. |
ollama_url |
string | http://localhost:11434 |
Base URL for Ollama, used for both chat and embeddings. |
ollama_model |
string | llama3.2 |
Chat model, used only when provider = "ollama". |
embedding_model |
string | nomic-embed-text |
Ollama embedding model. Only relevant when the Ollama embedding backend is active. |
anthropic_key |
string | (empty) | API key. Required when provider = "anthropic". Prefer the ANTHROPIC_API_KEY environment variable. |
provider = "claude-cli" shells out to the claude binary. If that binary is
not on the server process's PATH, serve warns at startup that extraction will
fail — the usual cause is a service started by launchd or systemd, which does not
inherit your login PATH. Re-running continuity install-service bakes a usable
PATH into the service definition.
| Key | Type | Default | Notes |
|---|---|---|---|
auto |
boolean | false |
Automatic session-end extraction: the Stop/SessionEnd hooks asking an LLM to infer memories from the whole transcript. |
relational_auto |
boolean | true |
Automatic relational profiling at session end: analyzing how you work and merging the result into the single profile node. Independent of auto. |
auto is off by default on purpose. When you turn it on, serve prints a
warning at startup saying so. Explicit remember calls, the signal-phrase path,
and continuity extract --force are unaffected either way. Booleans are read
loosely — true, 1, and yes all mean on; anything else means off.
relational_auto is on by default: unlike transcript extraction it never
creates arbitrary memories — it only merges into the system-owned
mem://user/profile/communication node, and its provenance is unambiguous
(analysis of the session, not facts transiting it). Turning it off freezes the
relational profile — including relational jobs already sitting in the durable
queue, which are dropped rather than replayed — and serve prints a warning at
startup saying so.
| Key | Type | Default | Accepted values |
|---|---|---|---|
backend |
string | auto |
auto, model2vec, ollama, hashtf (tfidf is accepted as a spelling of hashtf), none. |
auto means identity-aware selection — see
Embedder selection order below. An unrecognized
value is not fatal: serve warns and falls back to auto.
none disables embedding entirely, which disables search and the
dedup-against-retracted gate. It exists for testing.
Hand-editing this key does not migrate anything. It changes which backend the
next serve selects; your stored vectors stay in the old space, and search fails
closed on the mismatch until you repair it. continuity embedder use <backend>
is the command that changes the key and re-embeds.
The prompt gate (ADR-001 §4): on every user prompt, the submit hook asks the
server whether memory holds something similar enough to surface. In shadow
mode (the default) it only logs a calibration event per prompt — nothing is
ever injected. on injects hits at or above tau as one-line pointers
(L0 + mem:// URI), deduped against what the session has already seen.
continuity doctor renders the collected calibration distribution.
| Key | Type | Default | Accepted values |
|---|---|---|---|
mode |
string | shadow |
off, shadow, on. Anything else is read as shadow — a typo can disable injection, never enable it. |
tau |
number | 0.50 |
A number in (0, 1]. Out-of-range or unparsable values keep the default. |
The gate call fails closed by contract: if the server is stopped, slow, locked,
or answers garbage, the hook stays silent and the prompt passes through
unmodified. Turning mode to on prints a startup notice, like
[extraction].auto does.
| Variable | Overrides | Default when unset | Accepted values |
|---|---|---|---|
CONTINUITY_DB |
[database].path (for serve); the default path (for direct-DB commands) |
~/.continuity/continuity.db |
Any file path. |
CONTINUITY_BIND |
[server].bind |
127.0.0.1 |
Any address. Read by both serve and the CLI/hooks. |
CONTINUITY_PORT |
[server].port |
37777 |
Integer 0–65535. serve refuses to start on anything else. |
CONTINUITY_URL |
— | (built from bind + port) | Full base URL, e.g. http://127.0.0.1:37777. Client-side only — the CLI, hooks, and MCP server use it to find the server. It does not change what serve binds to. |
CONTINUITY_EMBEDDER |
[embedder].backend |
(no override) | auto, model2vec, ollama, tfidf, hashtf, none, or empty. Unrecognized values warn and fall back to auto. |
CONTINUITY_EXTRACTION_AUTO |
[extraction].auto |
false |
Any Go boolean: true, false, 1, 0, t, f. serve refuses to start on anything else. |
CONTINUITY_RELATIONAL_AUTO |
[extraction].relational_auto |
true |
Any Go boolean. serve refuses to start on anything else. false freezes the relational profile. |
CONTINUITY_OBSERVATION_RETENTION_DAYS |
— | 14 days |
A positive integer number of days, or off / false to disable pruning. See below. |
ANTHROPIC_API_KEY |
[llm].provider and [llm].anthropic_key |
(unset) | An API key. Setting it forces provider = "anthropic", overriding whatever config.toml says. |
CONTINUITY_GC |
— | off |
off, shadow, on. Memory garbage collection. Anything unrecognized is treated as off. Advanced. |
CONTINUITY_GATE |
[gate].mode |
shadow |
off, shadow, on. serve refuses to start on anything else — an explicit knob with a typo must surface, not silently pick a mode. |
CONTINUITY_GATE_TAU |
[gate].tau |
0.50 |
A number in (0, 1]. serve refuses to start on anything else. |
CONTINUITY_NO_MIGRATION_SNAPSHOT |
— | (unset) | Any non-empty value skips the safety snapshot before a risky schema migration. Advanced — this removes your rollback point. |
PATH and HOME are read by continuity install-service to build the service
definition. They are not Continuity settings.
CONTINUITY_OBSERVATION_RETENTION_DAYS controls how long raw tool-use
observations are kept before the daily sweep reclaims them. Memories, vectors,
and the relational profile are never affected.
| Value | Effect |
|---|---|
| unset | 14 days — the default. |
| a positive integer | That many days. |
greater than 3650 |
Clamped to 3650 days, with a log line. |
0, or any negative number |
Retention disabled; nothing is pruned. |
off or false |
Retention disabled; nothing is pruned. |
| anything unparseable | Retention disabled, with a log line. |
Unparseable input fails closed rather than falling back to the default: someone
typing of while reaching for off is trying to stop deletion, and the boot
sweep runs immediately, so a warning would arrive too late to intervene.
Note that a separate 30-day rule always applies: a session stuck in active
state — the client crashed, so Stop never fired — stops being treated as live
after 30 days, and its observations become reclaimable. This is not configurable.
Deleting rows does not shrink the database file. Run continuity prune
for that. See Keeping it healthy.
CONTINUITY_* environment variable (wins)
↓
~/.continuity/config.toml
↓
built-in default
ANTHROPIC_API_KEY is applied before the CONTINUITY_* overrides, and it
rewrites both the provider and the key. There is no CONTINUITY_* variable for
the LLM provider, so setting ANTHROPIC_API_KEY is the only environment-level
way to change it.
This is the one place with more than two tiers. serve picks its embedding
backend in this order, and stops at the first that applies:
CONTINUITY_EMBEDDER, if it names a concrete backend (notautoor empty).[embedder].backendinconfig.toml, if it names a concrete backend.- The corpus's declared identity — whatever backend your existing memories were embedded with. This is what keeps an existing install on the backend it already has instead of silently moving it.
- model2vec, for a fresh corpus with nothing declared yet. This is the default for new installs.
If step 4 fails because the model files cannot be downloaded (offline first run),
that session falls back to the lexical hashtf backend and says so. Run
continuity embedder use model2vec once you have a network to upgrade.
Steps 1 and 2 are deliberate overrides — they win even when they disagree with
what your memories were embedded with. That disagreement locks search, which
fails closed with an error rather than comparing incompatible vectors. Repair it
with continuity embedder use <backend> or
continuity doctor --repair-vectors --apply.
If step 3 fails to construct — Ollama is declared but not running, say — no embedder is used at all. Continuity will not silently substitute a different one.
continuity doctor and continuity embedder status resolve the embedder by
exactly these rules, so they report what serve would actually do. continuity dedup does not — it probes Ollama directly and otherwise uses the lexical
fallback, ignoring both the environment variable and the config key.
The identities you will see in doctor and embedder status output look like:
| Backend | Identity string |
|---|---|
| model2vec | model2vec:potion-retrieval-32M:512 |
| Ollama | ollama:nomic-embed-text:768 |
| lexical fallback | hashtf:2048 |
The CLI, the hooks, and the MCP server resolve the server URL like this:
CONTINUITY_URL (wins outright)
↓
http://${CONTINUITY_BIND:-127.0.0.1}:${CONTINUITY_PORT:-37777}
config.toml plays no part in that. serve resolves its own listen address from
config.toml overlaid with CONTINUITY_BIND / CONTINUITY_PORT. Keeping the
two in agreement is on you.
The parser is deliberately small. It reads exactly the subset of TOML Continuity writes:
# commentlines and blank lines are ignored.[section]headers, one level deep only. Nested tables are not supported.key = valuelines with string, boolean, or integer scalars. One layer of surrounding double quotes is stripped from strings. Arrays and multi-line strings are not supported.- Unknown sections and unknown keys are silently ignored. A
config.tomlleft over from an older version — one carrying a[hooks]section, or[llm].merge_model— still loads without error. Those keys simply do nothing. - A malformed line is skipped, not treated as an error. A non-integer
portis ignored and the default is kept.
Permissions: the file is written 0600 inside a 0700 directory when
continuity embedder use creates it.
Every key below is shown at its default value, so this file is equivalent to
having no config.toml at all.
[server]
bind = "127.0.0.1"
port = 37777
[database]
path = ""
[llm]
provider = "claude-cli"
model = "haiku"
ollama_url = "http://localhost:11434"
ollama_model = "llama3.2"
embedding_model = "nomic-embed-text"
anthropic_key = ""
[extraction]
auto = false
relational_auto = true
[embedder]
backend = "auto"Not here. Claude Code reads its hooks from ~/.claude/settings.json, and that is
the only place their commands and timeouts are set:
{
"hooks": {
"SessionStart": [{"hooks":[{"type":"command","command":"continuity hook start", "timeout": 10}]}],
"UserPromptSubmit": [{"hooks":[{"type":"command","command":"continuity hook submit", "timeout": 10}]}],
"PostToolUse": [{"hooks":[{"type":"command","command":"continuity hook tool", "timeout": 10}]}],
"Stop": [{"hooks":[{"type":"command","command":"continuity hook stop", "timeout": 120}]}],
"SessionEnd": [{"hooks":[{"type":"command","command":"continuity hook end", "timeout": 10}]}]
}
}Installed as a Claude Code plugin, the equivalent definitions ship in the
plugin's own hooks.json and you do not edit settings.json yourself.
See also: CLI reference · Files and paths · Configuration guide · Embedding backends · Keeping it healthy