Reference

HTTP API

Every endpoint, every parameter. The daemon listens on a Unix-domain socket at /tmp/eidetic-daemon.sock by default (/var/run/eidetic.sock on Linux). Set EIDETIC_TCP=1 for a loopback TCP fallback on 127.0.0.1:9876.

Conventions

Health & observability

GET /healthz

Liveness probe. Returns 200 + {"status":"ok"}. No store touch — answers from the listener thread, so a stuck writer pool doesn't tip the readiness signal. Stays open even when auth is enabled.

curl --unix-socket /tmp/eidetic-daemon.sock http://localhost/healthz
# → {"status":"ok"}
GET /metrics

Version, uptime, engram counts per surface, capture skip-counter, DB size, query latency P50/P95/P99. Schema is additive-only across versions. Three formats via Accept header:

curl --unix-socket /tmp/eidetic-daemon.sock http://localhost/metrics                                              # JSON (default)
curl -H 'Accept: text/plain' --unix-socket /tmp/eidetic-daemon.sock http://localhost/metrics                      # Prometheus exposition (v0.0.10+)
curl -H 'Accept: application/openmetrics-text' --unix-socket /tmp/eidetic-daemon.sock http://localhost/metrics    # OpenMetrics 1.0.0 (v0.0.11+)

v0.0.12+ adds query_latency_p50_us, _p95_us, _p99_us to JSON and eidetic_query_duration_microseconds{quantile=...} summary to Prometheus / OpenMetrics. Real Prometheus scrapers send a multi-type Accept by default; v0.0.11+ honors the OpenMetrics clause when present. v0.0.37+ adds latest_version + update_available fields populated by a 24h GitHub releases poll.

Surfaces

GET /surfaces

Map of every active surface to its engram count. Live view of what the daemon has seen. Empty store returns {}. (v0.0.13+)

curl --unix-socket /tmp/eidetic-daemon.sock http://localhost/surfaces
# → {"claude_code": 274203, "cursor": 4135, "cowork": 223}

Engrams — query

GET /engrams?[surface=X]&[limit=N]&[since=ns]&[before=ns]&[order=asc]

The core retrieval endpoint. Returns a JSON array of engrams.

ParamTypeDefaultDescription
surfacestring(optional, v0.0.23+)Surface name. Omit to retrieve across all surfaces.
limitint50Max rows. Capped at 500.
sinceint64 ns(none)Lower bound on ts (exclusive).
beforeint64 ns(none, v0.0.21+)Upper bound on ts (exclusive).
orderstringdescasc for oldest-first (v0.0.22+); anything else = newest-first.
# Last 5 engrams from claude_code surface
curl --unix-socket /tmp/eidetic-daemon.sock 'http://localhost/engrams?surface=claude_code&limit=5'

# Sliding time-window across all surfaces
curl --unix-socket /tmp/eidetic-daemon.sock 'http://localhost/engrams?since=1747000000000000000&before=1747500000000000000'

# Oldest-first for replay
curl --unix-socket /tmp/eidetic-daemon.sock 'http://localhost/engrams?surface=claude_code&order=asc'

P95 retrieval is 0.27 ms on a 10K-row fixture (M4 MacBook, 2026-05-13). Spec SLO is ≤100 ms; current headroom ~370×.

Engrams — insert

POST /engrams

Direct API-side insert; bypasses the fsnotify capture path. Enables injection from mobile, webhooks, relay pipelines. (v0.0.16+)

Body: {"surface": "...", "payload": "...", "ts": unix-ns}. ts optional (defaults to time.Now()).

curl -X POST --unix-socket /tmp/eidetic-daemon.sock \
  -H 'Content-Type: application/json' \
  -d '{"surface":"mobile","payload":"noted from phone"}' \
  http://localhost/engrams
# → {"id": 1234}
POST /engrams/batch

Bulk atomic insert — array of engrams committed in one transaction. Efficient for relay sync, session replay, bulk import. Body cap: 32 MiB. (v0.0.17+)

curl -X POST --unix-socket /tmp/eidetic-daemon.sock \
  -H 'Content-Type: application/json' \
  -d '[{"surface":"mobile","payload":"note 1"},{"surface":"mobile","payload":"note 2"}]' \
  http://localhost/engrams/batch
# → {"inserted": 2}

Engrams — point access

GET /engrams/{id}

Fetch a single engram by primary key. 404 when not found, 400 on non-integer or zero. Use after a POST /engrams to confirm the stored row. (v0.0.18+)

curl --unix-socket /tmp/eidetic-daemon.sock 'http://localhost/engrams/1234'
# → {"id":1234,"surface":"mobile","ts":...,"payload":"...","meta":""}
DELETE /engrams/{id}

Surgical removal of a single engram. 404 when not found, 400 on non-integer or zero. Use to remove accidentally captured sensitive data or dedup relay noise. (v0.0.19+)

