Configuration reference
The config loader parses strict JSONC, with comments and trailing commas. Every section is optional except embedding: without models, there is nothing to embed or route.
dimple init writes the full annotated schema. ${ENV_VAR} placeholders resolve from the environment, so tokens stay out of the config file. Validation reports all problems in one pass.
{ // store "storeUrl": "file:./.dimple/dimple.db", // remote (Turso): "libsql://<org>-<db>.turso.io?authToken=${TURSO_MEMORIES_TOKEN}"
// durable jobs "jobs": { "dbUrl": "file:./.dimple/jobs.db", // separate DB for the job queue "execution": "background", // background | inline | external (RESERVED — not yet // wired; the background worker is always installed) "concurrency": 4, "leaseTimeoutMs": 120000, // RESERVED — not yet wired to the executor "maxAttempts": 10, // clamped to [1, 100] → take maxAttempts "pollIntervalMs": 1000, // RESERVED — not yet wired },
// embeddings (REQUIRED) "embedding": { "defaultModel": "minilm", // the ACTIVE model for writes/queries // ONNX Runtime session options EVERY model inherits (per-model blocks // override them field by field). Split cores across parallel workers: // "intraOpNumThreads": 4, // 4 on 8 cores with 2 workers (0 = runtime default = 1/core) // "interOpNumThreads": 1, // only used when executionMode is "parallel" // "executionMode": "sequential", // sequential | parallel // "graphOptimizationLevel": "all", // disabled | basic | extended | all | layout // "enableCpuMemArena": false, // dimple default (bulk ingest does not need the arena) // "enableMemPattern": true, // "gpuMemLimit": 2147483648, // CUDA arena cap in bytes // "arenaExtendStrategy": 0, // 0 = next power of two, 1 = as requested "models": [ // local, any Transformers.js ONNX model (auto-installed on first use) { "id": "minilm", "provider": "transformers", "model": "Xenova/all-MiniLM-L6-v2", "dimensions": 384, "autoInstall": true, // optional peer auto-install (default true) // per-model runtime options (all optional, defaults shown): // "device": "cpu", // auto|gpu|cpu|wasm|webgpu|cuda|dml|coreml|webnn // "dtype": "q8", // fp32|fp16|q8|int8|uint8|q4|bnb4|q4f16|q2|q2f16|q1|q1f16 // "pooling": "mean", // mean|cls|none // "normalize": true, // "cacheDir": "~/.cache/dimple", // "vectorType": "float32", // float32|float16|float8|float1bit // per-model ORT session options, override the global block per field: // "sessionOptions": { "intraOpNumThreads": 2, "enableCpuMemArena": true }, // "wasm": { "numThreads": 4 }, // wasm backend ONLY, intra-op threads do not reach it }, // hosted, any OpenAI-compatible endpoint (default https://api.openai.com/v1) { "id": "openai", "provider": "openai", "model": "text-embedding-3-small", "dimensions": 1536, "apiKey": "${OPENAI_API_KEY}", "baseURL": "https://api.openai.com/v1", }, // native provider families, baseURL baked in, no baseURL needed // { "id": "gemini", "provider": "google", "model": "gemini-embedding-2", "dimensions": 3072, "apiKey": "…" } // { "id": "cohere", "provider": "cohere", "model": "embed-english-v3.0", "dimensions": 1024, "apiKey": "…" } // { "id": "titan", "provider": "bedrock", "model": "amazon.titan-embed-text-v2:0", "dimensions": 1024 } ], },
// topic tree shape (all optional, defaults shown) "topics": { "maxLeafItems": 128, // leaf overflow -> split "minLeafItems": 32, // leaf underflow -> borrow/merge "maxChildren": 16, // fan-out cap per split "minChildren": 4, "maxDepth": 6, "beamWidth": 3, // beam width for the leaf resolver (Store.resolveTopics) "splitDeferredHardLimit": 512, // force-split threshold for deferred leaves "rebalanceCooldownMs": 60000, // min delay between rebalances "lloydPasses": 2, // k-means refinement passes },
// artifact graph (all optional, defaults shown) "graph": { "enabled": true, "maxDepth": 2, // traversal depth "maxNeighbors": 12, // per-node fan-out "maxTotal": 80, // total neighborhood cap "supersedeDemotion": 0.5, // score penalty for superseded results "conflictBands": { "nearDuplicate": 0.9, "conflictLow": 0.6 }, "clusterK": 8, // dream concept-clustering K "clusterMinSize": 3, // min members for a concept },
// dream/repair LLM (optional, enables `dimple dream`) "llm": { "baseURL": "https://api.openai.com/v1", // any OpenAI-compatible endpoint "apiKey": "${OPENAI_API_KEY}", "modelId": "gpt-4o-mini", "temperature": 0.2, // 0 to 2 "maxOutputTokens": 512, // positive integer "reasoningEffort": "low", // low | medium | high },
// logging (all optional, console is silent by default) "logging": { "enabled": true, "level": "info", // trace | debug | info | warn | error "format": "jsonl", // jsonl | pretty (console rendering) "file": "./.dimple/logs.jsonl", // durable JSONL sink (off unless set) "scopes": { "@dimple/store": "debug" }, // scope names are runtime logger names, not installable packages "ringSize": 4096, // in-memory live tail },
// retrieval/write defaults (all optional) "defaultK": 60, // RRF smoothing constant "defaultLimit": 10, // default result count "defaultTtlSecs": 604800, // default write TTL in seconds; set ttlSecs:null per memory for no expiry "sweepIntervalMs": 300000, // expiry sweep cadence (5 minutes)}In the jobs section, dbUrl, concurrency, and maxAttempts affect the SDK and CLI runtime. execution, leaseTimeoutMs, and pollIntervalMs are accepted, but they do not change runtime behavior yet. The SDK and CLI run workers in the process.
Remote databases (Turso)
Section titled “Remote databases (Turso)”storeUrl and jobs.dbUrl accept remote libSQL URLs (libsql://, https://, and ws://) for Turso or any libSQL-compatible host. The same engine runs FTS5, vector search, the topic tree, and durable jobs over the network. This setup is verified against the Turso service.
Turso tokens are per database, so each URL carries its own token. ${ENV_VAR} resolution keeps them out of the config file:
{ "storeUrl": "libsql://<org>-<memdb>.turso.io?authToken=${TURSO_MEMORIES_TOKEN}", "jobs": { "dbUrl": "libsql://<org>-<memdb>.turso.io?authToken=${TURSO_MEMORIES_TOKEN}" },}Notes:
- One database can serve both memories and the durable queue, in separate table namespaces. The simplest setup shares one URL and one token.
TURSO_TOKENworks as the fallback. A dedicated jobs database stays possible withTURSO_JOBS_URLandTURSO_JOBS_TOKEN. - The jobs database must also be remote when the store is remote, because the queue and workflow state cross invocations.
- Remote URLs skip two
file:-only behaviors: parent-directory creation and the migration lock. - On edge runtimes, use a hosted embedding provider. The local ONNX runtime is local and CLI-only.
Embedding models
Section titled “Embedding models”Providers
Section titled “Providers”provider | Models | baseURL needed? |
|---|---|---|
transformers | Transformers.js ONNX models. Runs locally and installs on first use. | No |
openai (default) | OpenAI-compatible endpoints, including OpenAI, vLLM, Ollama, Groq, and Mistral. | Optional. Defaults to OpenAI. |
google | Google Gemini embedding models. | No |
cohere | Cohere Embed models. | No |
bedrock | Amazon Titan and Nova embedding models. Uses AWS credentials from the environment. | No |
dimensions must match the model output. A mismatch returns a typed error on first use.
Multiple models can coexist. Each model gets its own vector tables and its own topic tree. defaultModel picks the active model. Queries route per model, and a backfill uses the durable memory.embed job.
Transformers runtime options (per model, all optional)
Section titled “Transformers runtime options (per model, all optional)”| Field | Values | Default | What it does |
|---|---|---|---|
device | auto | gpu | cpu | wasm | webgpu | cuda | dml | coreml | webnn | cpu | Execution backend. cpu and wasm are tested. CUDA on Linux x64 needs the provider and CUDA 12; see CUDA on Linux x64. |
dtype | fp32 | fp16 | q8 | int8 | uint8 | q4 | bnb4 | q4f16 | q2 | q2f16 | q1 | q1f16 | q8 | Quantizes model weights for inference. It does not quantize output vectors. |
pooling | mean | cls | none | mean | Sentence-pooling strategy. |
normalize | boolean | true | L2-normalize the output. |
cacheDir | path | HF cache | Override the model download cache. |
autoInstall | boolean | true | Auto-install the optional @huggingface/transformers peer on first use. Scripts are skipped. |
sessionOptions | See Session options. | ORT defaults, except enableCpuMemArena: false | Set thread counts, execution mode, graph optimization, and memory arena options. gpuMemLimit caps GPU memory in bytes. arenaExtendStrategy selects the growth policy: 0 for the next power of two, 1 as requested. Set device: "cuda" to use the CUDA options. Tested at about 3.7 times CPU speed on a 4 GB card. |
wasm | { numThreads? } | ORT environment default | Set the WASM backend thread count. Intra-op thread settings do not apply to WASM. |
Session options (ONNX Runtime)
Section titled “Session options (ONNX Runtime)”sessionOptions is one shared struct, accepted at two levels. embedding.sessionOptions is the default every model inherits. A model’s own block overrides it field by field.
The precedence is built-in defaults, then global, then model. A field left out keeps the ONNX Runtime default.
| Field | Values | Default | What it does |
|---|---|---|---|
intraOpNumThreads | integer 0 to 1024 | 0 (runtime) | Threads used inside each operator. 0 means one thread per physical core for each session, so multiple Dimple processes can oversubscribe the machine. |
interOpNumThreads | integer 0 to 1024 | 0 (runtime) | Threads used between operators. Read only when executionMode is parallel. |
executionMode | sequential | parallel | sequential | Run operators one after another, or in parallel. |
graphOptimizationLevel | disabled | basic | extended | all | layout | all | How much the graph is fused or rewritten before inference. This is load-time work. |
enableCpuMemArena | boolean | false | Dimple default. The CPU arena preallocates and holds memory across runs (onnxruntime#11627), which bulk ingest does not need. |
enableMemPattern | boolean | ORT default | Record and reuse an allocation for repeated input shapes. ONNX Runtime applies this only in sequential mode. |
gpuMemLimit | number (bytes) | unbounded | Cap the CUDA arena. ONNX Runtime grows the arena by powers of two. Cards with 8 GB or less can run out of memory during a batch. |
arenaExtendStrategy | 0 | 1 | 0 | CUDA arena growth policy. 0 is kNextPowerOfTwo. 1 is kSameAsRequested. |
Tuning for parallel processes
Section titled “Tuning for parallel processes”ONNX Runtime gives every session its own intra-op thread pool, sized at one thread per physical core. Two Dimple processes on an 8-core machine therefore run 16 threads. The processes share the same cores, so ingestion may not be faster than with one process.
Split the threads explicitly:
{ "embedding": { // 8 physical cores, 2 ingest workers -> 4 threads each "sessionOptions": { "intraOpNumThreads": 4 }, "defaultModel": "minilm", "models": [ { "id": "minilm", "provider": "transformers", "model": "Xenova/all-MiniLM-L6-v2", "dimensions": 384, }, ], },}The recipe is intraOpNumThreads = floor(physicalCores / workers). Set it once globally, because each worker process reads the same config. Override it per model when one model deserves a different share. Two caveats:
enableCpuMemArenastaysfalseby default. The arena can add a small amount of single-process speed while holding memory across runs. Set"enableCpuMemArena": trueglobally or per model when you run one process and want that speed.- On the
wasmbackend,intraOpNumThreadsis ignored. ONNX Runtime documents thread counts as Node-binding only, and the WASM backend readsenv.wasm.numThreadsinstead. Set it in thewasmblock ("wasm": { "numThreads": 4 }). The standalonedimplebinary pins that value to1. The embedded default is ONNX Runtime’s own (0, system-determined).
CUDA on Linux x64
Section titled “CUDA on Linux x64”device: "cuda" runs inference on the GPU through the ONNX Runtime CUDA execution provider. The provider is not in the npm tarball. onnxruntime-node downloads it from NuGet in its own postinstall, and the CUDA runtime libraries must be visible to the dynamic loader.
bun run setup:cuda does both steps. bun run setup:cuda --check reports what is present and whether the provider resolves.
- The script runs the onnxruntime-node installer when the provider is missing. The download is about 196 MB from NuGet, and about 300 MB after extraction. The installer verifies only the HTTPS download and the ZIP structure, with no checksum. Treat it as any postinstall binary download.
- It stages the CUDA 12 and cuDNN 9 runtime wheels into
~/.cache/dimple/cuda12withuv pip install --targetand writes anenv.shthere. - Source
~/.cache/dimple/cuda12/env.shbefore you start Dimple, or pass the printedLD_LIBRARY_PATHinline.
Version constraints: onnxruntime-node 1.24.3 requires CUDA 12.8 or newer and cuDNN 9.x. That is the version transformers.js pins. ONNX Runtime 1.27 ships CUDA 13 builds, but only for PyPI and NuGet. There is no Node binding, so a system CUDA 13 installation does not satisfy it, and the setup script pins the CUDA 12 wheels.
If the provider or a runtime library is missing, model load fails with the provider error naming the missing library, for example libcublasLt.so.12. There is no silent CPU fallback.
Bun is secure by default. It does not run lifecycle scripts for packages outside its trusted list, so the onnxruntime-node postinstall does not run here by default.
The setup script does the same work explicitly. CPU-only users need nothing. The default install stays CPU.
Vector storage quantization (vectorType)
Section titled “Vector storage quantization (vectorType)”The per-memory search vectors are stored in the model’s vec_<dims>_<model> table and searched with libSQL’s native vector_distance_cos:
vectorType | Encoding | 384-dim stored | Tested |
|---|---|---|---|
float32 (default) | float32 | 1536 B | Yes |
float16 | bfloat16 | ~790 B | Seam exists |
float8 | int8 | 395 B (4x) | Yes, on write, query, health, and split |
float1bit | binary | ~48 B (32x) | Partial. L2 is unsupported for 1-bit. |
The topic tree centroids and memories.embedding stay float32. Quantization applies only to stored search vectors.
Validation notes
Section titled “Validation notes”All failures are typed with precise messages:
temperaturemust be in [0, 2].maxAttemptsandmaxOutputTokensare positive integers.maxAttemptsis at most 100.intraOpNumThreads,interOpNumThreads, andwasm.numThreadsare integers in [0, 1024].defaultModelmust name a configured model. Unknown keys fail at first use.- A
dimensionsmismatch fails on first embed. - JSONC is strict. Duplicate keys are rejected.
- Multiple problems are reported in one pass.
Environment variables
Section titled “Environment variables”The loader also reads three variables directly, beyond the ${ENV_VAR} placeholders in the file:
| Variable | What it does |
|---|---|
DIMPLE_CONFIG | Explicit config file path. Overrides project discovery. |
DIMPLE_CONFIG_CONTENT | Inline JSONC config content. No file is needed. |
DIMPLE_CWD | Treat this directory as the project root. Config discovery starts there, relative file: URLs resolve against it, and index() relative paths anchor to it. Use it for daemons, systemd units, and tests that run from a different working directory. |
DIMPLE_CWD does not change the process working directory. It changes only the paths Dimple resolves. Leave it unset for normal use. Relative file:./.dimple/... defaults keep working against the process working directory.