Pebble
FreeNot checkedGit-native AI memory for Claude Code. Open source, local-first, zero LLM API calls.
About
Git-native AI memory for Claude Code. Open source, local-first, zero LLM API calls.
README
🪨 Pebble
Open-source, git-native memory for Claude Code.
Per-project knowledge in your repo. Per-user voice and context machine-local. Both git-versionable. No cloud.
Why git-native • Install • How it works • Vs alternatives • MCP tools
The problem
You start a new Claude Code session on your laptop. Yesterday on the desktop, you and Claude spent two hours hammering out an architecture decision — the kind with real trade-offs you talked through carefully.
Today, none of that exists. You either re-explain it from memory, or paste stale notes. The conversation that didn't end up in code is gone.
How Claude Code users solve this today
- Hand-maintained
CLAUDE.md— works until you forget to update it. Goes stale. - Anthropic's built-in Auto Memory (v2.1.59+) — writes to
~/.claude/projects/.../memory/MEMORY.md. But caps auto-load at 200 lines, lives on one machine, silently truncates the newest entries. - claude-mem — works well, has vector search. But burns Claude subscription tokens summarizing every session, stores in local SQLite that doesn't move between machines, runs an unauthenticated HTTP server on port 37777.
None of these solve the problem the way developers already solve every other knowledge problem: git.
Why git-native
Pebble queues every commit via a post-commit hook, then lets your existing Claude Code session decide what's worth remembering. The intelligence is your AI's. The bookkeeping is Pebble's.
Memory lives as markdown inside your repo:
your-project/
├── src/
├── package.json
└── .pebble/
├── memory.md ← auto-generated index (Claude reads this)
├── context-tree/ ← human-readable knowledge, git-committable
│ ├── decisions/README.md
│ ├── patterns/README.md
│ ├── learnings/README.md
│ └── ...
└── memory.db ← per-machine cache (gitignored)
Commit .pebble/context-tree/ and .pebble/memory.md. Pull on the next machine. Pebble rehydrates.
Two-machine work just became git pull.
What's different about Pebble
| Manual CLAUDE.md | Anthropic Auto Memory | claude-mem | Pebble | |
|---|---|---|---|---|
| LLM cost to capture | Free | Free | Burns subscription tokens | Zero — uses your session |
| Auto-load cap | n/a | 200 lines / 25KB | n/a | Recall on demand |
| Lives in | One file | ~/.claude/ per machine |
Local SQLite | Your repo, as markdown |
| Cross-machine sync | Manual | None | None | git pull |
| Decision provenance | None | Session-based | Session-based | Commit-grained |
| Network surface | None | Anthropic's | Local HTTP :37777 | None |
| API keys needed | None | None | None | None |
| License | n/a | Proprietary | Apache 2.0 | MIT |
What Pebble is NOT
- Not a vector-search memory store. claude-mem does that better — use it if vector recall is what you need.
- Not a cross-tool memory layer (yet). Mem0 covers Cursor + Claude + Windsurf. Pebble is Claude Code first; AGENTS.md export is on the roadmap.
- Not an AI agent. Pebble runs no AI of its own. The AI you already pay for (Claude Code) does the thinking. Pebble is the bookkeeping.
- Not for casual users. If you don't run long Claude Code sessions across multiple machines,
CLAUDE.mdis probably enough — and that's fine.
Install
⚠️ npm package not yet published — install from source for now:
git clone https://github.com/mxfschr/pebble.git
cd pebble
npm install
npm run build
# Register globally so every project works:
claude mcp add -s user pebble node "$(pwd)/dist/mcp-server.js"
# Initialize in any project:
cd your-project
node /path/to/pebble/dist/index.js init
Once npm-published (P0):
npm install -g pebble-memory
cd your-project
pebble init
pebble init will:
- ✅ Install a git post-commit hook
- ✅ Create
.pebble/memory.mdwith bootstrapping instructions - ✅ Add a one-line pointer to your project's
CLAUDE.md(non-destructive) - ✅ Update
.gitignoreto keep the DB private but track the knowledge files - ✅ Inject mandatory usage rules into your global
~/.claude/CLAUDE.mdso Claude Code uses the tools in every session
How it works
┌─────────┐ ┌──────────┐ ┌──────────┐ ┌────────────────────┐
│ You │ ──> │ git hook │ ──> │ SQLite │ ──> │ .pebble/memory.md │
│ commit │ │ captures │ │ queue │ │ + context-tree/ │
└─────────┘ └──────────┘ └──────────┘ └─────────┬──────────┘
│
▼
┌────────────────┐
│ Claude Code │
│ next session │
└───────┬────────┘
│
┌────────────────┴────────────────┐
│ pebble_remember (insights) │
│ pebble_mark_processed (queue) │
│ pebble_recall (when needed) │
└────────────────┬────────────────┘
│
▼
┌────────────────┐
│ Memory persists│
│ across sessions│
│ + machines │
└────────────────┘
Five memory categories
| Category | Emoji | What it captures |
|---|---|---|
| Decision | ⚡ | Architectural choices with rationale |
| Pattern | 🔧 | Code conventions, naming rules |
| Context | 📋 | Project domain knowledge |
| Learning | 💡 | Bugs, pitfalls, gotchas |
| Todo | 🎯 | Active work items |
MCP tools
Project memory (per-repo, in .pebble/):
| Tool | What it does |
|---|---|
pebble_remember |
Store a memory with category + tags |
pebble_recall |
Search memories by keyword |
pebble_forget |
Remove an outdated memory |
pebble_status |
Show memory stats + unprocessed commit count |
pebble_mark_processed |
Clear reviewed commits from the queue (one commit_id, or all queued commits if omitted) |
Every project-memory call takes a project_path parameter — one global MCP server handles all your projects.
User memory (global, in ~/.pebble/user/):
| Tool | What it does |
|---|---|
pebble_user_note |
Record a durable observation about the user |
pebble_user_recall |
Search across voice.md, about.md, notes.md |
pebble_user_status |
Show file sizes + consolidation hint |
pebble_user_read |
Read one of the three user memory files |
pebble_user_write |
Overwrite voice / about / notes (used for consolidation) |
User memory has no project_path — it spans every project.
Schema limits: memory and note text 5 to 500 characters, up to 5 tags per memory, search queries at least 2 characters. If project_path is omitted, Pebble falls back to $PEBBLE_PROJECT_PATH and then to the server process's working directory, which is usually not the project you mean — so always pass it.
Why 500 characters? .pebble/memory.md is loaded into context at the start of every session, so every memory costs tokens forever. The cap is a forcing function: one fact per memory, written tight. If you deliberately want a longer entry, pebble add <category> "<text>" on the CLI writes straight to the DB with no upper bound.
User memory: voice, about, notes
Project memory captures decisions about code. User memory captures who you are and how Claude should communicate with you — across every project, every session.
pebble user init
This creates ~/.pebble/user/ with three files:
~/.pebble/user/
├── voice.md # how Claude should communicate (you edit)
├── about.md # who you are, context (you edit)
└── notes.md # observations Claude appends over time
voice.md and about.md ship as generic templates with placeholders. Fill them in yourself — they're machine-local and never committed to this repo.
notes.md grows over time as Claude calls pebble_user_note when it learns something durable about you (e.g. "user prefers async over sync", "user switched primary editor from X to Y"). You can edit or trim it any time.
At session start, Claude reads voice.md and about.md and applies them to tone and assumptions. The MANDATORY block in ~/.claude/CLAUDE.md (auto-injected on pebble init) instructs it to do so.
Auto-consolidation (the profile grows with you)
Static voice.md and about.md would go stale. The fix: at session start Claude checks pebble_user_status. If notes.md has accumulated 15+ entries, Claude consolidates — reads the notes, decides which observations have become durable patterns vs. one-off events, and rewrites about.md and/or voice.md to integrate the durable ones. Then it clears or archives the processed notes via pebble_user_write.
No approval dialog. This is the same pattern Anthropic uses for claude.ai memory (silent background synthesis) — except in Pebble it happens at session-boundaries, locally, and git is the safety net. If Claude consolidates wrong, you git diff and revert in two seconds. Approval dialogs sound safer but in practice get muted within a week; the diff-then-revert workflow is honest, fast, and aligns with how developers already review changes.
If your ~/.pebble/user/ lives inside a git repo (e.g. your dotfiles), every consolidation produces a normal commit you can review, edit, or roll back like any code change.
Why this is separate from ~/.claude/CLAUDE.md
You can already put personal context in your global CLAUDE.md. That works — but:
- It mixes user identity with global rules and workflows (which is what CLAUDE.md is meant for)
- It doesn't grow automatically — you have to remember to update it
- It's one undifferentiated blob — voice + context + rules + product list
Pebble's user memory separates three concerns cleanly: how Claude speaks (voice), who you are (about), and what Claude has noticed (notes). All three are plain markdown — you can still edit them by hand, or let Claude grow notes.md as you work.
CLI for user memory
pebble user init # Create ~/.pebble/user/ with templates
pebble user show # Show file sizes / entry counts
pebble user note "<text>" # Append a note manually
pebble user read voice # Print contents of voice.md
pebble user read about # Print about.md
pebble user read notes # Print notes.md
CLI
# Project memory (run inside a project's working directory)
pebble init [--no-hooks] # Initialize Pebble in this repo (--no-hooks skips the git hook)
pebble capture # Queue latest commit (git hook does this automatically)
pebble add <cat> <text> [-t a,b] # Manually add a memory, optional comma-separated tags
pebble search <query> # Search memories
pebble forget <id> # Remove a memory
pebble status # Show memory stats
pebble generate # Regenerate memory.md + context-tree
pebble hooks install # Install git hook (done by `init`)
pebble hooks uninstall # Remove git hook
pebble watch enable # Auto-sync: commit + push on remember, pull on session start
pebble watch disable # Back to manual git workflow
pebble watch status # Check if auto-sync is on for this project
# User memory (global, machine-local)
pebble user init # Create ~/.pebble/user/ with starter templates
pebble user show # Show file sizes / entry counts
pebble user note "<text>" # Append observation to notes.md
pebble user read <which> # Print voice / about / notes
Cross-machine workflow
Pebble's accumulated knowledge is markdown inside your repo, so any machine with the repo cloned has the knowledge. Two workflows:
Manual (default):
desktop: pebble_remember → git add .pebble/ && git commit && git push
laptop: git pull → memory ready, Claude reads .pebble/memory.md on session start
Rehydration on a fresh machine. A freshly cloned repo has the markdown but no local SQLite DB. On the first Pebble tool call in a project, if the DB holds no memories and .pebble/memory.md exists, Pebble parses the markdown back into the DB — so pebble_recall works immediately after git pull, with no extra command. If the DB already holds memories, the import is skipped and nothing is overwritten.
Auto-sync (opt-in, requires git remote):
cd your-project
pebble watch enable
After enabling, Pebble silently commits .pebble/memory.md and .pebble/context-tree/ and pushes them after every memory change (pebble_remember, pebble_forget, pebble_mark_processed), and runs git pull --rebase at the start of each MCP session per project. The commit uses git commit --only on those two paths, so anything else you have staged stays untouched. Failures are best-effort and never break Claude's response — if the network drops or auth fails, the local commit still stands and the push retries on the next memory event.
What auto-sync does NOT do:
- Sync the SQLite DB (it's per-machine; only the markdown files are versioned)
- Handle messy merge conflicts (it aborts the rebase and leaves you to resolve manually)
- Work in projects without a git remote (silently no-ops)
- Push at high frequency if you have a rapid-fire commit hook (rate limit yourself in that case)
Files Pebble touches
your-project/
├── CLAUDE.md ← yours; Pebble adds one pointer line on init, never touched after
├── .gitignore ← Pebble appends the right ignore patterns
└── .pebble/
├── memory.md ← AUTO — committable, Claude reads this on session start
├── memory.db ← per-machine SQLite cache, gitignored
├── config.json ← per-machine, gitignored
├── run.sh ← generated git-hook runner, gitignored
└── context-tree/ ← AUTO — committable, one markdown per category
├── README.md
├── decisions/README.md
├── patterns/README.md
├── context/README.md
├── learnings/README.md
└── active-work/README.md
Each category file under context-tree/ appears as soon as that category has its first memory, and is removed again when its last one is deleted.
~/.claude/CLAUDE.md ← Pebble injects a MANDATORY-usage block here on init,
so Claude Code uses Pebble's tools in every session
~/.pebble/user/ ← global, machine-local (NOT in any repo)
├── voice.md ← how Claude should communicate with you (you edit)
├── about.md ← who you are, cross-project context (you edit)
└── notes.md ← observations Claude appends; auto-consolidated into voice/about over time
Requirements
- Node.js 18+
- Git
- Claude Code (or any MCP-capable client — Claude Code first-supported)
Pebble works with Claude Code — whether you use the CLI (
claude.exe/claudein your terminal) or the Code tab in Claude Desktop App. Both share the same engine, the same~/.claude/CLAUDE.md, the same MCP config, the same auto-memory in~/.claude/projects/. Pebble installs identically for both.Pebble does not yet bridge memory across the Chat, Cowork, and Code tabs of Claude Desktop App — each tab has its own isolated memory system today (Chat: cloud-synced; Cowork: project-local; Code:
~/.claude/projects/.../memory/MEMORY.md). Cross-tab Pebble bridging is on the P2 roadmap, currently blocked by Windows MCP bug #42453.
Roadmap
P0 — before 1.0:
- Publish to npm so
npm install -g pebble-memoryactually works. - Submit to the official Claude Code Plugin Marketplace.
- FTS5 search in
pebble_recall(today: substring match).
P1:
- AGENTS.md export — generate
.pebble/AGENTS.mdsnapshot for cross-tool compatibility (Cursor, Codex, Aider, Copilot). - Cross-tab bridge for Claude Desktop App (Chat / Cowork / Code) once Windows MCP bug #42453 is fixed upstream.
- Optional
~/.pebble/user/sync via a separate dotfiles repo. - Honest benchmark vs. claude-mem for token usage on identical workloads.
P2:
pebble blame <decision>— show the commit diff that triggered a given memory.~/.pebble/global/— third memory layer for cross-project but non-personal context.- Cursor + other MCP-client first-class support.
Architecture
Zero LLM calls in the capture path. The git hook calls pebble capture which calls execSync('git diff') and a SQLite insert. That's it. No HTTP, no API keys, no inference.
The intelligence layer is Claude Code itself — running on your subscription, in your session, with the full context already loaded. Pebble's MCP tools let Claude write structured memory to the local DB, regenerate the markdown context-tree, and recall on demand.
This is the architectural inversion that makes Pebble cheap: instead of summarizing-on-capture with a separate model (and paying for it), we capture raw and decide-at-leisure inside the session that's already running.
License
MIT
Acknowledgments
Pebble exists because Anthropic's own engineering blog (Effective Context Engineering for AI Agents) is right: file-based, structured note-taking is the architecturally correct pattern for AI memory. Pebble takes that pattern and adds the trigger (git commits), the substrate (your repo), and the recall interface (MCP).
claude-mem walked so Pebble could run — their hooks-based session capture proved the category was real. Pebble takes a different architectural shape, but the prior art is theirs.
🪨 Memory that lives in your repo. Synced by git. Costs nothing.
Installing Pebble
This server has no published package — it is built from source. Open the repository and follow its README.
▸ github.com/mxfschr/pebbleFAQ
Is Pebble MCP free?
Yes, Pebble MCP is free — one-click install via Unyly at no cost.
Does Pebble need an API key?
No, Pebble runs without API keys or environment variables.
Is Pebble hosted or self-hosted?
Self-hosted: the server runs locally on your machine via the install command above.
How do I install Pebble in Claude Desktop, Claude Code or Cursor?
Open Pebble on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.
Related MCPs
wenb1n-dev/SmartDB_MCP
A universal database MCP server supporting simultaneous connections to multiple databases. It provides tools for database operations, health analysis, SQL optim
by wenb1n-devPostgres Server
This server enables interaction with PostgreSQL databases through the Model Context Protocol, optimized for the AWS Bedrock AgentCore Runtime. It provides tools
by madhurprashPostgres
Query your database in natural language
by AnthropicPostgreSQL
Read-only database access with schema inspection.
by modelcontextprotocolCompare Pebble with
Not sure what to pick?
Find your stack in 60 seconds
Author?
Embed badge for your README
Browse similar
All data MCPs
