Memory that lives with your code: reviewed in pull requests, enforced as guardrails, readable by every AI coding agent. Zero dependencies, no daemon, no account.
- Zero dependencies. Plain Node.js, MCP over stdio, memories stored as Markdown files.
- Per project. Memory is keyed by the git remote URL, so every clone of the same repo shares one memory.
- Works across agents. Claude Code, Cursor, Windsurf, Codex, Gemini CLI, VS Code (Copilot), OpenCode, or anything with MCP support.
- Handoffs. Stop mid-task in one agent, continue in another: the next session starts with what was done and what is next.
- Automatic in Claude Code. Hooks inject memory at session start, surface notes when a linked file is opened, and auto-capture new facts when a session ends.
- Team memory in git. Team memories live in
.agentmem/in your repo, so they are reviewed in PRs and shared ongit pull. - Guardrails. Turn a memory into a rule: agents are blocked or asked before editing matching files.
- Code-aware. Memories linked to files are flagged when those files change, so outdated knowledge does not linger.
- Export to rule files. Compile team memories into
AGENTS.md,CLAUDE.md, Copilot and Cursor rules for agents without MCP. - Contradiction checks. New memories come back with related ones to compare, and
agentmem checkfinds conflicts. - PR memory Action. A GitHub Action turns decisions from merged pull requests into team memories, opened as a PR for review.
- Safe by default. Writes that look like secrets are refused. Near-duplicate titles are refused unless forced.
- How it works
- Requirements
- Changelog
- Install
- Connect your agents
- MCP tools
- CLI
- Claude Code hooks
- Auto-capture
- Team memory
- Org memory
- Guardrails
- Code-aware staleness
- Usage stats
- Export to rule files
- Contradiction checks
- Handoffs between agents
- PR memory GitHub Action
- Memory format
- Configuration
- Sharing with a team
- Project structure
- Troubleshooting
- Uninstall
- Contributing
- License
Claude Code ─┐ ┌─► ~/.agentmem/<repo>-<hash>/*.md local, private
Cursor ──────┼── MCP (stdio) ──► agentmem
Other agent ─┘ └─► <repo>/.agentmem/*.md team, committed
- An agent starts
agentmemas an MCP server from inside a project folder. - agentmem finds the project with
git remote get-url origin(falls back to the repo root path, then the current folder) and hashes it into a project id likemy-app-1a2b3c4d5e6f. - Every memory is one Markdown file, either local (
~/.agentmem/<project-id>/) or team (<repo>/.agentmem/). - Any agent opened in the same repo reads both layers.
- Node.js 18 or newer
- git (optional, used to identify the project)
- Claude Code CLI (optional, only for hooks and auto-capture)
See CHANGELOG.md and GitHub releases.
One line. Detects Claude Code, Cursor, Windsurf, Gemini CLI, Codex, VS Code and OpenCode on your machine and configures each one:
npx -y @virling/agentmem installOr install globally first (faster hooks, agentmem on your PATH):
npm i -g @virling/agentmem && agentmem installConfigure only specific agents:
agentmem install claude cursorRestart your agents afterwards. Running install again is safe: it updates existing entries instead of adding duplicates.
/plugin marketplace add virling/agentmem
/plugin install agentmem@virling
The plugin brings the MCP server and all hooks. Use either the plugin or agentmem install claude, not both, or every hook runs twice.
agentmem install writes these for you. The details are here if you prefer to do it by hand.
| Agent | What install changes |
|---|---|
| Claude Code | claude mcp add agentmem --scope user, plus four hooks in ~/.claude/settings.json |
| Cursor | mcpServers.agentmem in ~/.cursor/mcp.json |
| Windsurf | mcpServers.agentmem in ~/.codeium/windsurf/mcp_config.json |
| Gemini CLI | mcpServers.agentmem in ~/.gemini/settings.json |
| Codex | [mcp_servers.agentmem] in ~/.codex/config.toml |
| VS Code (Copilot) | servers.agentmem in the user mcp.json (~/Library/Application Support/Code/User/ on macOS, ~/.config/Code/User/ on Linux, %APPDATA%\Code\User\ on Windows) |
| OpenCode | mcp.agentmem in ~/.config/opencode/opencode.json |
Other keys and other MCP servers in those files are left as they are.
Any client that can launch a stdio MCP server works:
{
"mcpServers": {
"agentmem": { "command": "npx", "args": ["-y", "@virling/agentmem", "mcp"] }
}
}If memories land under the wrong project, the editor started the server outside your project folder. Ask the agent to pass project_path (the absolute project path) on its tool calls, or use the editor's per-project MCP config.
git clone https://github.com/virling/agentmem.git
cd agentmem
npm test
node bin/agentmem.js installThere are no dependencies, so no npm install is needed.
Agents without hooks do not read memory on their own. Add a line like this to your AGENTS.md, .cursor/rules, or equivalent:
At the start of each task call memory_list. Save durable decisions, conventions and gotchas with memory_write.
| Tool | Arguments | What it does |
|---|---|---|
memory_list |
List all memories for the project (id, type, title, flags) | |
memory_search |
query |
Keyword search across title, type, tags, files and body |
memory_read |
id |
Full text of one memory |
memory_write |
title, content, type, files, tags, pinned, guard, scope, agent, force |
Save one fact. Returns related memories to check for contradictions |
memory_update |
id plus any field to change |
Edit a memory in place. With only id, re-verifies it against its files |
memory_promote |
id |
Move a local memory into the repo's .agentmem/ folder |
memory_handoff |
summary, next_steps, files, agent |
Leave a note for the next session in any agent. Replaces the previous handoff |
memory_delete |
id |
Remove a memory |
Every tool also accepts an optional project_path.
Types: decision, convention, gotcha, todo, note, handoff. Scopes: local (default), team. Guards: warn, block.
Run inside any project folder:
agentmem list
agentmem search "auth token"
agentmem show 2026-10-31-use-pnpm
agentmem add "Use pnpm" "This repo uses pnpm 9, not npm" --type convention --files package.json --pin
agentmem edit 2026-10-31-use-pnpm --content "pnpm 9 only"
agentmem pin 2026-10-31-use-pnpm
agentmem unpin 2026-10-31-use-pnpm
agentmem rm 2026-10-31-use-pnpm
agentmem add "Generated code" "Run pnpm codegen" --files "src/gen/**" --guard block --team
agentmem promote 2026-10-31-use-pnpm
agentmem verify 2026-10-31-api-returns-json
agentmem handoff "Refactored auth middleware" "1. Add tests 2. Update docs"
agentmem export agents cursor
agentmem check
agentmem stats # how often each memory was used
agentmem guard-check --base origin/main
agentmem org add git@github.com:acme/.agentmem.git
agentmem path # prints this project's local, team and org foldersRun agentmem with no arguments in a terminal to see the full help.
agentmem install registers these:
| Hook | What it does |
|---|---|
SessionStart |
Injects the latest handoff and pinned memories in full, plus an index of the 50 most recent others. Flags stale and changed memories. |
PreToolUse (Edit, Write, MultiEdit, NotebookEdit) |
Enforces guardrails: denies edits to files under a block memory, asks first for warn. |
PostToolUse (Read, Edit, Write, MultiEdit) |
When a file is touched, injects memories whose files list includes it. Each memory is shown once per session. |
SessionEnd |
Starts auto-capture in the background. Does not block exit. |
When a Claude Code session ends, agentmem:
- Reads the session transcript (user and assistant text only, last 40k characters).
- Sends it to
claude -p --model haikuwith no tools and no MCP servers. - Points out commands that failed and then passed after a file was edited, so the fix can be saved as a gotcha linked to those files.
- Saves up to 5 durable facts with
agent: auto-capture. Secrets and near-duplicates are skipped. If work was left unfinished, it also writes a handoff. - Appends the result to
capture.login the project's storage folder.
Run it by hand on any transcript:
agentmem capture ~/.claude/projects/<project>/<session-id>.jsonlAuto-capture uses your logged-in Claude Code account. Each run is one small Haiku call.
Memories have two scopes:
- local (default):
~/.agentmem/<project-id>/, private to your machine. - team:
<repo>/.agentmem/, committed with your code.
agentmem add "API errors use RFC 7807" "Return problem+json bodies" --type convention --team
agentmem promote <id> # move an existing local memory into the team folder
git add .agentmem && git commit -m "Add API error convention"Team memories are plain Markdown, so they show up in pull requests like any other change. Reviewers can correct or reject them before they reach the rest of the team, and everyone gets them on git pull. Agents call memory_write with scope: "team" or memory_promote to do the same.
Share rules across every repo of the same owner, such as "timestamps are UTC" for a whole GitHub org. Put team memories in the .agentmem/ folder of one repo, then add it once:
agentmem org add git@github.com:acme/.agentmem.git
agentmem org pull # fetch the latest org memories
agentmem org list
agentmem org rm git@github.com:acme/.agentmem.gitThe repo is cloned into ~/.agentmem/_org/. Its memories show up, marked (org), in every project whose origin remote has the same owner (here github.com/acme/). They are read-only: change them with a pull request to the org repo.
A memory with guard and a files pattern becomes a rule that the PreToolUse hook enforces in Claude Code:
agentmem add "Generated client" "Run pnpm codegen instead" --type convention --files "src/gen/**" --guard block --team
agentmem add "Migrations are append-only" "Add a new migration file" --files "db/migrations/*.sql" --guard warn --teamblock: the edit is denied, and the agent sees the memory as the reason.warn: you are asked to approve the edit, with the memory shown.
Patterns support *, ** and ?. Agents without hooks get guardrails through exported rule files.
agentmem guard-check lists files changed since a ref (default HEAD^1) that are covered by a guardrail, and exits with an error if any are block. To run it on every pull request, add .github/workflows/agentmem-guard.yml:
name: agentmem guardrails
on: pull_request
jobs:
guard:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2
- uses: virling/agentmem/guard@v0block guardrails fail the check and warn guardrails add a warning on the file. Only team memories are in the repo, so only team guardrails apply.
When a memory lists files, agentmem stores a content hash of each file. Later:
- If a file is deleted, the memory is flagged
stale. - If a file's content changed, the memory is flagged
changed since written.
Both flags appear in list, search results and the session-start index, so the agent knows to double-check. After checking, run agentmem verify <id> (or memory_update with just the id) to record the current file versions.
agentmem counts a memory as used when it is shown at session start (handoff and pinned), injected for a touched file, hit by a guardrail, or read with memory_read or agentmem show.
agentmem statsIt lists memories by use count, then the ones not used in 14 or more days so you can delete what no longer helps. Counts are stored in usage.json in the project's local folder.
Agents that do not speak MCP still read rule files. agentmem export compiles team conventions, decisions, gotchas and guardrails into them:
agentmem export # AGENTS.md
agentmem export agents claude copilot cursor
agentmem export --include-local # also include your local memories| Target | File |
|---|---|
agents |
AGENTS.md |
claude |
CLAUDE.md |
copilot |
.github/copilot-instructions.md |
cursor |
.cursor/rules/agentmem.mdc |
agentmem only rewrites the block between <!-- agentmem:start --> and <!-- agentmem:end -->. Everything else in the file is left as it is. The Cursor file is fully managed.
memory_writeandagentmem addreturn related memories (same files or similar wording) so the agent can spot a conflict right away.agentmem checksends all memories toclaude -p --model haikuand lists pairs that contradict each other.
$ agentmem check
- 2026-10-31-package-manager-is-pnpm vs 2026-10-31-use-npm-for-installs: One says always use pnpm, the other says run npm install in CI.
Stop in one agent and continue in another without re-explaining:
- In Claude Code, auto-capture writes a handoff when a session ends with work unfinished.
- Any agent can call
memory_handoff(for example when you say "hand this off, I'm switching to Cursor"). - From the terminal:
agentmem handoff "<what is done>" "<next steps>".
The latest handoff from the last 7 days is shown first at the next session start, and at the top of memory_list in agents without hooks. Writing a new handoff replaces the old one.
Turn decisions made in pull request reviews into team memories. Add this workflow to your repo as .github/workflows/agentmem.yml:
name: agentmem
on:
pull_request:
types: [closed]
permissions:
contents: write
pull-requests: write
jobs:
memories:
if: github.event.pull_request.merged
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.base.ref }}
- uses: virling/agentmem@v0
with:
anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }}When a pull request is merged, the action reads its description, reviews and comments, asks Claude for decisions, conventions and gotchas worth keeping, and opens a pull request that adds them to .agentmem/. Your team reviews that pull request like any other.
| Input | Default | Purpose |
|---|---|---|
anthropic-api-key |
required | Anthropic API key, stored as a repository secret |
model |
claude-opus-5-5 |
Claude model used for extraction |
github-token |
github.token |
Reads the pull request and opens the memory pull request |
Your repository must allow GitHub Actions to create pull requests (Settings, Actions, General, Workflow permissions).
---
title: Use pnpm
type: convention
agent: claude-code
date: 2026-10-31
updated: 2026-11-02
pinned: true
guard: warn
files: package.json, pnpm-lock.yaml
tags: tooling
hashes: package.json@3f2a9c1b7d4e, pnpm-lock.yaml@a91c03e5f2b8
---
This repo uses pnpm 9, not npm.- files: repo-relative paths. Used for file-linked hints and stale detection.
- stale: if a listed file no longer exists, the memory is shown with
stale: <file> missingso an agent can verify and fix it. - pinned: always shown in full at session start.
- guard:
warnorblock. See Guardrails. - hashes: written by agentmem. See Code-aware staleness.
You can edit these files by hand. agentmem reads them fresh on every call.
| Variable | Default | Purpose |
|---|---|---|
AGENTMEM_HOME |
~/.agentmem |
Where all project folders live |
CLAUDE_CONFIG_DIR |
~/.claude |
Where agentmem install writes hooks |
The recommended way is team memory in git. To share local memories without git, point AGENTMEM_HOME at a synced folder (Dropbox, iCloud Drive, Google Drive). Every teammate who opens the same repo gets the same project id, so they read the same memories. One fact per file keeps sync conflicts rare.
agentmem/
├── bin/agentmem.js CLI and MCP entry point
├── src/ store, MCP server, hooks, auto-capture, installer, export, PR capture
├── test/ one test file per module (node:test)
├── hooks/ Claude Code plugin hooks
├── .claude-plugin/ Claude Code plugin and marketplace manifests
├── action.yml PR memory GitHub Action
├── guard/action.yml Guardrails GitHub Action
└── .github/ CI, release workflow, issue and PR templates
See CONTRIBUTING.md for what each module does.
- Agent does not see the tools. Run
claude mcp listand check thatagentmemshows as connected. Restart the agent after config changes. - Memories saved under the wrong project. Run
agentmem pathinside the project to see the expected folder. Passproject_pathfrom editors that start servers elsewhere. - Nothing is captured and no handoff appears. The hooks are missing. Run
agentmem install claude, or check~/.claude/settings.jsonfor the fouragentmem ... hookentries. When they are missing, the MCP server tells Claude Code to say so. - Auto-capture saved nothing. Check
capture.login the folder fromagentmem path. Short sessions (under 500 characters of conversation) are skipped. - "similar memory exists". Update the existing memory, or pass
force: true/--force. - "looks like it contains a secret". Remove the key from the text. Store the name of the env var instead.
- Remove the four
agentmemhook entries from~/.claude/settings.json, or/plugin uninstall agentmem@virlingif you used the plugin. claude mcp remove agentmem --scope user- Remove the
agentmementry from each other agent's MCP config listed in Connect your agents. npm rm -g @virling/agentmemif you installed it globally.- Optional:
rm -rf ~/.agentmemdeletes all memories.
See CONTRIBUTING.md.
PolyForm Noncommercial 1.0.0. Free for personal, research, educational and other noncommercial use. Selling agentmem or using it commercially requires a separate license from the author: open an issue or contact Virling.