Continuous Evolving Memory System
Persistent memory for AI coding assistants. Store, retrieve, and evolve memories to make Claude Code and Cursor smarter over time.
You need two things from your CEMS admin: a server URL and an API key.
curl -fsSL https://getcems.com/install.sh | bashIt will ask for your API URL and key interactively.
CEMS_API_KEY=your-key-here CEMS_API_URL=https://cems.example.com \
curl -fsSL https://getcems.com/install.sh | bashgit clone https://github.com/chocksy/cems.git && cd cems
./install.sh- Installs uv if missing
- Installs the CEMS CLI (
cems,cems-server,cems-observer) viauv tool install - Runs
cems setup --claudewhich:- Copies 6 hook scripts to
~/.claude/hooks/ - Copies 5 skill files to
~/.claude/skills/cems/ - Merges CEMS config into
~/.claude/settings.json(preserves existing settings) - Saves credentials to
~/.cems/credentials(chmod 600)
- Copies 6 hook scripts to
cems --version # Verify CLI is installed
cems health # Check server connection
cems update # Pull latest version + re-deploy hooks/skills
cems setup # Re-run setup (reconfigure credentials, re-install hooks)
cems uninstall # Remove hooks/skills (keeps credentials by default)CEMS auto-updates when you start a new Claude Code session — no action needed. If your install is more than 24 hours old, the SessionStart hook pulls the latest version in the background.
To update manually:
cems update # Pull latest + re-deploy hooks/skills
cems update --hooks # Re-deploy hooks only (skip package upgrade)Auto-update can be disabled by setting CEMS_AUTO_UPDATE=0 in your environment or ~/.cems/credentials.
Stored in ~/.cems/credentials (chmod 600). Checked in order:
- CLI flags:
--api-url,--api-key - Environment:
CEMS_API_URL,CEMS_API_KEY - Credentials file:
~/.cems/credentials
CEMS hooks into your IDE (Claude Code or Cursor) and provides persistent memory across sessions:
- Memory Injection -- On every prompt, the
UserPromptSubmithook searches your memories and injects relevant context - Session Learning -- On session end, the
Stophook extracts learnings from your session and stores them - Observational Memory -- The observer daemon watches session transcripts and extracts high-level observations about your workflow
- Scheduled Maintenance -- Nightly/weekly/monthly jobs deduplicate, compress, and prune memories automatically
~/.claude/
├── settings.json # Hooks config (merged, not overwritten)
├── hooks/
│ ├── cems_session_start.py # Profile + context injection
│ ├── cems_user_prompts_submit.py # Memory search + observations
│ ├── cems_post_tool_use.py # Tool learning extraction
│ ├── cems_pre_tool_use.py # Gate rules enforcement
│ ├── cems_stop.py # Session analysis + observer
│ ├── cems_pre_compact.py # Pre-compaction hook
│ └── utils/ # Shared utilities
└── skills/
└── cems/
├── remember.md # /remember - Add personal memory
├── recall.md # /recall - Search memories
├── share.md # /share - Add team memory
├── forget.md # /forget - Delete memory
└── context.md # /context - Show status
~/.cems/
└── credentials # API URL + key (chmod 600)
/remember I prefer Python for backend development
/remember The database uses snake_case column names
/recall What are my coding preferences?
/share API endpoints follow REST conventions with /api/v1/...
/forget abc123
/context
cems status # System status
cems health # Server health check
cems add "I prefer dark mode" # Add a memory
cems search "coding preferences" # Search memories
cems list # List all memories
cems rule add # Interactive constitution/playbook rule wizard
cems rule load --kind constitution # Load default constitution rule bundle
cems update # Update to latest version
cems update --hooks # Re-deploy hooks only (no package upgrade)
cems maintenance --job consolidation # Run maintenance
cems uninstall # Remove hooks/skills
cems uninstall --all # Remove everything including credentialsFor team usage, deploy CEMS as a server. Requires Docker Compose.
| Service | Image | Port | Purpose |
|---|---|---|---|
| postgres | pgvector/pgvector:pg16 |
5432 | PostgreSQL + pgvector (vectors + metadata + auth) |
| cems-server | Built from Dockerfile |
8765 | Python REST API (Starlette + uvicorn) |
| cems-mcp | Built from mcp-wrapper/ |
8766 | MCP wrapper (Express.js, Streamable HTTP) |
-
Clone and configure:
git clone https://github.com/chocksy/cems.git && cd cems cp .env.example .env # Edit .env with your OPENROUTER_API_KEY and CEMS_ADMIN_KEY
-
Start services:
docker compose up -d
-
Create your first user:
source .env curl -X POST http://localhost:8765/admin/users \ -H "Authorization: Bearer $CEMS_ADMIN_KEY" \ -H "Content-Type: application/json" \ -d '{"username": "yourname"}' # Returns: {"api_key": "cems_usr_abc123..."}
-
Give the API key to your team member -- they run the client install above.
Required (set in .env):
| Variable | Description |
|---|---|
OPENROUTER_API_KEY |
Get from https://openrouter.ai/keys |
CEMS_ADMIN_KEY |
Generate with openssl rand -hex 32 |
Optional:
| Variable | Default | Description |
|---|---|---|
POSTGRES_PASSWORD |
cems_secure_password |
Change in production |
CEMS_EMBEDDING_BACKEND |
openrouter |
Embedding provider |
CEMS_EMBEDDING_DIMENSION |
1536 |
Embedding dimension |
CEMS_RERANKER_BACKEND |
disabled |
Reranker (disabled by default) |
Everything lives in PostgreSQL with pgvector:
memory_documents-- Documents with content, user/team scoping, categories, tags, soft-deletememory_chunks-- Chunked content with 1536-dim vector embeddings (HNSW index) and full-text search (tsvector)users/teams-- Authentication via bcrypt-hashed API keys
text-embedding-3-small via OpenRouter (1536 dimensions). Batch support for bulk operations.
CEMS uses a 9-stage retrieval pipeline:
Query → Understanding → Synthesis → HyDE → Retrieval → RRF Fusion → Filtering → Scoring → Assembly → Results
| Stage | What it does |
|---|---|
| 1. Query Understanding | LLM routes to vector or hybrid strategy |
| 2. Query Synthesis | LLM expands query into 2-5 search terms |
| 3. HyDE | Generates hypothetical ideal answer for better matching |
| 4. Candidate Retrieval | pgvector HNSW (vector) + tsvector (BM25 full-text) |
| 5. RRF Fusion | Reciprocal Rank Fusion combines result lists |
| 6. Relevance Filtering | Removes results below threshold |
| 7. Scoring Adjustments | Time decay, priority boost, project-scoped boost |
| 8. Token-Budgeted Assembly | Greedy selection within token budget (default: 2000) |
Search modes: vector (fast, 0 LLM calls), hybrid (thorough, 3-4 LLM calls), auto (smart routing).
Scheduled via APScheduler:
| Job | Schedule | Purpose |
|---|---|---|
| Consolidation | Nightly 3 AM | Merge semantic duplicates (cosine >= 0.92) |
| Observation Reflection | Nightly 3:30 AM | Condense observations per project |
| Summarization | Weekly Sun 4 AM | Compress old memories, prune stale |
| Re-indexing | Monthly 1st 5 AM | Rebuild embeddings, archive dead memories |
The observer (cems-observer) runs as a background process on the client machine:
- Polls
~/.claude/projects/*/JSONL transcript files every 30 seconds - When 50KB of new content accumulates, sends it to the server
- Server extracts high-level observations via Gemini 2.5 Flash
- Observations like "User deploys via Coolify" or "Project uses PostgreSQL" are stored as memories
The MCP wrapper on port 8766 exposes CEMS as an MCP server with 6 tools:
| Tool | Description |
|---|---|
memory_add |
Store a memory |
memory_search |
Search with the full retrieval pipeline |
memory_forget |
Delete or archive a memory |
memory_update |
Update memory content |
memory_maintenance |
Trigger maintenance jobs |
session_analyze |
Analyze session transcripts |
Full API reference
Public API (Bearer token auth):
| Method | Endpoint | Purpose |
|---|---|---|
| POST | /api/memory/add |
Add a memory |
| POST | /api/memory/search |
Search memories |
| POST | /api/memory/forget |
Delete memory |
| POST | /api/memory/update |
Update memory |
| POST | /api/memory/log-shown |
Feedback tracking |
| POST | /api/memory/maintenance |
Run maintenance |
| GET | /api/memory/list |
List memories |
| GET | /api/memory/status |
System status |
| GET | /api/memory/profile |
Session profile context |
| GET | /api/memory/gate-rules |
Gate rules by project |
| POST | /api/session/summarize |
Session summary (observer daemon) |
| POST | /api/tool/learning |
Tool learning |
| POST | /api/index/repo |
Index git repo |
Admin API (CEMS_ADMIN_KEY auth):
| Method | Endpoint | Purpose |
|---|---|---|
| GET/POST | /admin/users |
List/create users |
| GET/PATCH/DELETE | /admin/users/{id} |
Manage user |
| POST | /admin/users/{id}/reset-key |
Reset API key |
| GET/POST | /admin/teams |
List/create teams |
- Check credentials:
cat ~/.cems/credentials - Test connection:
cems health - Test search:
cems search "test" - Check hook output:
echo '{"prompt": "test"}' | uv run ~/.claude/hooks/cems_user_prompts_submit.py
- Verify:
ls ~/.claude/skills/cems/ - Restart Claude Code
- Type
/and look forremember,recall, etc.
cems setup # Re-runs the full setupgit clone https://github.com/chocksy/cems.git && cd cems
uv pip install -e ".[dev]"
pytest # Run tests
mypy src/cems # Type checkingMIT
