Install
$ agentstack add mcp-carloshpdoc-agent-memory-hub Open-source listing — not yet scanned by AgentStack. Follow the source repository for install instructions.
Security review
⚠ Flagged1 finding(s); flagged for manual review. · v0.1.0 How review works →
- • Prompt-injection patterns
- • Secret / credential exfiltration
- • Dangerous shell & filesystem operations
- • Untrusted network calls
- • Known-malicious package signatures
- high Dangerous shell/eval execution.
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ● Dynamic code execution Used
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
agent-memory-hub
[](https://github.com/carloshpdoc/agent-memory-hub/actions/workflows/ci.yml)
> 🇧🇷 Leia em [Português](README.pt-br.md).
Persistent, shared memory for AI coding agents (Claude Code, and any MCP/REST-capable tool), backed by your own Supabase. Every session is auto-saved to a Postgres table and recalled at the start of the next one, across sessions, tool instances, and machines.
One stance sets it apart: memory you can trust, explain, and own. Not a black box.
- Explainable. Recall shows each item's provenance (a fact's confidence and age, a session's
session_id), and a fact's confidence decays with age, so stale memory fades on its own.
- Human-gated. The cross-project developer profile and its rules are proposed, never
applied on their own. You approve or reject; nothing silently rewrites how your agent works.
- Yours. Plain Postgres on your own Supabase.
pg_dumpanytime. No SaaS in the middle, no lock-in.
Why
Claude Code starts every session from zero. Tools like claude-mem or mem0 solve this, but either store locally (no cross-machine) or run through a hosted service, and most auto-apply whatever they extract. agent-memory-hub is the self-owned, auditable take: a Supabase table you own, optional layers you switch on as you need them (semantic search, facts, a cross-project developer profile, backups), and a human in the loop wherever memory changes how the agent behaves.
- Cross-session / instance / machine: any setup pointing at the same Supabase shares everything.
- Distilled, not dumped: recall injects compact, ranked, explainable context, not raw transcripts.
- Self-improving, on your terms: it learns how you work across projects and proposes rules; you decide.
vs. CLAUDE.md / AGENTS.md
They don't compete: CLAUDE.md (and Cursor's AGENTS.md) are static instructions you write by hand; agent-memory-hub is dynamic memory captured automatically. One answers "how I want you to work" (conventions, canonical commands, rules); the other answers "what we already did, decided, and broke before" — episodic context that doesn't fit a hand-kept file because it changes every session.
| | CLAUDE.md / AGENTS.md | agent-memory-hub | |---|---|---| | Nature | Static instructions, written by hand | Dynamic memory, captured automatically | | Source | You type and maintain it | Generated from your real session history | | Kind of knowledge | Rules ("always do it this way") | Episodic ("what happened / was decided / was fixed") | | Cross-session | Reloads the same text every time | Recalls specific past sessions, on demand | | Cross-machine | Only if you version the file | Automatic (shared Supabase) | | Evolves itself? | No | Yes — captures, and proposes rules (you gate them) | | Upkeep | You maintain it manually | Maintains itself |
Where each wins. CLAUDE.md is deterministic and versioned: a hand-written rule always loads, identically, in every PR — right for commit conventions, build commands, module rules, and anything that must be fixed. Memory is ranked and probabilistic, and shines where a static file structurally can't: remembering automatically, across every session/machine/tool, auditably and self-owned — so you stop re-explaining the project every session.
They connect. The two aren't rivals — the hub feeds CLAUDE.md. Its cross-project profile watches your patterns, proposes rules, you approve, and they land in a profile-rules.md your CLAUDE.md imports (@~/.claude/profile-rules.md). That's the loop that turns episodic history into the static rules a CLAUDE.md holds — closing the gap between what happened and how to always work. Use both: rules for what must be guaranteed, memory for everything you'd otherwise forget.
Features
- Auto-capture of every session, with a per-turn checkpoint that survives crashes.
- Secrets never persist: always-on redaction at capture masks private-key blocks, cloud/API
tokens and NAME=value credentials before anything reaches the database, and anything you wrap in ... in the conversation is never stored at all.
- Recall at session start: a clean one-line summary per relevant session, plus the durable
facts for the current project. Each item carries its provenance (facts: confidence and since-when; sessions: the session_id) so recall is explainable. Fact confidence decays with age (per-kind half-life), so stale facts fade from recall without being deleted.
- Recall on a token budget: the injected context has a hard cap (
RECALL_MAX_TOKENS,
default 1500). Over budget it degrades gracefully — compact index first (full detail one MCP get_session away), then lowest-priority items drop. Every injection is logged to hooks/recall.log (what went in, estimated cost, what was cut) — no blackbox memory, no burned token budgets.
- Search your whole history: hybrid (keyword + semantic via
pgvector), with an
optional LLM --rerank second pass.
- Facts layer (optional, bring-your-own-LLM): durable preferences / decisions / configs /
procedures (how-tos that worked) with temporal validity, deduped by meaning. A new fact that contradicts an old near-match supersedes it at extraction time (valid_until + superseded_by, non-destructive) instead of piling up conflicting memories.
- Defrag job (
scripts/defrag_facts.py, optional): periodic sleep-time pass with your local
LLM — supersedes duplicates, invalidates stale ephemeral facts. Non-destructive, conservative by default ("keep" when unsure).
- Developer profile (optional): distills how you work across all your projects into a profile,
and turns the patterns you approve into rules your agent follows. A self-improving loop, human-gated.
- Rules → enforcement (
scripts/enforce_rules.py, optional): approved rules that are
mechanizable become a PreToolUse guard that blocks the violating shell command — a rule in markdown is a wish list; a hook is a contract. Human-gated: dry-run shows every regex, and it never edits your settings.json itself.
- Cross-tool: Claude Code via hooks, Codex CLI and Cursor via adapters, any tool via the adapter template.
- MCP server (
scripts/mcp_server.py, pure stdlib): dedicated tools —recall_relevant,
recent_sessions, get_facts, get_session — so any MCP agent (Claude Code, Cursor, Codex) queries the memory on-demand, with the task in hand, not just the passive recall at boot.
- Memory console (
scripts/memory.py): browse, search and inspect from the terminal —
stats, recent, search, facts, show, profile, plus standup (what you touched today/this week), health and log (below). Installable as a global mem command (pipx install -e .).
- Markdown export (
mem export): a human-readable, git-versionable dump of facts, session
summaries and approved rules — read, diff and commit what your agent knows. The database stays the source of truth; the export is the audit copy.
- Procedures → skills (
mem skills): promotesprocedurefacts (how-tos that worked in a
real session) to Claude Code SKILL.md files, closing the loop session → procedural fact → reusable skill. Dry-run by default, and it never overwrites an existing skill — once created, the file is yours to edit.
- Health & observability (
memory.py health/log): reconciles local transcripts against
Supabase and watches the capture error rate, so a silent capture failure surfaces instead of going unnoticed — memory you can verify, not just trust.
- Weekly digest (
scripts/weekly_digest.py): a 7-day summary across all projects (LLM-free),
with a hook into your content workflow.
- Tested & measured: an offline pytest suite + CI (on every push/PR) pin the capture pipeline
so the silent-capture bugs can't return, and a recall eval harness (scripts/eval_recall.py, hit@k / MRR) means recall quality is measured, not assumed — that's how we confirmed a recency bias would hurt and kept the 1:1 hybrid fusion as the calibrated default.
- Your own backups: daily
pg_dumpto a portable.sql. No lock-in. - No LLM in the core (the "semantic" part uses an embedded model, not a chat LLM); every
LLM-powered piece is optional and has a free option.
How it works
flowchart TD
subgraph S["AI coding session (Claude Code)"]
direction TB
SS["SessionStart"] --> RECALL["recall_session.pyinjects a digest of relevant past sessions"]
STOP["Stop (each turn)"] --> CAP["capture_session.pycontinuous checkpoint, background, upsert"]
SE["SessionEnd"] --> SAVE["capture_session.pyfinal save"]
end
RECALL -.->|reads| DB[("Supabase, your projecttable public.sessions")]
CAP -->|writes| DB
SAVE -->|writes| DB
DB -->|optional| DUMP["pg_dumpcron on an always-on host"]
DUMP --> GZ([".sql.gz"])
GZ --> PULL["pull to your machine"]
- Capture is idempotent (upsert by
session_id). TheStopcheckpoint means even an
abrupt kill keeps the session up to its last turn.
- Recall injects only a compact digest (one extractive summary line per session, not raw
transcript). Full transcripts stay queryable on demand via the Supabase MCP or REST.
- The summary is deterministic and LLM-free: the capture hook keeps the first substantive
user ask, the last one, and turn counts. Run sql/04-summary.sql to add the column.
What's automatic vs. what waits for you
The design rule: collecting and reading are automatic; anything that changes how your agent behaves goes through you. The split is deliberate — it's this project's defense against memory poisoning (see the non-goals in [ROADMAP.md](ROADMAP.md)). mem help prints the whole map in the terminal.
Automatic — hooks; you never run anything:
| What | When it runs | |---|---| | Session capture (per-turn checkpoint + final save) | every Stop / SessionEnd | | Secrets redaction + ` stripping | inside capture, always | | Recall injection (facts + relevant sessions) | every SessionStart | | Token budget + injection log (hooks/recall.log`) | inside recall, always | | Temporal fact supersession | inside facts extraction, whenever it runs |
Semi-automatic — built for cron; run or schedule them yourself:
| What | Command | Note | |---|---|---| | Facts extraction | python3 scripts/extract_facts.py | needs your LLM reachable (e.g. local Ollama) | | Re-extract old sessions | mem reprocess [how-to\|all] | one command: resets + loops until drained (dedup keeps it safe). Add --embed to also fill session embeddings | | Defrag / reflection | python3 scripts/defrag_facts.py | same; non-destructive | | Pending embeddings | python3 scripts/embed_pending.py | no LLM — just calls the Supabase embed function; ideal for an EC2 cron (only needs EMBED_KEY) |
Manual on purpose — human-gated (each one is dry-run by default):
| What | Command | Why a human gate | |---|---|---| | Patterns → rules in CLAUDE.md | mem profile (approve) then apply_profile_rules.py --write | a rule changes how the agent acts everywhere | | Rules → blocking hook | enforce_rules.py --write | one wrong regex blocks a legitimate command | | Procedures → skills | mem skills --write | a skill enters your agent's context | | Markdown export | mem export | on-demand snapshot |
Requirements and supported tools
The memory itself is just Postgres, so what's tool-specific is only the automatic capture/recall, which ships as Claude Code hooks.
- Auto-capture + recall (the hooks): Claude Code. The
hooks use its SessionStart, Stop, and SessionEnd events.
- Read and query the shared memory: any MCP or REST capable AI tool, for example Cursor,
Codex CLI, Gemini CLI, or ChatGPT, through the Supabase MCP or the REST API.
- Capture from another tool: an adapter scans that tool's local transcripts and uploads
them. Codex CLI and Cursor ship as adapters (scripts/adapters/); see [Capture from other tools](#capture-from-other-tools-adapters) to add more.
Also needed:
- A free Supabase project.
python3(hooks and backup are pure stdlib, no pip needed).
Getting started (also: how to set it up on a machine)
> Shortcut: after cloning and filling .env, run ./scripts/setup.sh. It applies the > SQL migrations and installs the Claude Code hooks in one idempotent step (it does not enable > the optional LLM facts layer). The manual steps below explain what it does.
1. Clone
git clone https://github.com/carloshpdoc/agent-memory-hub.git
cd agent-memory-hub
2. Create a Supabase project
At supabase.com: new project. Enable Data API and RLS. Grab from Settings > API: Project URL, publishable key, secret key.
3. Apply the schema
Open SQL Editor in Supabase and run [sql/01-schema.sql](sql/01-schema.sql). It creates the sessions table, the full-text index, and RLS.
4. Configure .env
cp .env.example .env
# edit .env with your SUPABASE_URL and SUPABASE_SECRET_KEY (and backup vars if used)
.env is gitignored. The hooks read it directly.
5. Wire the hooks into Claude Code
Add to your Claude Code settings.json (~/.claude/settings.json for user scope), using the absolute path to your clone:
{
"hooks": {
"SessionStart": [
{ "matcher": "", "hooks": [
{ "type": "command", "command": "python3 /ABS/PATH/agent-memory-hub/hooks/recall_session.py", "timeout": 15 }
]}
],
"Stop": [
{ "matcher": "", "hooks": [
{ "type": "command", "command": "payload=$(cat); printf '%s' \"$payload\" | python3 /ABS/PATH/agent-memory-hub/hooks/capture_session.py >/dev/null 2>&1 &" }
]}
],
"SessionEnd": [
{ "matcher": "", "hooks": [
{ "type": "command", "command": "python3 /ABS/PATH/agent-memory-hub/hooks/capture_session.py", "timeout": 20 }
]}
]
}
}
> If you already have hooks for these events, add these entries to the existing arrays.
6. (optional) Add the Supabase MCP
Lets the agent query memories interactively:
claude mcp add --scope user --transport http supabase \
"https://mcp.supabase.com/mcp?project_ref="
# then authenticate: /mcp > supabase
7. (optional) Backup module
On an always-on host with pg_dump at or above your Postgres major version, and the repo cloned:
- Put your pooler creds in
~/.pgpass(chmod 600):
HOST:5432:postgres:postgres.:PASSWORD
- Fill the
PG_POOLER_*vars in.env. - Cron:
30 3 * * * /ABS/PATH/agent-memory-hub/scripts/backup.sh >> .../backup.log 2>&1 - Pull copies locally with
scripts/pull-backups.sh(setREMOTE_SSHandSSH_KEYin.env).
Adding another machine
This is the whole point, and it's trivial:
- Clone the repo on the new machine.
- Copy the same
.env(same Supabase credentials). - Run
./scripts/setup.sh.
Done. That machine now writes to and reads from the same shared memory. The migrations are idempotent (and skipped if it has no DB creds, since the schema is shared). The optional facts layer stays off, so a weaker machine just captures and reads, while heavy fact extraction runs only where you enable it.
To also upload that machine's prior Claude Code history (sessions from before the hooks), run python3 scripts/backfill_sessions.py --dry-run to preview, then without the flag to upload. It is idempotent (skips sessions already in Supabase).
Capture from other tools (adapters)
The Claude Code hooks are one capture path. Tools without lifecycle hooks are handled by an adapter that scans their local transcripts and uploads new ones (idempotent), the same wa
…
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: carloshpdoc
- Source: carloshpdoc/agent-memory-hub
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.