curl -X DELETE --unix-socket /tmp/eidetic-daemon.sock 'http://localhost/engrams/1234'
# → {"deleted":1}

Engrams — count + purge

GET /engrams/count?[surface=X][&since=ns]

Returns {"count": N} without fetching rows. Use for monitoring badges, health dashboards, sync-diff checks. (v0.0.20+)

curl --unix-socket /tmp/eidetic-daemon.sock 'http://localhost/engrams/count'
curl --unix-socket /tmp/eidetic-daemon.sock 'http://localhost/engrams/count?surface=claude_code'
curl --unix-socket /tmp/eidetic-daemon.sock 'http://localhost/engrams/count?since=1747500000000000000'
DELETE /engrams?surface=X[&before=ns]

Bulk delete by surface (optionally bounded by timestamp). Returns {"deleted": N}. (v0.0.13+)

# Purge all cursor engrams
curl -X DELETE --unix-socket /tmp/eidetic-daemon.sock 'http://localhost/engrams?surface=cursor'

# Purge only engrams older than a cutoff
curl -X DELETE --unix-socket /tmp/eidetic-daemon.sock 'http://localhost/engrams?surface=cursor&before=1715000000000000000'

Search

GET /search?q=...[&surface=X][&limit=N]

FTS5 keyword / phrase / boolean search over engram payloads, ranked by relevance. Answers "what did I say about X?" Same engram JSON shape as /engrams, plus a snippet field (~200-char context window around the match keyword, v0.0.28+). (v0.0.14+)

curl --unix-socket /tmp/eidetic-daemon.sock 'http://localhost/search?q=benchmark'
curl --unix-socket /tmp/eidetic-daemon.sock 'http://localhost/search?q="benchmark+result"&surface=claude_code&limit=10'

Recent

GET /recent?[since=ns][&before=ns]&[limit=N]

Newest engrams across all surfaces, newest-first. since + before enable sliding-window polling. Answers "what happened lately?" without a keyword or surface filter. Max 500 rows. (v0.0.15+)

curl --unix-socket /tmp/eidetic-daemon.sock 'http://localhost/recent'
curl --unix-socket /tmp/eidetic-daemon.sock 'http://localhost/recent?since=1747500000000000000&limit=20'
curl --unix-socket /tmp/eidetic-daemon.sock 'http://localhost/recent?before=1747500000000000000&limit=20'

AI-powered recall

GET /ask?question=<text>[&surface=X][&limit=N]

Extracts keywords from a natural-language question, FTS5-retrieves top-K engrams, returns them wrapped in answer-scaffolding for the caller's host LLM. Same semantics as the nucleus_ask MCP tool — MCP + HTTP /ask have identical retrieval behavior. (v0.0.38+)

Response shape: {question, fts_query, instructions, engrams}. LRU + TTL cache so repeat questions don't re-hit the index (v0.0.45+) — every response includes X-Ask-Cache: hit or miss.

curl --unix-socket /tmp/eidetic-daemon.sock \
  'http://localhost/ask?question=what+was+that+Postgres+trick'

# Inspect the generated FTS query
curl --unix-socket /tmp/eidetic-daemon.sock \
  'http://localhost/ask?question=what+was+that+Postgres+trick' | jq '.fts_query'

Export

GET /export[?surface=X][&since=ns][&before=ns]

Paginated NDJSON stream of every engram, asc timestamp order. Memory-bounded — safe against 10M-row stores via 1000-row pages. Final line is a summary {"_export_complete": true, "_count": N} so clients can verify completion. (v0.0.42+)

Headers: Content-Type: application/x-ndjson + Content-Disposition: attachment; filename="engrams-export.ndjson"curl -O saves the file with a sensible name; jq consumes one line at a time.

# Save everything
curl -O --unix-socket /tmp/eidetic-daemon.sock 'http://localhost/export'

# Or pipe to jq line-by-line
curl --unix-socket /tmp/eidetic-daemon.sock 'http://localhost/export' \
  | jq -r 'select(._export_complete | not) | .payload[0:100]'

Caller auth (opt-in)

Off by default — preserves the single-user UDS-trust model in the security policy. Enable with one env var or flag:

EIDETIC_AUTH=1 eideticd      # env var (recommended for service managers)
eideticd -auth                # flag (recommended for one-shot invocations)

On enable, the daemon writes <dataDir>/auth-token (0600 perms, 64-char hex from crypto/rand). Token rotates every restart — no stale-token replay. /healthz stays open even with auth on; everything else requires Authorization: Bearer <token>. (v0.0.9+)

TCP bridge

The -bridge :8421 flag starts a second TCP listener alongside the primary UDS server. Both share the same store. Used to expose the daemon to local web pages (the web dashboard) or remote clients via a Cloudflare tunnel. The bridge listener always enables Bearer auth using a separate token at ~/.eidetic/bridge-token (rotates each restart) and adds CORS headers. (v0.0.31+)