RememberStackdocs.remember.dev

Configuration

How to bind a single deployment to stores, model seats, budgets, and optional exporters. This page is operator-facing and agent-scannable. Run-through: Getting started · Deployment.

TL;DR

NeedDo
Local full stackCopy .env.example.env, set OpenRouter key, docker compose up
Reproducible modelsPin explicit model IDs — never a rotating free router
Client onlypip install rememberstack + REMEMBERSTACK_API_URL
Ops / budgets / DLQrememberstack[server] + REMEMBERSTACK_DATABASE_URL
SecretsNever commit real keys; local examples are disposable

One deployment id = one trust domain. Changing REMEMBERSTACK_SELFHOST_DEPLOYMENT_ID creates a different deployment identity.

Install surfaces

Extra / artifactRole
rememberstack (base)Typed SDK, remote CLI/MCP, lineage-aware remote ingest
rememberstack[server]API, workers, PostgreSQL 19 adapters, local ops CLI
rememberstack[connectors-watched-directory]Names the watched-dir connector surface (stdlib)
rememberstack[k]Names the Plane K install surface
rememberstack[benchmark]LoCoMo / scorer deps
rememberstack[observability]Sentry-protocol + Langfuse SDKs (still opt-in by env)
GHCR image / ComposeFresh single-deployment self-host

Environment map (self-host)

Authoritative template: repository .env.example.

Identity and API

VariablePurpose
REMEMBERSTACK_SELFHOST_DEPLOYMENT_IDStable UUID for this deployment
REMEMBERSTACK_SELFHOST_DEPLOYMENT_SLUGShort slug (also default Sentry environment)
REMEMBERSTACK_SELFHOST_DEPLOYMENT_NAMEHuman label
REMEMBERSTACK_SELFHOST_API_PORTAPI listen port (Compose)
REMEMBERSTACK_SELFHOST_API_BEARER_BINDOptional {issued_deployment_uuid}:{sha256hex} of the API Bearer secret. When set, /operations and other memory routes require that Bearer. GET /healthz stays unauthenticated
REMEMBERSTACK_SELFHOST_API_BEARER_TOKENOptional plaintext Bearer for local self-host; hashed at startup and bound to SELFHOST_DEPLOYMENT_ID. Must match BIND when both are set
REMEMBERSTACK_SELFHOST_API_SIGNING_KEYSOptional JWKS (Ed25519 public keys only) this deployment verifies signed credentials against. Set beside or instead of API_BEARER_BIND: a caller may present a shared secret, a signed credential, or either. Refused at startup if it carries private key material, a non-Ed25519 key, or a key that half loads
REMEMBERSTACK_SELFHOST_API_REVOKED_CREDENTIAL_IDSOptional comma-separated credential ids to refuse. A signature is verified by arithmetic, so its issuer cannot withdraw one — this is how a revoked but unexpired credential is refused. Meaningless without API_SIGNING_KEYS, and rejected if set alone
REMEMBERSTACK_SELFHOST_REQUIRE_API_AUTHWhen true, the API process refuses to start unless it has a perimeter — API_BEARER_BIND, API_SIGNING_KEYS, or both. Default false (open quickstart)
REMEMBERSTACK_SELFHOST_BROWSER_ORIGINSOptional comma-separated https:// origins allowed to call this deployment from a browser. Empty by default, which advertises no CORS at all. Each entry must be an exact scheme-and-host origin — no wildcard, no path, no http://
REMEMBERSTACK_API_URLClient target; defaults to http://127.0.0.1:8000must match if you change the port
REMEMBERSTACK_TOKEN_HOSTDevice-grant host for remember login (required unless --token-host is passed). Never derived from the query API URL
REMEMBERSTACK_CONFIG_DIROptional override for the CLI credential directory. Holds credentials.json and, while a replaced credential is still awaiting revocation, pending-revocation.json — both 0600 inside a 0700 directory
REMEMBERSTACK_COST_EXPORT_BINDOptional second listen address for HTTP cost export (127.0.0.1:8001, [::1]:8001, or unix:/path). Unset = no HTTP export
REMEMBERSTACK_COST_EXPORT_TOKENBearer for the export listener. Required and ≥32 bytes when the bind is set

Calling a deployment from a browser

