Skip to main content

Persistent memory system for AI coding assistants

Project description

MemXCore

English | 中文

Persistent memory system for AI coding assistants. Stores and retrieves memories across sessions via MCP (Model Context Protocol), with semantic search powered by ChromaDB + sentence-transformers.

Works with Claude Code, Cursor, Gemini CLI, and any MCP-compatible tool.


Architecture

RECENT.md          <- L0: raw append log (WAL). Every remember() lands here.
archive/<cat>.md   <- L1: distilled long-term memory, per category, with YAML front matter
USER.md            <- L2: permanent facts (remember(permanent=True)), never compacted
chroma/            <- RAG vector index (rebuilt from archive/ files, lossy-safe)
index.json         <- Keyword search index (tags + summaries from archive/ front matter)

Search tiers (in order):

  1. RAG semantic search (ChromaDB + BM25, RRF fusion) — most accurate, requires chromadb + sentence-transformers
  2. LLM relevance judgment — Claude reads all facts and picks relevant ones, requires API key
  3. Keyword fallback — always available, scans archive files directly

Write flow:

  1. remember(text) -> append to RECENT.md
  2. When RECENT.md exceeds token threshold -> LLM distills into structured facts
  3. Each fact -> written to archive/<category>.md + upserted into ChromaDB (dual-write)

Quick Start

pip install memxcore          # core
pip install 'memxcore[rag]'   # + semantic search (recommended)
pip install 'memxcore[all]'   # everything

# Or from source:
pip install -r memxcore/requirements.txt

Check your setup:

memxcore doctor
# or: python -m memxcore.cli doctor

Requirements: Python 3.11+

LLM API key (any provider supported via litellm):

# Pick one:
export ANTHROPIC_API_KEY=sk-ant-...     # Anthropic (direct API)
export ANTHROPIC_AUTH_TOKEN=xxx         # Anthropic (gateway/proxy, with ANTHROPIC_BASE_URL)
export OPENAI_API_KEY=sk-...            # OpenAI
export GEMINI_API_KEY=...               # Google Gemini
# Or use Ollama for fully local/offline: no key needed, just set model in config.yaml

Without any API key, compaction falls back to basic mode (truncation instead of LLM distillation).

Important: Compaction is not automatic. MemXCore does not detect session boundaries. If compaction is never triggered, memories accumulate in RECENT.md and are not distilled into long-term storage.

Recommended setup (pick one):

  • Use the provided Stop hook (memxcore.hooks.auto_remember) — extracts facts after each response and triggers compaction automatically.
  • Call compact(force=True) via the MCP tool at the end of each session.
  • Run memxcore compact from the command line as a cron job or manual step.

See the Integration section for hook setup examples.

Workspace resolution:

By default, MemXCore resolves the workspace from the module's install location (suitable for development / editable installs). For pip-installed usage, set MEMXCORE_WORKSPACE to your project root:

export MEMXCORE_WORKSPACE=/path/to/your/project

Or in your MCP server config:

{
  "env": { "MEMXCORE_WORKSPACE": "/path/to/your/project" }
}

Configuration (config.yaml)

Located at memxcore/config.yaml. All fields are optional — sensible defaults apply.

compaction:
  strategy: llm             # 'llm' = LLM distills to structured facts (via litellm)
                            # 'basic' = truncate first 50 lines to general.md
  threshold_tokens: 2000    # Trigger compaction when RECENT.md exceeds this
  min_entries: 3            # Don't compact if fewer than N entries in RECENT.md
  check_interval: 5         # Check token count every N remember() calls (reduces I/O)
  stale_minutes: 10         # Auto-compact on search() if RECENT.md older than this

llm:
  model: anthropic/claude-sonnet  # litellm format: provider/model
                                  # Examples: openai/gpt-4o, gemini/gemini-2.5-flash, ollama/llama3
  api_key_env: ANTHROPIC_API_KEY  # Env var name (litellm also auto-reads OPENAI_API_KEY, etc.)
  # base_url:                     # Optional: custom API endpoint (gateway/proxy)

rag:
  embedding_model: all-MiniLM-L6-v2  # sentence-transformers model (80MB, CPU-friendly)
  top_k: 10                           # Max results from semantic search
  rrf_k: 60                           # Reciprocal Rank Fusion constant

watch: false    # Auto-reindex archive/*.md on file change (off by default)

memory:
  categories:
    - id: user_model
      description: "User identity, preferences, communication style, feedback"
    - id: domain
      description: "Transferable domain/technical knowledge  valid across projects"
    - id: project_state
      description: "Active tasks, in-progress decisions  decays within weeks"
    - id: episodic
      description: "Time-bound events and past decisions  has TTL"
    - id: references
      description: "URLs, doc links, dashboards, ticket trackers, Slack channels"

Integration

One-command setup (recommended)

memxcore setup            # auto-detects tools and configures everything
memxcore setup --dry-run  # preview without making changes

Automatically detects and configures:

Tool What it does
Claude Code Registers MCP server, installs hooks (auto-remember + auto-compact), appends agent rules to ~/.claude/CLAUDE.md
Cursor Writes MCP config to ~/.cursor/mcp.json, copies rules to ~/.cursor/rules/memxcore.md
Windsurf Writes MCP config to ~/.codeium/windsurf/mcp_config.json
Codex (OpenAI) Writes MCP config to ~/.codex/config.toml
Gemini CLI Writes MCP config to ~/.gemini/settings.json

After setup, restart your tool and verify the MCP connection.

Manual setup

If you prefer manual configuration, the MCP server config for any tool is:

{
  "mcpServers": {
    "memxcore": {
      "command": "/path/to/your/.venv/bin/python",
      "args": ["-m", "memxcore.mcp_server"],
      "env": { "MEMXCORE_WORKSPACE": "/path/to/your/workspace" }
    }
  }
}

