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.
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.
- Session start: `get_instructions()` for the workflow rules, `get_summary()` for distilled memory, `get_project_map()` for repo structure, `get_plan()` for `plan.md` — intent kept deliberately separate from the event log
- `precheck_file(path)` before editing a file, which surfaces that file's failure history
- `get_issue(id)` for one issue's full history, `search_events(query)` for plain-text search across everything logged
- `get_context(tokens, focus)` — a memory block built to a token budget, with an optional focus filter
- `get_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 outcome `failed`, `partial` or `worked`, `record_fix(summary)`, `add_decision(summary, supersedes?)` and `add_note(summary)`
- Decisions retire without disappearing: pass `supersedes` and the old event stays in the log, tagged
- For agents with no MCP support, `pjm export --claude-md` compiles live decisions, gotchas and a do-not-retry list into a marked block in `CLAUDE.md` or `.cursorrules`
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. Two configuration details the README documents from its own cross-client testing: use the absolute path to `python` in the client config, because Claude Desktop and Cursor subprocesses do not inherit your shell `PATH`; and pass the project root as `--root /absolute/path/to/your/project` rather than the `cwd` field, which both clients ignore. 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` (0.2.0) on PyPI. MIT licensed.
One command — pip install projectmem
