What is Erold
Persistent project memory for AI coding agents. Any new Claude Code session in any project picks up exactly where the last one left off: open tasks, open + resolved bugs (with fix narratives), every deploy, every decision, every credential reference — plus searchable fragments of prior work.
What it is
Section titled “What it is”A three-piece system:
┌─────────────────────────────────┐ ┌──────────────────────────┐│ Claude Code plugin │ │ MCP server ││ (claude-plugin/) │ │ (mcp-server/) ││ - 9 hooks capture passively │◀──▶│ - 18 tools (Phase 0-7) ││ - Local JSONL outbox │ │ - Validates via ││ - Background flush daemon │ │ @erold/shared-types │└──────────────┬──────────────────┘ └────────────┬─────────────┘ │ │ └────────────────┬───────────────────┘ │ HTTPS ▼ ┌─────────────────────────────┐ │ Backend API │ │ (erold-backend/) │ │ - FastAPI + asyncpg │ │ - Postgres 17 + pgvector │ │ - Outbox + embedding │ │ workers │ │ - RLS per tenant │ │ - Live on Scaleway fr-par │ └─────────────────────────────┘Code lives in this monorepo: claude-plugin/ +
mcp-server/ + erold-backend/ +
shared-types/ (the TS schema package they share).
What’s automatic vs explicit
Section titled “What’s automatic vs explicit”| Captured passively (hooks) | Needs explicit call (agent) |
|---|---|
| File edits — paths only, never contents | Architectural Decisions |
| Bash commands — sha, service, exit, duration | Bug fix narratives |
| User prompts — hash + intent class (deploy / bug / refactor / audit) | Deploy outcomes |
| Subagent start/stop | Credential references |
| Compaction checkpoints | Long-form observations the agent wants to surface later |
| Session lifecycle (start, stop, end, notification) |
Hooks return in ~60 ms — they never block the agent. Two redaction layers strip secrets before anything leaves your machine.
The agent gets prompted at every session start (via claude-plugin/CLAUDE.md)
to log the four explicit categories. The get_context() packet returns
a gaps[] array if previous sessions skipped any.
How memory survives sessions
Section titled “How memory survives sessions”- Hook fires → writes one JSON line to
~/.erold/outbox/events.jsonl(atomic <60 ms, never blocks the agent). - Background daemon flushes JSONL to
/v1/events/batchwith idempotency keys +dedup_hash. - Backend’s outbox worker drains
events_outbox, applies Smart-Strip compression → writes afragmentrow. - Embedding worker takes the fragment, runs it through OpenAI
text-embedding-3-small, writes the vector. - Next session: agent calls
get_context()→ server assembles in one transaction: project, active tasks, open + resolved bugs, recent deploys, all decisions, credential refs, ranked next actions, recent fragments. - Agent calls
search()for prior decisions/observations → pgvector HNSW cosine search returns ranked fragments.
Consistency model (by design)
Section titled “Consistency model (by design)”- Strong: Tasks, Bugs, Deploys, Decisions, CredentialReferences — Postgres transactions + row-level security per tenant.
- Eventual (~1–3 s): Fragment semantic search — embedding worker runs asynchronously.
- At-least-once + idempotent: event ingest — client UUIDv4 idempotency
key (72 h window) + server-side SHA-256
dedup_hash(30 min window).
Phase status
Section titled “Phase status”| Phase | What it shipped | Status |
|---|---|---|
| 0 | Security hardening: Keychain auth, redaction, URL allowlist, supply-chain pin | ✅ |
| 1 | Shared-types package + local JSONL outbox + flush daemon (offline-tolerant) | ✅ |
| 2 | Task / Bug / Deploy / Decision / CredentialRef entities + state machines | ✅ |
| 3 | Backend live against Scaleway RDB, ResumePacket end-to-end, session-id binding | ✅ |
| 4 | 30-min content dedup + 1000-event replay acceptance test | ✅ |
| 5 | 8 passive-capture hooks + redaction + tests (24 green) | ✅ |
| 6 | Smart-Strip + pgvector HNSW search + stub embedder for tests | ✅ |
| 7 | Prod Scaleway deploy (RDB + Container + Registry + SM + Gitea CI) | ✅ |
Live: https://eroldapi2093acff-erold-api-prod.functions.fnc.fr-par.scw.cloud
(plus api.erold.dev once the CNAME is set).
Operator surface
Section titled “Operator surface”- Daily ops → OPERATOR_GUIDE.md
- Plugin install → claude-plugin/QUICKSTART.md
- Agent behaviour → claude-plugin/AGENT_PLAYBOOK.md
- Backend deploy → erold-backend/DEPLOY.md
- Full architecture → plans/plugin-mcp-v3.md
Live infrastructure
Section titled “Live infrastructure”| Resource | ID | Cost |
|---|---|---|
Scaleway project erold | 4393b09f-8abe-4336-acae-4870da6033db | free |
RDB erold-db-dev (db-dev-s) | d6560b85-… | ~€6/mo |
RDB erold-db-prod (db-gp-xs HA) | ccd7c08f-… | ~€25/mo |
Serverless Container erold-api-prod (min=1, max=5) | d03ae584-… | ~€14/mo |
Serverless Container erold-api-staging (min=0, max=2) | f6dff64e-… | ~€2/mo |
Container Registry erold + image api:v0.1.0 | — | ~€1/mo |
Object Storage: erold-raw-events, erold-deploy-logs, erold-attachments | — | ~€2/mo |
| Secret Manager: 3 secrets | — | ~€1/mo |
| Total | ~€51/mo |
All RDB endpoints private-only. All buckets BucketOwnerEnforced. All
secrets in Scaleway Secret Manager + macOS Keychain (never .env,
never .mcp.json, never shell history).
Open follow-ups
Section titled “Open follow-ups”- DNS:
api.erold.devCNAME → the.scw.cloudURL. - Staging container: same env-var fix as prod.
- Plugin daemon: migrate POST target from legacy
/logto/v1/events/batchto activate Phase-4 dedup_hash on the wire. - 227 pyright type-annotation cleanup + 154 ruff stylistic (non-blocking).
- 44 stale mcp-server v2-collapse tests to delete.
License + ownership
Section titled “License + ownership”MIT. Self-host or use the SaaS — both are first-class. Code is the same.