If you use more than one AI coding agent β say, Claude Code for some work and Codex CLI for other tasks β you've probably run into this:
Each agent's session history lives in its own format, in its own directory, invisible to every other tool. Switching agents means switching to a different "island" of memory.
I built memcp, an open-source tool that solves this: it captures session logs from multiple AI coding agents, stores them in one local SQLite database, and exposes them to any connected agent via MCP (Model Context Protocol) β so an agent can search work done by a different agent, in a different tool, and get a correct answer.
https://github.com/nnyannya-tech/memcp
An agent's session ends
β (automatically)
βΌ
Log gets parsed and normalized
β
βΌ
Stored in a local SQLite DB (full-text search via FTS5)
β
βΌ
Any connected agent can search it later, via MCP
All data stays on your machine β no cloud sync, no telemetry. Each agent gets its own log format handled by a small parser that normalizes it into a shared schema (session, message, tool call):
ParseFn = Callable[[Path], tuple[Session, list[Message], list[ToolCall]]]
Adding support for a new agent means writing one function with that signature. That's the whole extension point.
memcp exposes four MCP tools that any connected agent can call:
| Tool | Description |
|---|---|
search_memory(query, limit) |
|
| Full-text search across all past sessions, from any source | |
read_session(session_id, query, max_messages) |
|
| Read a specific session's transcript, optionally filtered | |
list_recent_sessions(limit) |
|
| List sessions in reverse chronological order | |
ingest_session(path) |
|
| Manually ingest a specific log file |
Here's the part I'm actually excited about. Claude Code and Codex CLI are built by different vendors, store session logs in completely different formats, and have entirely different mechanisms for registering MCP servers. Getting them to share one memory store meant writing a dedicated parser for Codex CLI's rollout-style JSONL logs, normalizing it to the same schema Claude Code's logs use, and extending memcp setup
to wire up both agents' MCP registration in one command.
The result looks like this in practice:
ββ A Claude Code session, a few days ago ββ
User: How did we implement JWT refresh token rotation for the auth service?
Claude: We used a sliding-window approach with Redis for token revocation.
(session ends here)
ββ Today, starting a fresh Codex CLI session ββ
User: How did we handle JWT refresh token rotation again?
Codex: [calls search_memory("JWT refresh token rotation")]
Found it β a Claude Code session from a few days ago.
You used a sliding-window approach with Redis for revocation.
Want me to pull up the implementation details?
A completely different vendor's tool correctly recalling work it never did, from a session it was never part of. Seeing this actually work end-to-end was the most satisfying part of building this β the daily friction of re-explaining context every time you switch agents just disappears.
One setup detail worth calling out: registering the MCP server makes search_memory
callable, but an agent only calls it proactively β without being asked β if a project instruction tells it to. This repo's CLAUDE.md
and AGENTS.md
both carry a "proactively search memory" instruction, which is why it works unprompted here. If you want this behavior in your own projects, add the same kind of instruction to that project's CLAUDE.md
(Claude Code) or AGENTS.md
(Codex CLI and other AGENTS.md-reading tools).
Being upfront about the current state:
Works:
Doesn't work yet:
SessionEnd
hook event to attach to. The hook-registration code is already in place and will activate with zero changes once Codex ships that event; until then, running memcp ingest-new
manually (or just using Claude Code alongside it, since its hook scans every configured source) picks up new Codex sessions.As more people run multiple AI coding agents side by side, I think "memory that doesn't reset when you switch tools" is going to matter more, not less. memcp is a small, early project, but it's a real working piece of that β and I'm using it to develop itself, feeding its own development sessions back into its own memory store.
Feedback and PRs welcome.