Configuration Profiles

July 30, 2026 ยท View on GitHub

A profile is a named bundle of configuration values applied to config.yaml in one command. There are eight built-ins, each setting the same 74 keys, so switching profiles moves every tunable together instead of leaving a half-configured mixture.

mnemosyne profile list
mnemosyne profile show quality
mnemosyne profile apply speed --dry-run
mnemosyne profile apply speed

The eight profiles

ProfileIntentUse case
minimalNo LLM, no embeddings. Pure SQLite and FTS5Local-only agents, CI, constrained devices
speedFastest recall. Bit vectors, small scan limits, aggressive degradationReal-time agents
qualityMaximum recall quality. Float32, every experimental feature onResearch agents, precision-critical work
researchDeep memory, aggressive consolidation and linkingMulti-session research, literature review
paranoidSecurity first. Strict write classifier, sync encryption, no host LLMSensitive data, compliance
balancedSensible defaults. The "just works" profileGeneral purpose, default install
embeddedTiny limits, bit vectors, no LLMRaspberry Pi, IoT, edge
developmentVerbose. Diagnostics on, warn-mode classifierDebugging Mnemosyne itself

embedded keeps embeddings on despite the name; minimal is the only profile that disables them.

How they differ

The full 74 keys per profile are in mnemosyne/core/profiles.py and printable with mnemosyne profile show <name>. The values that actually distinguish them:

Settingminimalspeedqualityresearchparanoidbalancedembeddeddevelopment
vec_typeint8bitfloat32int8int8int8bitint8
vec_weight0.00.40.60.50.50.50.40.5
fts_weight1.00.50.20.30.30.30.50.3
importance_weight0.00.10.20.20.20.20.10.2
embeddingsoffononononononon
llm_enabledfalsetruetruetruetruetruefalsetrue
llm_timeout301512012060601560
cross_session00110000
default_scopesessionsessionglobalglobalsessionsessionsessionsession
write_classifieroffoffwarnwarnstrictoffoffwarn
sync_encryptfalsefalsefalsefalsetruefalsefalsefalse
persona_enabledfalsefalsetruetruefalsefalsefalsetrue
auto_sleep_enabledfalsetruetruetruetruefalsetruetrue

Only quality turns on the whole vector-dependent feature block (polyphonic recall, query intent, fact recall, enhanced recall, proactive linking, lenient fact match, recall diagnostics). research enables most of it. development enables only recall diagnostics. The rest disable all of it.

paranoid is the only profile with a non-empty ignore_patterns, covering passwords, tokens, API keys, secrets, Bearer, Authorization, and PEM key blocks.

Validation

apply validates before writing and refuses the whole profile if any rule fails, so you never get a partially applied profile. Thirteen rules are enforced, and they exist because these combinations are silently useless rather than loudly broken:

  • The three embedding-disable aliases (no_embeddings, skip_embeddings, embeddings_off) must agree.
  • vec_weight must be above zero when embeddings are on. A profile with embeddings enabled and zero vector weight pays for embeddings and ignores them.
  • cross_session requires default_scope: global. Cross-session recall over session-scoped memories returns nothing.
  • smart_compress, sleep_model_refresh_enabled, llm_conflict_detection, and persona_enabled each require llm_enabled.
  • tier3_max_chars must be above zero when smart_compress is on.
  • proactive_linking, polyphonic_recall, enhanced_recall, and query_intent each conflict with no_embeddings.
  • Every key must exist in ENV_VAR_MAP.

The restart trap

Exactly one of the 74 keys is in REQUIRES_RESTART: vec_type. Every profile sets it, and the eight profiles disagree (int8, bit, float32).

This matters more than it looks. vec_type determines the element type of the sqlite-vec tables, which is fixed at creation. Applying a profile that changes it does not convert your existing vectors, and mnemosyne config reload cannot apply it either.

Crossing a vec_type boundary needs:

mnemosyne profile apply quality
# restart the process, then
mnemosyne reindex

mnemosyne profile apply detects this and prints the restart-and-reindex steps whenever vec_type actually changes, so you will not silently end up with vector tables in the wrong format.

CLI

mnemosyne profile list                                  # all built-ins with rating bars
mnemosyne profile apply <name> [--dry-run] [--config <path>]
mnemosyne profile show <name>                            # key = value, sorted
mnemosyne profile create <name> [description...]         # persisted to disk

mnemosyne config reload                                  # re-read config.yaml
mnemosyne config get <key>
mnemosyne config set <key> <value>
mnemosyne config migrate                                 # import current env vars into config.yaml

--config <path> works on apply but is missing from the printed help.

config set warns when the key requires a restart.

profile create captures your current configuration as a named profile, written to <config dir>/profiles/<name>.json. It persists across processes and appears in profile list alongside the built-ins.

Built-in profiles are never modified; a user profile with the same name as a built-in does not shadow it.

config.yaml

Path resolution, in order: $MNEMOSYNE_DATA_DIR/config.yaml, then $HERMES_HOME/mnemosyne/config.yaml, then ~/.hermes/mnemosyne/config.yaml.

Read precedence is config.yaml > environment variable > built-in default.

The file is seeded from defaults on first access, preferring any already-set environment variable, and seeding never overwrites an existing file. Writes are a full read-modify-write with sorted keys, so comments do not survive a config set or profile apply.

Two subsystems ignore config.yaml entirely. The persona modules and SHMR read os.environ directly at import time, so the persona_* and shmr_* values a profile writes have no runtime effect unless something also exports them as environment variables. See Persona and SHMR.

See also