ctxmem
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ctxmemrecall the decision about the database schema"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
ctxmem
Git-native, shareable project memory for AI coding agents โ fully local, no cloud.
ctxmem gives your project a permanent, searchable memory that lives inside the
repo. AI agents (and you) can store decisions and recall relevant context on
demand, so nothing is forgotten when a chat exceeds the model's context window.
๐ง Remembers โ decisions, notes, sessions + your code, in a searchable index.
๐ค Shareable โ the memory is a text file committed to git. You commit, your colleague pulls, and they have your exact context. Branch-aware for free.
๐ฆ Works as a git package โ
pip install git+https://โฆ, zero required deps.๐ Fully local โ SQLite files in your repo. No cloud, no API keys, no servers.
๐ Search modes โ
keyword(built-in) plussemantic/hybrid(๐งช beta, local embeddings).
๐ Table of contents
Related MCP server: LumenCore
๐ฏ 1. The problem it solves
Large language models have a finite context window (e.g. 200K tokens). When a session grows past it, the model "forgets" decisions, files it read, and the project's conventions. Worse, that context is trapped in one chat: it isn't shared with teammates, and it has no notion of what changed between branches.
The fix is not to make the window bigger. It is to keep the memory outside the model and feed back only the few relevant pieces when needed.
Principle: the context window is a cache, not storage. The truth lives in an external, searchable index.
๐ก 2. The core idea
Two files under .ctxmem/ in your repo:
.ctxmem/
โโโ memory.jsonl # SOURCE OF TRUTH โ committed to git.
โ # Append-only, human-readable, one JSON object per line.
โ # Holds your decisions / notes / sessions.
โ
โโโ index.db # DERIVED index โ gitignored, rebuilt on demand.
# SQLite full-text (FTS5) + optional vector table.
# Holds a searchable copy of memory.jsonl PLUS your code symbols.Why this split is the whole trick:
memory.jsonlis text in the repo โ it versions, diffs, and merges like any file. Switch branch โ the memory changes with it. Push โ your teammate gets it.index.dbis disposable โ anyone can rebuild it frommemory.jsonl+ the code on disk. So we never commit a binary; we commit readable history.
๐ 3. How it works (data flow)
flowchart TD
A[You / AI agent] -->|ctxmem remember| B[memory.jsonl<br/>source of truth, git-committed]
C[Your source code] -->|ctxmem sync| D[indexer: tree of symbols]
B -->|ctxmem sync| E[index.db<br/>SQLite FTS5 + vectors]
D --> E
A -->|ctxmem recall query| F{search mode}
F -->|keyword| G[FTS5 full-text]
F -->|semantic ๐งช| H[Ollama embed + sqlite-vec KNN]
F -->|hybrid ๐งช| I[merge both]
G --> E
H --> E
I --> E
E -->|top results| AWrite:
rememberappends a JSON line tomemory.jsonl(and updates the index).Index:
syncrebuildsindex.db= replaymemory.jsonl+ scan the code for symbols (functions/classes) + optionally compute embeddings.Read:
recallsearches the index in the configured mode and returns the best matches โ the small, relevant slice you (or the agent) actually need.
๐๏ธ 4. Project structure
ctxmem/
โโโ pyproject.toml # Package metadata, CLI entry points, optional extras.
โโโ README.md # This file.
โโโ LICENSE # MIT.
โโโ .gitignore # Ignores venv, build artifacts, and .ctxmem/index.db.
โ
โโโ src/ctxmem/ # The Python package.
โ โโโ __init__.py # Package version marker.
โ โโโ gitinfo.py # Reads current git branch + commit (so memory is
โ โ # tagged with the context it was created in).
โ โโโ store.py # Storage layer: paths, config, the SQLite/FTS5 schema,
โ โ # insert/append/search/read helpers.
โ โโโ indexer.py # Scans source files and extracts code "symbols"
โ โ # (functions/classes) into searchable chunks.
โ โโโ embeddings.py # ๐งช beta: talks to Ollama for embeddings and to
โ โ # sqlite-vec for vector KNN search.
โ โโโ retrieval.py # The brain: rebuilds the index and dispatches a query
โ โ # to keyword / semantic / hybrid (with auto-fallback).
โ โโโ bench.py # Token-savings benchmark + SVG chart generation.
โ โโโ cli.py # The `ctxmem` command line (init, remember, recall, โฆ).
โ โโโ mcp_server.py # Exposes ctxmem to AI agents via the MCP protocol.
โ
โโโ example/
โ โโโ sample_app.py # A tiny module so there is real code to index/recall.
โ โโโ bench/ # A sample generated benchmark report + charts.
โ
โโโ ollama/ # ๐งช beta: run the semantic backend in an isolated VM.
โ โโโ lima.yaml # Lima VM: Ubuntu + Ollama + the embedding model.
โ โโโ Taskfile.yaml # `task start/stop/status/demo` helpers for the VM.
โ
โโโ .ctxmem/ # Created by `ctxmem init` in whatever repo you use it in.
โโโ memory.jsonl # Committed source of truth.
โโโ config.json # Committed: which search mode + model to use.
โโโ .gitignore # Keeps index.db out of git.
โโโ index.db # Derived, local-only search index.The modules in plain words
File | Responsibility | Key functions |
| Know which branch/commit we're on. |
|
| Read/write files + SQLite. Defines the FTS5 table. |
|
| Turn code files into searchable symbol chunks. |
|
| Beta: local embeddings (Ollama) + vector KNN (sqlite-vec). |
|
| Rebuild the index; pick keyword/semantic/hybrid; fallback. |
|
| Measure token / request savings; render SVG charts. |
|
| The user-facing commands. | one |
| The agent-facing tools over MCP. |
|
Both cli.py and mcp_server.py are thin: they call into retrieval.py, which
calls store.py, indexer.py, and (optionally) embeddings.py. One brain, two
front-ends.
๐ฅ 5. Install
# from a clone
pip install -e .
# as a git package (this is the "works as a git package" part)
pip install "git+https://github.com/DoppiaG93/ctxmem.git"
# with optional extras
pip install "ctxmem[mcp]" # AI-agent server (MCP)
pip install "ctxmem[semantic]" # ๐งช beta semantic search (sqlite-vec; needs Ollama too)
pip install "ctxmem[all]" # everythingRequires Python 3.8+ with FTS5 (bundled in virtually every sqlite3 build).
The base install has zero third-party dependencies.
๐ 6. Quick start (5 minutes)
cd your-project
ctxmem init # creates .ctxmem/
ctxmem remember --type decision \
--title "Auth via JWT" --tags auth,security \
"We chose stateless JWT over server sessions for horizontal scaling."
ctxmem sync # also index your code
ctxmem recall "how do we handle authentication" # ask in plain language
ctxmem recall "cart" --type symbol # search only code symbols
ctxmem log # recent memories
ctxmem status # what's indexedThen commit the memory so it's shared:
git add .ctxmem/memory.jsonl .ctxmem/config.json
git commit -m "chore: seed project memory"๐งญ 7. Full walkthrough (install, agent, colleague)
A complete, realistic story: you have your own package/codebase, you add ctxmem, the AI agent starts remembering, and you hand the memory to a colleague.
First, the key question up front:
Do I type commands by hand, or is it automatic? Both โ there are three levels, and you choose how much to automate:
What
Who does it
How
Index the code
automatic
the git hook runs
ctxmem syncon every commitRecord a decision
you or the agent
you run
ctxmem remember, or the AI calls therememberMCP tool for youRecall context
you or the agent
you run
ctxmem recall, or the AI calls therecallMCP toolThe code index maintains itself. Decisions are written either by you (one command) or automatically by the agent once you wire up MCP + a short instruction telling it to do so (Step 4 below).
Step 1 โ Add ctxmem to your codebase (once)
cd ~/code/my-awesome-package # your existing repo
pip install "git+https://github.com/DoppiaG93/ctxmem.git" # or: pip install -e ../ctxmem
ctxmem init # creates .ctxmem/ (keyword mode by default)
ctxmem hook install # auto-rebuild the index after every commit
ctxmem sync # first index of your existing codeWhat just happened:
.ctxmem/memory.jsonl(empty for now) +.ctxmem/config.jsonwere created.A
post-commithook now keeps the code index up to date by itself.Your code is already searchable: try
ctxmem recall "database connection".
Step 2 โ Seed a few decisions (you, one line each)
Write down the things you'd want a new teammate (or a fresh AI session) to know:
ctxmem remember --type decision --title "HTTP client" \
"We use httpx (async) everywhere; do not add requests."
ctxmem remember --type decision --title "DB" --tags db \
"Postgres via SQLAlchemy 2.0; migrations with Alembic."
ctxmem remember --type note --title "Gotcha" \
"The worker must run with TZ=UTC or scheduling breaks."Check them: ctxmem log.
Step 3 โ Commit the memory so it can be shared
git add .ctxmem/memory.jsonl .ctxmem/config.json
git commit -m "chore: seed project memory"
git pushOnly the source of truth (memory.jsonl) and config are committed. The
index.db stays local (gitignored) and is rebuilt on demand.
Step 4 โ Let the AI agent remember on its own (optional but powerful)
So far you typed the commands. To make the agent do it automatically, give it the MCP tools plus a one-time instruction.
Register the MCP server โ create
.vscode/mcp.jsonin your repo:
{
"servers": {
"ctxmem": {
"command": "ctxmem-mcp",
"env": { "CTXMEM_ROOT": "${workspaceFolder}" }
}
}
}(Install the extra once: pip install "ctxmem[mcp]".)
Tell the agent when to use them โ create
.github/copilot-instructions.md:
# Project memory
This repo has a ctxmem memory. Before starting a task, call the `recall` tool
with a short description of the task to load relevant decisions and code.
When you make or confirm an important decision, call the `remember` tool
(type: decision) so it is saved for future sessions and teammates.Now, in a normal chat, the agent will:
call
recallat the start โ it "remembers" past decisions without you pasting them;call
rememberwhen it decides something โ the memory grows by itself.
You can still use the CLI anytime; the agent and you write to the same memory.
Step 5 โ Your colleague gets the exact same context
git clone https://github.com/DoppiaG93/my-awesome-package && cd my-awesome-package
pip install "git+https://github.com/DoppiaG93/ctxmem.git" # or your normal env setup
ctxmem hook install # one-time: git doesn't share hooks, so each dev installs it
ctxmem recall "which HTTP client do we use"
# [decision] HTTP client
# We use httpx (async) everywhere; do not add requests.They never ran remember โ they simply pulled your memory.jsonl. The first
recall rebuilt their local index.db automatically. If they use VS Code, the
.vscode/mcp.json and .github/copilot-instructions.md are already in the repo,
so their agent starts remembering too.
Two one-time, per-machine steps that git can't do for you:
pip installctxmem, andctxmem hook install(git hooks live in.git/, which isn't pushed). Everything else travels in the repo.
Recap: what's manual vs automatic
Automatic: code indexing (git hook), index rebuild on
recall, and โ once Step 4 is set up โ the agent recalling and recording decisions.Manual (optional): writing decisions yourself with
ctxmem remember, and the two per-machine setup commands above.
๐ 8. Commands reference
Command | What it does |
| Create |
| Store a memory (โ |
| Search memory + code. |
| Rebuild |
| Show, or switch to, |
| List recent memories. |
| Branch/commit, mode, and counts of indexed items. |
| Add/remove a git post-commit auto-sync hook. |
| Wire up Copilot/agents: write the memory protocol into |
| Measure token savings and premium-request savings: |
| Run against a repo other than the current directory. |
Measuring token savings (bench)
ctxmem bench quantifies the whole point of the tool: instead of pasting whole
files (or the whole repo) into the model, you inject only the relevant recall
snippets. It reports two things โ the context tokens you feed the model
and the number of premium requests (agent round-trips) the answer costs.
ctxmem bench "how is a marker structured" # snippets vs whole referenced files
ctxmem bench "how is a marker structured" --baseline repo # snippets vs the entire codebase
ctxmem bench "versioning" --baseline memory --type note # snippets vs the whole memory.jsonl without ctxmem : 21306 tokens
with ctxmem : 1526 tokens
saved : 19780 tokens (92.8%)
reduction : 14.0x smaller
premium requests (estimated agent round-trips)
without ctxmem : 6 (1 orient + 5 file reads)
with ctxmem : 1 (single recall)
saved : 5 (6.0x fewer)Baselines: files (default โ full text of the files behind the results),
memory (the whole memory.jsonl), repo (all indexed code + memory). Test
files are excluded from the baseline by default (--include-tests to keep
them), because a real agent would not paste whole test suites to answer a
question. Token counts use tiktoken when installed
(pip install "ctxmem[bench]"), otherwise a portable ~chars/4 estimate (the
label shows which was used).
Run a whole suite of questions and generate a shareable report with charts:
ctxmem bench --suite questions.txt --baseline files --report bench-out
# writes bench-out/report.md, bench-out/bench_tokens.svg, bench-out/bench_requests.svg๐ 9. Benchmark โ how it was tested
The claim "ctxmem saves tokens and premium requests" is not hand-waving โ it is measured on a real, third-party codebase and fully reproducible.
Setup
Repo under test: the Django source tree (~2,900 Python files, ~45k indexed symbols) โ a large, independent codebase to avoid any home-field advantage.
Questions: 15 real "onboarding" questions a developer would ask (QuerySet, URL routing, model fields, form validation, middleware, auth, migrations, signals, ORM manager, admin, sessions, WSGI, model forms). See
example/bench_questions_django.txt."Without ctxmem" baseline: the full text of the relevant source files an agent would otherwise open โ test files excluded, because dumping entire test suites overstates the naive cost.
"With ctxmem": only the snippets a single
ctxmem recallreturns.Tokenizer:
tiktoken/cl100k_base(the GPT-4 / Copilot family).
Results
Metric | Without ctxmem | With ctxmem | Improvement |
Context tokens (13 answerable questions) | 272,354 | 14,028 | 19.4ร smaller (94.8%) |
Premium requests (agent round-trips) | 49 | 13 | 3.8ร fewer |
Context tokens per question:
Premium requests per question (billed per model round-trip, not per token โ
without stored memory the agent orients itself and then opens each relevant file;
ctxmem returns every snippet in one recall):
Reproduce it yourself
git clone https://github.com/django/django ~/bench-django
cd ~/bench-django
pip install "ctxmem[bench]"
ctxmem init && ctxmem sync # index the repo (~seconds)
ctxmem bench --suite /path/to/bench_questions_django.txt \
--baseline files --report bench-outHonest reading of these numbers
The token figure is the context you feed the model, not a Copilot bill. Token savings translate directly into money on token-billed APIs (OpenAI/Anthropic) and into more headroom under the context-window limit.
For a GitHub Copilot subscription (billed in premium requests), the lever is the right-hand chart: fewer exploration round-trips per question.
Not every query wins big โ small files or broad questions save less, and the suite includes those too. The report is generated as-is, no cherry-picking.
๐ 10. Search modes: keyword vs semantic vs hybrid
Mode | Finds results by | Needs | Speed | Default |
| matching words (SQLite FTS5) | nothing | instant | โ |
| matching meaning (embeddings) | sqlite-vec + Ollama | a bit slower | โ |
| both, results merged | sqlite-vec + Ollama | a bit slower | โ |
๐งช
semanticandhybridare beta โ the local-embedding backend is experimental and under active testing.keywordmode is stable and needs no setup. If the semantic backend isn't available, ctxmem automatically falls back to keyword and tells you ([keyword (fallback)]).
keyword: great, zero-setup baseline. Searching
"login"won't find a note that only says"authentication".semantic ๐งช: understands meaning, so
"login"does find"authentication". Uses a local embedding model โ no cloud.hybrid ๐งช: runs both and merges โ best recall.
The mode is stored in .ctxmem/config.json (so it's shared).
ctxmem init --mode hybrid
ctxmem mode # show current mode + backend availability
ctxmem mode semantic # switch (beta)
ctxmem recall "auth" --mode keyword # override for one query๐ค 11. Sharing with your team
The memory travels through git like code:
# you
ctxmem remember --type decision "Payments go through Stripe, not PayPal."
git add .ctxmem/memory.jsonl && git commit -m "memory: payments" && git push
# your colleague
git pull
ctxmem recall "payments" # index rebuilds from memory.jsonl โ same contextBecause memory.jsonl is a normal file:
Branch-aware: each branch carries its own decisions; switch branch and
recallreflects it.Merge-friendly: append-only lines merge cleanly; conflicts are rare and readable.
No server: nothing to host, nothing to sync โ git is the transport.
๐ช 12. Auto-sync with a git hook
Keep the index fresh automatically:
ctxmem hook install # writes .git/hooks/post-commit
ctxmem hook uninstallAfter every git commit, the index rebuilds so recall always reflects the
latest code and decisions. The hook uses your exact Python interpreter, so it
works from inside a virtualenv.
๐ค 13. Use it from an AI agent
There are two ways to connect an agent (e.g. GitHub Copilot) to the memory. They are independent โ use whichever your setup allows.
Option A โ instructions + CLI (recommended, no MCP needed)
The agent already runs terminal commands, so it can drive the ctxmem CLI
directly. You just tell it when to recall and remember via an instructions
file. This works even when MCP is unavailable or disabled by policy.
Set it up in one command from your repo root:
ctxmem agent-init # writes/updates .github/copilot-instructions.md
ctxmem agent-init --mcp # also drop a .vscode/mcp.json (for Option B)This inserts a Project Memory Protocol between managed markers
(<!-- ctxmem:begin --> โฆ <!-- ctxmem:end -->). It is idempotent: if the
file already exists it appends the section; re-running updates that section in
place without duplicating it or touching your other instructions.
The protocol tells the agent to, on every task:
run
ctxmem recall "<the request>"first, to load relevant context;run
ctxmem remember โฆwhenever it explains a non-trivial part of the code or makes a decision โ as a mandatory end-of-turn self-check;run
ctxmem syncafter changing code.
Requirements & tips:
ctxmemmust be on PATH in the terminal the agent uses. If you installed it in a venv, expose it globally, e.g.ln -s "$(command -v ctxmem)" ~/.local/bin/.Use the agent in a mode that can run terminal commands (VS Code Copilot Agent mode). Choose "Always allow" for
ctxmemto remove friction.Start a new chat after
agent-initso the updated instructions load.Reality check: LLMs are probabilistic โ a strong, imperative protocol makes proactive saving reliable, not guaranteed. For 100% determinism, save explicitly (ask the agent, or run
ctxmem rememberyourself) or via the git hook.
Option B โ MCP server
ctxmem also ships an MCP server so agents can
call the memory as native tools. MCP is an open standard (MIT-licensed SDKs);
the server runs locally and reads only your repo.
pip install "ctxmem[mcp]"Register it (VS Code .vscode/mcp.json, also created by agent-init --mcp):
{
"servers": {
"ctxmem": {
"command": "ctxmem-mcp",
"env": { "CTXMEM_ROOT": "${workspaceFolder}" }
}
}
}If
ctxmem-mcpisn't on the global PATH (e.g. it lives in a venv), use the absolute path to the binary ascommand.
Tools exposed to the agent:
recall(query, limit, type, mode)โ pull relevant context before a task.remember(content, type, title, tags)โ record a decision when done.memory_status()โ mode, branch/commit, index counts.
The pattern (both options): the agent calls recall at the start of a task
(injecting only the relevant snippets, staying well under the token limit) and
remember at the end โ so the project's memory grows and persists across sessions.
๐งช 14. Semantic backend with Ollama (beta)
โ ๏ธ Beta / experimental. Semantic search works but is under active testing. Keyword mode remains the stable default. Expect the semantic setup and defaults to evolve in a future release.
Semantic search needs two open-source, fully-local pieces:
Ollama runs an embedding model on your machine (offline, no API key). We use the small
nomic-embed-textmodel.sqlite-vec stores the vectors and does nearest-neighbor search inside SQLite (a single loadable extension, no server).
Option A โ install Ollama on the host
pip install "ctxmem[semantic]"
# install Ollama from https://ollama.com, then:
ollama pull nomic-embed-text
ctxmem mode semanticOption B โ run Ollama in an isolated Lima VM
Keeps Ollama off the host. Guest port 11434 is forwarded to the host, so ctxmem
(default ollama_url = http://localhost:11434) needs no extra config.
cd ollama
task start # create VM, install Ollama, pull nomic-embed-text
task status # verify the endpoint responds
task demo # ctxmem mode semantic + a real query
task stop # or: task delete (fully reversible)ollama/lima.yaml provisions Ubuntu 24.04, installs Ollama as a systemd service,
pulls the model, and includes a readiness probe. ollama/Taskfile.yaml wraps the
lifecycle in task commands.
โ 15. FAQ
Is my data sent anywhere? No. Everything is local: SQLite files in your repo and, if you enable the beta semantic mode, a local Ollama. The MCP server also runs locally.
Do I have to use embeddings? No. keyword mode needs nothing and is the
default. Semantic is opt-in and still in beta.
Should I commit index.db? No โ it's derived and gitignored. Commit
memory.jsonl and config.json.
What if a teammate doesn't have Ollama? ctxmem falls back to keyword automatically; the shared memory still works.
Does it scale to a big repo? The keyword index is fine for large repos.
Embeddings cost one Ollama call per chunk on sync; for very large codebases
incremental (diff-based) indexing is a natural next step.
Is MCP proprietary? No. MCP is an open protocol with MIT-licensed SDKs. The underlying LLM behind your agent may be proprietary, but the memory and the protocol here are fully open and self-hosted.
๐ค 16. Contributing
Contributions are welcome! This project follows the Git Flow branching model
(feature/*, bugfix/*, hotfix/* โ develop โ main). Before opening a pull
request, please read the Contributing guide โ it covers
branch naming, commit conventions, labels, milestones, and the release process.
๐ 17. License
Released under the MIT License.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/DoppiaG93/ctxmem'
If you have feedback or need assistance with the MCP directory API, please join our Discord server