# Agent Memory Hub

> Shared persistent memory for AI coding agents (Claude Code), backed by your own Supabase. Cross-session, cross-machine, self-owned.

- **Type:** MCP server
- **Install:** `agentstack add mcp-carloshpdoc-agent-memory-hub`
- **Verified:** Pending review
- **Seller:** [carloshpdoc](https://agentstack.voostack.com/s/carloshpdoc)
- **Installs:** 0
- **Category:** [Databases](https://agentstack.voostack.com/c/databases)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [carloshpdoc](https://github.com/carloshpdoc)
- **Source:** https://github.com/carloshpdoc/agent-memory-hub

## Install

```sh
agentstack add mcp-carloshpdoc-agent-memory-hub
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## 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_dump` anytime. 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`): promotes `procedure` facts (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_dump` to 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

```mermaid
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`). The `Stop` checkpoint 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](https://claude.com/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](https://supabase.com) 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
```bash
git clone https://github.com/carloshpdoc/agent-memory-hub.git
cd agent-memory-hub
```

### 2. Create a Supabase project
At [supabase.com](https://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`
```bash
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:

```json
{
  "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:
```bash
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` (set `REMOTE_SSH` and `SSH_KEY` in `.env`).

## Adding another machine

This is the whole point, and it's trivial:

1. Clone the repo on the new machine.
2. Copy the **same `.env`** (same Supabase credentials).
3. 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](https://github.com/carloshpdoc)
- **Source:** [carloshpdoc/agent-memory-hub](https://github.com/carloshpdoc/agent-memory-hub)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** yes

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: flagged — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-carloshpdoc-agent-memory-hub
- Seller: https://agentstack.voostack.com/s/carloshpdoc
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