A browser refuses a cross-origin request before it is sent unless the server says the origin is allowed. The credential is never examined and the perimeter never runs, so the failure looks like the deployment being down — which is why this is configuration rather than something that can be worked around in a client.

REMEMBERSTACK_SELFHOST_BROWSER_ORIGINS names the origins permitted to do that. It is empty by default: a deployment nobody told about an app should not advertise anything, and a permissive default would hand every website on the internet the ability to make authenticated requests from a visitor's browser.

Each entry must be an origin exactly as a browser sends it: https://app.example.com, optionally with a port, and nothing else — lowercase scheme and host, no path, no query, no userinfo, no wildcard.

The reason is worth knowing. The match is a byte comparison against the request's Origin header, so a value that is not exactly what a browser sends can never match — it does not widen the perimeter, it silently closes it. An operator who writes https://*.example.com and watches the deployment start cleanly believes they have granted a subdomain tree; they have granted nothing, and will go looking for the fault in their app.

Validation is deliberately small: scheme, structure, case and port, and no finer judgement of hostname syntax than that. A rule strict enough to catch every impossible name also refuses real ones — underscores, trailing dots and IDNA2008 labels are all things browsers send and naive checks reject. DNS fails loudly and specifically for a name that does not exist, which is a better error than a startup refusal for a host that does. The origins actually installed are logged when the API starts, so a typo is something you can see rather than infer.

Credentialed CORS is disabled (allow_credentials is off). Be precise about what that does: it stops the response being shared with a page that made the request in credentials: "include" mode. It does not block an ordinary bearer call — a request carrying Authorization is preflighted, and that preflight succeeds because the header is on the allowlist. What is refused is a page trying to have cookies or client certificates count as authentication across the origin boundary. It does not reach into the browser and stop a page attaching cookies to a simple cross-origin request in the first place; that request may still be sent, and only its response is withheld.

So the honest statement is that no credentialed cross-origin call can succeed here, not that cookies can never leave the browser. The credential this surface expects travels in Authorization, and same-origin traffic is unaffected by any of it.

Only GET and POST are advertised, with Authorization and Content-Type. Sending Authorization makes the request preflighted, and that preflight succeeds because the header is on the allowlist — it is the browser's credentials: "include" mode, not the presence of a bearer header, that would need credentialed CORS.

Preflight responses are cached for ten minutes, which is worth knowing when you remove an origin: a browser that has already been told "yes" may keep that answer for up to that long, so revoking the credential is what ends access immediately, not editing this list.

The CORS layer is installed outermost, so refusals raised by other layers — an oversize body, an exhausted spend ceiling — reach the browser as the errors they are rather than as opaque network failures.

A non-default port is part of an origin and may be included: https://app.example.com:8443 (1–65535, but not 443 — a browser omits the default port from Origin, so writing it out matches nothing). https://localhost and https://localhost:3000 are accepted, so a self-hoster can develop against a local https listener.

Several origins are comma-separated, and the whole list is validated together — a stray comma is a refusal, not a silently skipped entry, because a list that starts with fewer origins than you wrote hides the missing one until somebody's browser is turned away.

REMEMBERSTACK_SELFHOST_BROWSER_ORIGINS=https://app.remember.dev

Compose passes this through, so it can be set in .env beside the other deployment settings.

Stores (Compose local defaults)

VariablePurpose
REMEMBERSTACK_POSTGRES_*Postgres user/password/db for the stack
REMEMBERSTACK_MINIO_*MinIO access keys for object storage
REMEMBERSTACK_DATABASE_URLUsed by local server-extra CLI tools (budget, ops) when connecting to the spine

Replace every local-only secret before any non-isolated use.

Ingest admission

VariablePurpose
REMEMBERSTACK_SELFHOST_INGEST_BODY_MAX_BYTESOptional POST /ingest request-body ceiling in bytes, enforced before the body is buffered (413 body_too_large; requests without a Content-Length get 411). Unset (default) = no engine-imposed limit — a managed host publishes and sets its own bound

Managed deployments also configure content-free billing receipts. These values are fleet-authored as one all-or-nothing set; ordinary self-host installations leave all of them unset and do not start the Compose managed profile.