MCP Tools Reference

Tool Args Description
remember text, category?, permanent?, tenant_id? Store a memory
search query, max_results?, tenant_id? Retrieve memories (semantic + keyword)
compact force?, tenant_id? Distill RECENT.md into categorized archives
reindex category?, tenant_id? Rebuild RAG index after manual edits

Categories for remember: user_model / domain / project_state / episodic / references

Permanent memories: Use permanent=True to write directly to USER.md (L2). These are never compacted and always have the highest priority in search. Use for stable facts like core user identity or long-term architectural decisions.


Multi-Tenant

All MCP tools and CLI commands accept an optional tenant_id. Each tenant gets isolated storage under tenants/<tenant_id>/storage/. Omit tenant_id for single-user mode.

# CLI
memxcore --tenant alice search "preferences"

# MCP
search("preferences", tenant_id="alice")

Tenants can also have their own config.yaml override at tenants/<tenant_id>/config.yaml.


CLI Reference

memxcore setup                        # auto-detect tools, configure everything
memxcore setup --dry-run              # preview without changes
memxcore doctor                       # check system readiness
memxcore reindex                      # rebuild RAG index
memxcore compact                      # force distillation
memxcore search "query"               # search memories (debug)
memxcore benchmark                    # search precision benchmark
memxcore mine <path>                  # import conversations
memxcore --tenant alice doctor        # multi-tenant

All commands also work via python -m memxcore.cli <command>.


HTTP API Server (optional)

For development/testing. In production, use the MCP server.

pip install 'memxcore[server]'
python -m memxcore.server --host 127.0.0.1 --port 8000

Endpoints:

POST /remember       { "text": "...", "level": null }
GET  /search?query=  returns List[MemoryResult]
POST /compact        ?force=false
POST /rebuild-rag    rebuild ChromaDB from archive files

Storage Structure

memxcore/
+-- storage/
    +-- RECENT.md              Raw memory log. Cleared after each compaction.
    +-- USER.md                Permanent facts (permanent=True). Never compacted.
    +-- index.json             Keyword search index. Auto-rebuilt after compaction.
    +-- chroma/                ChromaDB vector index. Rebuildable from archive/.
    +-- archive/
        +-- user_model.md      User identity, preferences, feedback
        +-- domain.md          Domain/technical knowledge
        +-- project_state.md   Active tasks, decisions (stale after weeks)
        +-- episodic.md        Past events and decisions
        +-- references.md      URLs, doc links, external pointers
        +-- general.md         Fallback when LLM distillation unavailable

Archive file format:

---
topic: project_state
tags: [api, testing]
last_distilled: 2026-04-07T14:23:01
confidence_level: 4
---

## [2026-04-07T14:23:01]

Unit test initiative complete: 234 tests passing across 9 packages.

Archive files are plain Markdown — edit them directly. After editing, run memxcore reindex <category> to update the RAG index.


Security Considerations

Storage permissions: Memory files (storage/, knowledge.db) are created with default OS permissions (typically 0644). On shared/multi-user systems, restrict access manually:

chmod 700 memxcore/storage/

HTTP server: The optional HTTP API (memxcore.server) has no authentication and is intended for local development only. Do not expose it to a network. It binds to 127.0.0.1 by default — never change this to 0.0.0.0 in production.

memxcore mine command: Reads any file the user specifies. This is by design (same as cat), but be careful not to pipe untrusted paths into it if used in scripts.

LLM prompt injection: Like all LLM-based systems, stored memory content is passed to the LLM during distillation and search. Malicious content in memories could influence LLM outputs. Category names from LLM responses are sanitized to prevent path traversal, but fabricated memory content is a fundamental limitation of LLM-based extraction.

Dependency versions: Core dependencies use >= pins without upper bounds. For production deployments, use a lock file (pip freeze > requirements.lock) to pin exact versions.


Troubleshooting

Run memxcore doctor first — it checks everything and tells you what to fix.

RAG not working

pip install 'memxcore[rag]'
# First run downloads the embedding model (~80MB) + torch (~500MB)

LLM distillation falling back to basic

echo $ANTHROPIC_API_KEY   # must be set
# Without API key, memories go to archive/general.md (uncategorized)

Rebuild RAG index

memxcore reindex

License

MIT. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

memxcore-0.1.1.tar.gz (64.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

memxcore-0.1.1-py3-none-any.whl (70.4 kB view details)

Uploaded Python 3

File details

Details for the file memxcore-0.1.1.tar.gz.

File metadata

  • Download URL: memxcore-0.1.1.tar.gz
  • Upload date:
  • Size: 64.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for memxcore-0.1.1.tar.gz
Algorithm Hash digest
SHA256 118bc012cf891dbfa38dd0bee5dcc29b5d24bb93a2c1381ac33d034c4b3e1c5a
MD5 1c22cee4bf273114f5511d81c644e2d4
BLAKE2b-256 4df605b80d53b8aee988778400abc1caeea317ed6a6d8f19ca1ea16f0d0b8c70

See more details on using hashes here.

Provenance

The following attestation bundles were made for memxcore-0.1.1.tar.gz:

Publisher: workflow.yml on Danny0218/memxcore

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file memxcore-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: memxcore-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 70.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for memxcore-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 642b21b9b46a6fdc7704416a6977a15a9b116c7f30d44a8be743085bc90c9bef
MD5 6d63de7bfc281e3583afbf8ad39b4793
BLAKE2b-256 42f3a93072e9cfea055a9d18dbe51cfc82348c0f026927522f4b144429a591f4

See more details on using hashes here.

Provenance

The following attestation bundles were made for memxcore-0.1.1-py3-none-any.whl:

Publisher: workflow.yml on Danny0218/memxcore

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page