get_instructionsLABSCO SUMMARY
It remembers what failed, and says so before you do it again.
The distinctive part is not storage, it is the moment of use: a pre-commit hook that names the dead ends already recorded for the file you are about to commit. Everything else follows from keeping typed events in events.jsonl next to the code — greppable, diffable, and gone from nobody's server because there is no server. Old memories are flagged against the file's git history rather than deleted, so retiring one is a decision you make, and the superseded event stays readable.
What it is
A local-first memory layer for AI coding agents. Memory lives in a plain .projectmem/ directory inside the repository — no cloud, no account, no telemetry — and the MCP server is a stdio subprocess your client spawns, not a service to keep running. What it stores is typed events rather than chat history: issues hit, approaches attempted, fixes confirmed, decisions made and notes. That typing is what makes the pre-commit warning possible: pjm init installs git hooks, and a commit that touches a file with failure history tells you what already failed there before you repeat it.
What you get
- Session start:
get_instructions()for the workflow rules,get_summary()for distilled memory,get_project_map()for repo structure,get_plan()forplan.md— intent kept deliberately separate from the event log precheck_file(path)before editing a file, which surfaces that file's failure historyget_issue(id)for one issue's full history,search_events(query)for plain-text search across everything loggedget_context(tokens, focus)— a memory block built to a token budget, with an optional focus filterget_score()for the prevention grade and ROI numbers,get_global_gotchas(library)for lessons inherited from your other repositories- Write side, called by the agent as work happens:
log_issue(summary, location),record_attempt(summary, outcome)with outcomefailed,partialorworked,record_fix(summary),add_decision(summary, supersedes?)andadd_note(summary) - Decisions retire without disappearing: pass
supersedesand the old event stays in the log, tagged - For agents with no MCP support,
pjm export --claude-mdcompiles live decisions, gotchas and a do-not-retry list into a marked block inCLAUDE.mdor.cursorrules
Requirements
Python, and pip install projectmem followed by pjm init in the repository — that step installs three git hooks (pre-commit warnings, post-commit classification, post-merge tracking), starts the file watcher and creates .projectmem/. Nothing to host and nothing to authenticate against. Use the absolute path to python in the client config — Claude Desktop and Cursor subprocesses do not inherit your shell PATH — and pjm init prints the block with yours filled in. Since 0.3.0 one entry with no --root serves every project you have run pjm init in. On Codex, set reasoning effort to medium or higher — on low it skips get_instructions at session start and misses the workflow rules. Package projectmem on PyPI. MIT licensed.
Setup effort
Follow the published steps — pip install projectmem
USE CASES
Not repeating a fix that already failed
Before editing a file, the agent reads that file's failure history; before you commit, the hook names the dead ends out loud.
Starting a session already knowing where you were
Workflow rules, distilled memory, repo structure and the current plan load in the first few calls, instead of the agent re-reading source to guess.
Capturing a debugging session as it happens
The agent logs the issue, records each attempt with whether it failed, partially worked or worked, and closes with the confirmed fix.
Changing an architectural decision without erasing the old one
Record the new decision with the id it supersedes; the previous event stays in the log, tagged rather than removed.
Carrying a library gotcha into your next project
Lessons stored against a library are inherited by new repositories with a matching stack, so the same trap is not learned twice.
Fitting memory into a small context budget
Ask for a memory block sized to a token count, optionally focused on one area, rather than pasting the whole log.
15 tools
Listed in project docs. Your client may show a different list.
get_summaryget_project_mapget_planprecheck_fileget_issuesearch_eventsget_contextget_scoreget_global_gotchaslog_issuerecord_attemptrecord_fixadd_decisionadd_noteBEFORE YOU INSTALL
What to know first
Tools you get
15 tools named in the project's documentation.
Requires
Python 3.10+
INSTALLATION
Connect your client
Server setup
pip install projectmem
pjm initMCP Clients
Claude Desktop, Cursor
{
"mcpServers": {
"projectmem": {
"command": "<YOUR_PATH_TO_PYTHON>",
"args": [
"-m",
"projectmem.mcp_server"
]
}
}
}<YOUR_PATH_TO_PYTHON> is the Python that has projectmem installed — which python prints it, and pjm init prints this block with your own path already filled in. This client does not inherit your shell PATH, so a bare python often fails.
Antigravity
{
"mcpServers": {
"projectmem": {
"command": "python",
"args": [
"-m",
"projectmem.mcp_server"
]
}
}
}Paste this into Antigravity's MCP config (Agent window → ⋯ Additional Options → MCP Servers → Manage MCP Servers), or edit ~/.gemini/antigravity/mcp_config.json. Then fully quit and reopen Antigravity. The README's Antigravity block uses a bare python; if Antigravity cannot start the server, put the absolute path of the Python that has projectmem installed in "command" (which python prints it) — the README's advice for Claude Desktop, Cursor and Codex, whose subprocesses do not inherit your shell PATH.
Codex
[mcp_servers.projectmem]
command = "<YOUR_PATH_TO_PYTHON>"
args = ["-m", "projectmem.mcp_server"]
cwd = "<YOUR_PATH_TO_PROJECT>"<YOUR_PATH_TO_PYTHON> is the Python that has projectmem installed — which python prints it, and pjm init prints this block with your own path already filled in. This client does not inherit your shell PATH, so a bare python often fails.
Any MCP client
python -m projectmem.mcp_serverPoint your client at this command, and either set its working directory to your project root or let projectmem find .projectmem/ by walking up from where it starts.