VariablePurpose
REMEMBERSTACK_SELFHOST_METER_INGEST_URLHTTPS root of the managed control-plane receipt service
REMEMBERSTACK_SELFHOST_METER_INGEST_TOKENDeployment-scoped umc_mi_ producer credential; never a customer API token
REMEMBERSTACK_SELFHOST_METER_IDENTITY_KEYDeployment-local umc_mik_ HMAC key for stable opaque lineage/version IDs. It never leaves the engine and must survive token rotation
REMEMBERSTACK_SELFHOST_METER_ORG_IDFleet-bound organisation UUID carried in every receipt
REMEMBERSTACK_SELFHOST_METER_PROJECT_IDFleet-bound Project UUID carried in every receipt
REMEMBERSTACK_SELFHOST_REQUIRE_METERINGWhen true, startup fails unless the entire managed receipt configuration is present

Conversion routes

VariablePurpose
REMEMBERSTACK_SELFHOST_CONVERSION_ROUTESJSON object mapping input MIME type to a converter adapter name, e.g. {"text/markdown": "passthrough", "text/plain": "passthrough", "text/html": "markitdown", "application/pdf": "mistral_ocr"}. Shipped adapter names: passthrough, markitdown, mistral_ocr. Setting the variable replaces the whole table (defaults are the stock text table); a MIME type without a route dead-letters on convert, and an unknown adapter name refuses startup

The mistral_ocr route is BYO-key (provider-backed; off unless routed):

VariablePurpose
REMEMBERSTACK_MISTRAL_OCR_API_KEYMistral API key. Required when any route names mistral_ocr; composition refuses to start without it
REMEMBERSTACK_MISTRAL_OCR_MODELOCR model (default mistral-ocr-latest). Pin a dated model for reproducible representations — the manifest records whatever model identifier the provider echoes
REMEMBERSTACK_MISTRAL_OCR_MAX_DOCUMENT_BYTESDeterministic input ceiling before any provider call (default 50000000)
REMEMBERSTACK_MISTRAL_OCR_CONFIDENCE_GRANULARITYword (default) or page; word-level scores are retained in the provider-response interchange asset
REMEMBERSTACK_MISTRAL_OCR_KEEP_PROVIDER_RESPONSEKeep the sanitized raw OCR response as an interchange asset (default true)
REMEMBERSTACK_MISTRAL_OCR_PRICE_USD_PER_1000_PAGESMetered price per 1000 processed pages recorded in the cost ledger (default 1)

Every output-affecting mistral_ocr option is folded into the converter version, so changing the model or an option re-converts affected documents as new representations instead of replaying old ones.

Live-graph resources

VariablePurpose
REMEMBERSTACK_SELFHOST_GRAPH_POOL_SIZEDedicated PostgreSQL graph-pool connections (default 4)
REMEMBERSTACK_SELFHOST_GRAPH_POOL_TIMEOUT_SMaximum wait for a graph-pool connection (default 1 second)
REMEMBERSTACK_SELFHOST_GRAPH_MAX_CONCURRENCYPer-process admitted graph expansions (default 2)
REMEMBERSTACK_SELFHOST_GRAPH_WORK_MEM_KIBTransaction-local graph work_mem ceiling per memory node (default 16384 KiB)

Size these four values together with PostgreSQL shared memory and host reserve. Increasing pool or concurrency independently multiplies worst-case memory; the managed service applies a stricter host-level admission calculation.

Interactive retrieval resources

VariablePurpose
REMEMBERSTACK_SELFHOST_RETRIEVAL_POOL_SIZEDedicated PostgreSQL P1/fact read connections (default 4)
REMEMBERSTACK_SELFHOST_RETRIEVAL_POOL_TIMEOUT_SMaximum admission wait for an interactive retrieval read (default 1 second, also clamped to the operation deadline)
REMEMBERSTACK_SELFHOST_RETRIEVAL_MAX_CONCURRENCYPer-process P1/fact reads admitted across the shared retrieval pool (default 4)

Keep maximum concurrency at or below pool size. fact_context also clamps every admitted PostgreSQL statement and transaction to its remaining operation deadline; pool saturation returns a typed boundary rather than using the worker/write pool.

Provider (OpenRouter)

