Claude Transcripts docs GitHub
Work in progressUnder active development — not tested as ready for use. Breaking changes land without notice, stored data may need to be discarded between revisions, and there is no auth or security model.

28. External vs bundled Meilisearch

Date: 2026-07-30

Status

Accepted (2026-08-07): option 2, external and namespaced — see Decision. The bundled instance remains the default and the configuration we test; pointing at an external one is now safe rather than merely likely to work.

Context

CouchDB and Garage are addressable stores. Point COUCHDB_URL / S3_ENDPOINT elsewhere and the app works; the bundled stack is a convenience, not an assumption (ADR 0020).

Meilisearch is a derived index: everything in it is a projection of CouchDB (ADR 0009). Making it external means more than a URL:

ADR 0009 also anticipates indexing sources beyond this stack, which argues for a shared external instance: the case hardest to isolate.

Options

  1. Bundled only (status quo). Meilisearch stays part of deploy/, no auth, localhost. Simple, isolated, disposable; rebuilds are safe because nothing else uses it. Rules out reusing an existing instance.
  2. External, namespaced. Support MEILI_HOST + MEILI_API_KEY pointing anywhere, and prefix index names per deployment (e.g. <instance>_sessions). Removes the collision and makes a destructive rebuild safe. Costs a config surface (instance id), a migration for existing index names, and key/permission handling.
  3. External, bring-your-own-index. The operator creates and configures the indexes; we only read and write documents, never settings, and never clear. Safest for a shared instance, but moves setup burden onto the operator and makes our settings documentation normative rather than executable.
  4. Pluggable search backend. Treat Meilisearch as one implementation behind a small interface (index/search/rebuild), so an external engine — or Typesense, or none — is a config choice. The most flexible and the most work; only worth it if a second backend is actually wanted.

Decision

Adopt option 2: external, namespaced.

CouchDB databases and S3 buckets were already named in config/ as namespaced keyed maps, while Meilisearch's indexes were hard-coded as "sessions" and "turns". Since reindex clears an index before rebuilding, anyone pointing MEILI_HOST at an existing Meilisearch (which config always allowed) could destroy someone else's sessions index with a supported command. The status quo was the dangerous option.

So the index names move into config/ as meilisearch.indexes, defaulting to claude-transcripts-sessions and claude-transcripts-turns. That is all of option 2 that Tier 1 needs:

Deliberately not adopted:

Migrating an existing instance

Nothing in Meilisearch is authoritative, so there is no data migration. An instance running before this change has indexes literally named sessions and turns; after it, the app reads and writes the namespaced names. Run claude-transcripts reindex to populate them, then delete the two old indexes if you want the space back. A deployment whose config.json predates the meilisearch key gets the defaults, so it keeps working without being edited.

Consequences