VariablePurpose
REMEMBERSTACK_OPENROUTER_API_KEYRequired to start the provider adapter and process a corpus
REMEMBERSTACK_OPENROUTER_MAX_COMPLETION_TOKENSCombined reasoning+content budget (default 32000 in example)
REMEMBERSTACK_OPENROUTER_EMBEDDING_PROVIDEROptional hard pin of embedding host slug
REMEMBERSTACK_OPENROUTER_EMBEDDING_PROVIDER_ORDERPreferred ordered shortlist (wins over hard pin)
REMEMBERSTACK_OPENROUTER_REASONING_EFFORTGlobal effort: nonemax (unset = model default)
REMEMBERSTACK_OPENROUTER_REASONING_EFFORT_MAPJSON map of model-id → effort overrides

Embedding routing policy notes: design/operations/openrouter-embedding-routing.md in the repo.

Model seats (optional overrides)

Pin explicit IDs for reproducible runs. Unset values fall back to deployment profile defaults.

VariableStage
REMEMBERSTACK_E2_EXTRACT_MODELClaim extraction
REMEMBERSTACK_E3_NORMALIZE_MODELNormalization / adjudication seats as bound by profile
REMEMBERSTACK_STRUCTURER_MODELOnly string-anchor structure fallback proposer
REMEMBERSTACK_SKELETON_CHECK_MODELBounded skeleton sanity judge (default flash-class)
REMEMBERSTACK_ROLE_MODELTitle-only section-role classifier
REMEMBERSTACK_SUMMARY_MODELBottom-up section summaries + root placement reduction

Structure honesty: routine skeleton construction is deterministic. Bounded summary/role/check calls still run; STRUCTURER is not “the whole document structure model.”

Smoke conversion route is Markdown unless you register more converters on the deployment.

P1 search indexes (D94)

P1 lives in PostgreSQL. Migrations own the pgvector HNSW and pg_textsearch BM25 indexes, while ordinary ingestion transactions update the search rows and embedding attestations. There is no separate search-store path, maintenance worker, or search-index environment namespace to configure.

Spend ceilings (optional)

export REMEMBERSTACK_WORK_BUDGETS='[
  {
    "deployment_id":"<deployment-uuid>",
    "stage":"extract_claims",
    "lane":"steady",
    "window_seconds":86400,
    "ceiling_usd":"10.00"
  }
]'
  • JSON list; omit a route → unlimited
  • Use null lane for unlaned K/P routes
  • Exhaustion parks healthy work until the window ends — does not burn handler attempts or invent a failure
  • Inspect: remember budget inspect --deployment <uuid> (needs [server])

Observability (optional, fail-closed off)

Exporters stay disabled until env is non-empty.

VariableEffect
REMEMBERSTACK_SENTRY_DSNMetadata-only errors to Sentry/GlitchTip/Bugsink
REMEMBERSTACK_SENTRY_ENVIRONMENTDefaults to deployment slug
REMEMBERSTACK_SENTRY_SAMPLE_RATEDefaults to 1.0
LANGFUSE_PUBLIC_KEY + SECRET_KEY + HOSTLoCoMo answer/judge traces only when all three set

What is not sent: request bodies, local vars, breadcrumbs, PII, prompts/completions, exception message text as free-form dumps. Worker tags stay stage/lane/processing id. Postgres + JSON telemetry remain authoritative for retries.

Conversion and connectors

PieceConfig posture
Markdown smokeDefault Compose conversion route
HTML/PDF/mediaBind converter routes per MIME type via REMEMBERSTACK_SELFHOST_CONVERSION_ROUTES (the smoke profile does not auto-route beyond text)
Watched directoryConnector extra + connector management API/CLI; credentials stay deployment-side
Lineage identitysource_kind + source_ref together on ingest; `versioning_mode=snapshot

See Ingestion and Lifecycle.

What configuration is not

  • Not multi-tenant control-plane config
  • Not a hosted SLA or billing product
  • Not free-tier model routing for publication benchmarks
  • Not secret storage — use your secret manager outside git

Progressive disclosure

DepthPage
This pageEnv + seats + budgets
DeploymentCompose lifecycle, projections
TroubleshootingWhen config fails in practice
CLI referencebudget / ops command contracts
Repo .env.exampleCanonical variable list

Next