Projectmem
Projectmem is a local-first memory layer for AI coding agents: this MCP server lets an agent read a project's accumulated memory (instructions, summary, structure, plan, failure history) and write back what it learns as typed events (issues, attempts, fixes, decisions, notes).
Load session context —
get_instructions(),get_summary(),get_project_map(),get_plan()give workflow rules, distilled memory, repo structure, and current intent in a few thousand tokens instead of re-reading source files.Check before editing —
precheck_file(file_path)surfaces a file's failed past approaches, unresolved issues, high churn, and possibly-stale memories before changes are proposed.Query memory selectively —
get_issue(issue_id)for one issue's full history,search_events(query, limit)for keyword search,get_context(tokens, focus)for a token-budgeted block,get_score()for the A+→F ROI grade.Reuse cross-project lessons —
get_global_gotchas(library)returns library gotchas learned in other repos (from~/.projectmem/global/).Capture work as typed events —
log_issue(summary, location)opens an issue and returns its ID;record_attempt(summary, outcome)logs each try as failed/partial/worked;record_fix(summary)closes an issue after evidence it works.Record durable knowledge —
add_decision(summary, supersedes?)for architectural choices (append-only, retire old ones without deleting),add_note(summary)for gotchas and setup details (prefixable for cross-project promotion).Route across many projects — one server serves every registered repo; every tool takes an optional
project(id, alias, or path), withlist_projects()andcurrent_project()to see what's registered, which is active, and where a write would land.Stay safe and local — all read tools are side-effect free, writes append to
.projectmem/plain files with summary regeneration, and nothing leaves the machine.
https://github.com/user-attachments/assets/e055988e-7253-4ba9-92fc-95d3d4bcd763
🚀 Start here — five minutes, once
*Five minutes if you follow along here. Want to be shown instead — every command, the exact output it prints back, and the dashboards at the end? Take the complete setup guide.*
New to projectmem, or upgrading from 0.1.x / 0.2.x? Since 0.3.0 one MCP server serves every project, so this is the last time you configure anything.
1. Install or update
pip install -U projectmem2. Find the projects you already have
pjm doctorIt looks where code lives —
~/Developer,~/code,~/projects, your cloud folders, and every drive on Windows — and lists projects with memory that aren't registered yet. Anything it missed, add by hand:pjm project register "/Users/you/Developer/repos/ossdrop"3. Register them
pjm doctor --fix4. Point your AI at all of them with one config
"mcpServers": { "projectmem": { "command": "/absolute/path/to/python", "args": ["-m", "projectmem.mcp_server"] } }No
--root, nocwd— that's what makes it serve everything. Per-client instructions (Claude Desktop, Claude Code, Cursor, Antigravity, Codex) are in MCP Integration;pjm initprints this block with your own Python path filled in. Then fully restart the client — MCP servers only load on a cold start.5. Check your work
pjm doctorAdd
--onlineif you also want it to tell you when a newer projectmem is out — projectmem makes no network calls otherwise, and--autoturns that into a once-a-day check if you prefer.Run it again after editing the config. It flags any client still pinned to a single repo — the most common reason a new project is invisible to your agent.
All green? You're done. From here on it is one command per repo:
pjm initYour agent reads what the project already learned instead of rediscovering it, and writes down what it finds. Fewer tokens, no repeated dead ends, memory that outlives the session.
Related MCP server: Memstate AI - Agent Memory System
What is coding agent memory?
Coding agent memory is a persistent record of what happened while building a project — the issues hit, the approaches attempted, the fixes that worked and the decisions made — stored so an AI coding agent can read it at the start of a new session. Without it every session begins from zero.
projectmem is an open-source agent memory layer built for that job. It is
local-first: memory lives in a plain .projectmem/ directory inside your
repository, with no cloud, no account and no telemetry — the only network call
it can make is an update check you turn on yourself. A native MCP server
exposes 17 tools to Claude Code, Claude Desktop, Cursor, Antigravity and Codex,
so your agent reads memory and logs its work on its own.
Unlike chat-history memory tools, projectmem stores typed events — issues, attempts, fixes, decisions, notes — which is what makes its signature feature possible: a pre-commit warning that fires before you repeat an approach that already failed in this project.
pip install projectmem
cd your-project && pjm init🎬 Watch the demo
📚 Docs
Doc | What's in it |
The full walkthrough on the web — install, MCP setup per client, | |
15-minute step-by-step walkthrough — set up projectmem on your own project, watch the lifecycle, see the pre-commit warning fire. | |
Release history. Latest: v0.3.5 — precheck matches every spelling of a path, and long entries no longer bloat the summary. | |
PROJECTMEM: A Local-First, Event-Sourced Memory and Judgment Layer for AI Coding Agents — the peer-readable version: design, Memory-as-Governance framing, capability comparison, and the 207-event dogfooding study. | |
MIT |
The Problem
Every new AI session starts from zero. Claude, Cursor, Aider — they all forget yesterday's decisions, repeat failed debugging attempts, and burn millions of tokens reconstructing context from raw source files.
The model isn't the problem. The architecture is. Stateless models need a memory cortex.
The Solution
projectmem is the local-first memory + judgment layer that sits above your AI tools. It captures every failed attempt, decision, and gotcha — then injects that experience back into future AI sessions. Git tracks what changed. projectmem tracks why it changed, what was tried, and what failed.
Install
First time here? → The complete setup guide walks the whole path end to end: install, connecting Claude Desktop, Claude Code, Cursor, Codex or Antigravity, checking it with
pjm doctor, and reading your memory back through the dashboards — with the real terminal output at every step.
Three commands to a project that remembers:
pip install projectmem
cd your-project
pjm initThat's it. pjm init installs three git hooks (pre-commit warnings, post-commit classification, post-merge tracking), auto-starts a real-time file watcher, inherits cross-project memory if available, and creates .projectmem/. Capture is active from minute one.
The canonical command is
projectmem. Apjmalias is installed for speed.
✨ New in 0.3.5 — warnings for every spelling, and a summary that stays small
Precheck recognises a file however its path is spelled. Events store
project-relative paths, so asking about ./src/auth.py, an absolute path, a
path through a symlinked folder or a Windows C:\ path matched nothing, and
precheck called a file with known failures "Safe to modify". Every spelling now
gets the same warnings, and checking is faster on large logs.
get_issue("1") and get_issue("#1") find issue 0001.
(#26)
Long entries no longer bloat the summary. 0.3.4 capped how many entries the summary shows, not how long each one is. Records are now clipped at 300 characters, and a fixed issue takes one line. On a real 238-event project the summary went from 8,974 tokens to 3,458. (#29, #30)
Upgrading? Run pjm init once in each project. The instructions now ask
agents for shorter records, and pjm init refreshes AI_INSTRUCTIONS.md,
keeping your previous copy as AI_INSTRUCTIONS.md.bak.
The #26 fixes were contributed by @vishalhabib99, and #29 was reported and fixed by @bigfree.
✨ New in 0.3.4 — memory that stays small, and warnings you can trust
The summary no longer grows forever. Notes were capped, but Recent issues and Decisions listed everything ever logged, so on an aged project reading the memory cost more than reading the code. Every open issue is still shown — the newest 20 in full, older ones by id — while fixed issues are capped at the newest 10 and decisions at the newest 15, each with a line saying what was left out and where to find it. On a test project with 25 issues and 60 decisions the summary went from about 2,900 tokens to about 1,100. (#19)
Commits are filed under the code they change. Auto-capture used the first
changed path in git's sort order, which was usually the regenerated
.projectmem/summary.md — so valid memories were flagged stale and the real
file lost its history. The location is now the source file the commit is about,
with deletions, renames, merges and a repository's first commit handled.
(#20)
Stale warnings no longer depend on your time zone. A 0.3.3 speed-up compared
git's local-time commit dates with UTC event times as text: west of UTC, recent
stale memories were never flagged; east of UTC, fresh ones were flagged at once.
Both sides are compared in UTC now, and events already filed under
.projectmem/ stop warning without your log being rewritten.
The guidance names the tools' real arguments. It gave precheck_file and
get_issue the wrong argument names (path and id, where the tools take
file_path and issue_id) and showed search_events without its required
query, so an agent copying the call got a validation error. A test
now checks every call shown to an agent against the tool's actual signature.
(#18)
Upgrading? Run pjm init once in each project. Older projects kept the
AI_INSTRUCTIONS.md and git hooks of the release that created them, so fixes to
either never arrived. pjm init now refreshes both — your previous instructions
are kept as AI_INSTRUCTIONS.md.bak, and anything of yours outside
projectmem's block in a hook is left untouched.
Also: a mistyped issue id no longer breaks every later command, pjm precheck
stops warning about projectmem's own files, and Python 3.13 and 3.14 are
supported.
Fixes for #18 and #20 were contributed by Rohan Tiwari, and the first cap for #19 by hylin. #18 and #19 were reported by @medium-effort, #20 by @bigfree.
✨ New in 0.3.3 — precheck stops getting slower, and Windows works end to end
pjm precheck runs before every edit — the instructions tell agents to call it
first — so its cost is paid constantly. It was taking 26 seconds on a
1,200-event project, and getting worse every week, because it ran one
git log per event to answer a question about a single file. It now makes one
call per distinct file, bounded by the oldest event citing it.
events | before | after |
100 | 2,210 ms | 48 ms |
400 | 8,905 ms | 51 ms |
1,500 | ~33 s, 1,501 git processes | 82 ms, 2 processes |
Latency is now flat rather than linear in project age. Results matched a reimplementation of the old algorithm, including across merge commits — except for a time-zone bug this change introduced, which 0.3.4 fixes.
A retired decision no longer resurfaces. supersedes has existed since
0.1.4, but the two surfaces an agent actually reads during work — get_context
and precheck_file — were not filtering it. You could retire a decision and
still be told about it. Both filter now, and AI_INSTRUCTIONS.md finally
documents how to retire one, which is why models never called it.
Your project is named in the bridge file, and AGENTS.md is written too.
One server serves every project, so a call naming none is refused rather than
guessed at — but nothing told the agent the name, so it learned it from the
error and retried, every session. The name is in the bridge now. It goes into
AGENTS.md as well as CLAUDE.md, because Antigravity and Codex never read
the latter.
Six Windows reports are closed. Git hooks shipped a bash shebang that
Git for Windows often cannot resolve — and an unresolvable shebang does not
skip the hook, it aborts your commit. The baked binary path lost its
backslashes to shell escaping. The venv fallback looked in bin/, which
cannot exist there. pjm watch --daemon could not be seen or stopped. And a
box-drawing character in the output killed pjm init outright on a cp1252
console — after it had already created everything, so the command both did its
work and reported failure.
Every one was fixed by running projectmem on the machines that reported it — Windows 11, and three MCP clients (Antigravity, Claude, and Codex) — not by reading the code. Reported by @medium-effort, who also contributed the 0.3.2 Windows daemon support.
✨ New in 0.3.2 — Windows, properly
pjm watch --daemon crashed on Windows with AttributeError: module 'os' has no attribute 'fork'. It now spawns a detached worker instead of forking, so
background watching works on every platform.
Fixing that uncovered a second bug hiding behind it. Liveness was checked with
os.kill(pid, 0) — a POSIX idiom that does not port, because on Windows
os.kill routes to TerminateProcess and signal 0 is not a check at all. The
watcher could not be seen or stopped there, and each pjm watch --daemon leaked
another process. Both are fixed.
Windows daemon support was contributed by @medium-effort (#13).
pjm doctor also got two things. It now tells you to quit your AI client
before editing its config — those files hold the app's own preferences too, so
a running client can rewrite the whole thing on exit and restore the --root
you just removed. And it remembers what it saw last time, so a config that was
clean and is pinned again gets named as a revert rather than looking like doctor
being flaky. Local files only; nothing leaves your machine.
✨ New in 0.3.1 — know when to upgrade
Both dashboards now show which version generated the page, with a check for
updates link beside it. The page makes no request until you click — PyPI's
public JSON is fetched straight from your browser and nothing about your machine
is sent. On the command line, pjm doctor --online checks once and
pjm doctor --auto remembers to check daily; both are off unless you ask.
✨ New in 0.3.0 — one server, many projects
Until now an MCP config was tied to one repository: eleven projects meant eleven
server entries and eleven restarts. 0.3.0 serves every registered project from
a single server. Paste the config once; every repo you pjm init afterwards is
reachable from it.
pjm project list # what this server can reach
pjm project use ossdrop # the default when a call names no projectlog_issue(summary="stars come back empty", project="ossdrop")
→ Logged issue #0019 → ossdrop: stars come back emptyEvery write names the project it landed in — in a shared server, the dangerous
failure is not "nothing works", it is a write that succeeds against the wrong
repo. Existing --root configs keep working untouched, and a pinned server now
refuses to write anywhere else even when asked.
Also in 0.3.0:
Fixed: the MCP server was broken on fresh installs. mcp 2.0 renamed
FastMCPand left the old import path raising — since 2026-07-28 every newpip install projectmemgot a server that died at import. Caught and fixed by @VIVAAN-DHAWAN.Security: stored XSS in
pjm visualize. Event summaries reached the DOM unescaped, and git commit messages become event summaries — so a crafted commit in a branch you pulled could run script in your dashboard. Every sink is escaped now.A rebuilt dashboard — a shareable Memory Card, case files with the full issue → attempt → fix chain, an effort treemap, per-file dossiers, and a global view that opens with where you left off.
Registry migration is automatic: the 0.2.x list of paths is converted on first
read, with a .bak kept beside it.
✨ New in 0.2.0 — the workspace release
0.1.6 made one project's memory something you could watch. 0.2.0 lifts that to your whole workspace — and closes the gap between what happened (memory) and what your code is (structure).
🌐 Global dashboard —
pjm dashboardis one page over every project you'vepjm init-ed: total issues captured, fixes confirmed, dead-ends prevented, tokens saved, a grade per project, and a "needs attention" list. Click any card to open that repo's own dashboard, generated fresh. It's a global view, not a global store — each repo's.projectmem/is aggregated at read time and never leaves its folder. Default is serverless (a static snapshot); add--servefor a tiny, ephemeral live server where the Refresh button re-reads your files — no background daemon, Ctrl+C stops it.🧬 Structure & relations —
pjm map --build(run automatically atpjm init) walks your codebase and, for Python, resolves imports into a real dependency graph. The Project Map's Graph and Flow views now render actual files and the import edges between them. The cache (structure.json) is derived from code, gitignored, and never committed — code is only ever read.🔥 Failure heat on structure (the combo) — the one view a pure code-grapher can't draw and a pure memory tool can't either: files with repeated failed attempts glow red, laid directly over the real import graph. Structure comes from the code, heat comes from your memory, and they meet only in the renderer.
🗂️
plan.md— a new editable intent file: ideas and plans, what you mean to do — deliberately not the event log.events.jsonl → summary.mdrecords what happened;plan.mdrecords what you intend. The AI reads it at session start and edits it directly; a plan never becomes an event.pjm plan/pjm plan "idea"/ MCPget_plan().
Everything stays 100% local — the global dashboard is a read-time aggregate, never a central honeypot of your code's history.
The visualization suite (shipped in 0.1.6)
Your project's memory is also something you can watch — and share.
🎬 Showoff — a dashboard tab with three animated story scenes, all rendered from your real event log: Story Replay (watch your project's history build itself, node by node), Orbit (files orbit the project, events orbit their file), and Universe (your project as a rotating galaxy — every bright star is a real issue, attempt, fix, or decision; click one for its full details).
⏺ Built-in recorder — hit REC (10–60 s) and Showoff downloads a
.webmclip of the animation, rendered 100% locally with a "made with projectmem" badge. Your debugging story, ready for a tweet or a standup.🗺️ Flow — the Project Map's default view: a layered flowchart reading
PROJECT → DIRECTORIES → FILES → WHAT HAPPENED → MEMORY. Files with repeated failures glow red along their path, every file shows its outcome chips, and everything flows into theevents.jsonlcylinder. Tree and Graph views are one click away.🧵 Time Spine — the Timeline's default view: a real-time axis you scroll, with problems branching left (issues, failed attempts) and knowledge branching right (fixes, decisions, notes). Hover any card and its whole issue thread lights up. The classic list remains as "Details".
Why You'll Love It
Pre-Commit Warnings —
pjm precheckwarns you before you commit if you're about to repeat a failed approach, modify a high-churn file, or touch an unresolved issue. It works from this project's own recorded failures, which is why it needs the memory layer underneath. The warning now lists the dead ends themselves ("What already failed here: ✗ tried CSS contain:layout"), andpjm precheck --snooze 2hsilences it politely — the snooze is itself logged, so even the silence is audited.Stale-Memory Detection (new in 0.1.4) — projectmem never deletes a memory. Every decision that cites a file is cross-checked against that file's git history — when the file has moved on, the memory is flagged ("predates 7 commits to auth.py — confirm or supersede") and a human decides. Retire it cleanly with
pjm decision "new way" --supersedes <id>: the old event stays in the log, tagged, forever.Session-Start Briefing (new in 0.1.4) —
pjm briefanswers "where was I?" in one screen: active warnings, possibly-stale memories, open issues, recent decisions, stack gotchas, and your prevention score with a week-over-week delta.Memory for agents without MCP (new in 0.1.4) —
pjm export --claude-mdcompiles live decisions, gotchas, and a "Do NOT retry — these already failed" list into a marked block in CLAUDE.md (or.cursorrules). Copilot, plain Claude, any agent that reads the file inherits your project's judgment.Smart Context Injection —
pjm wrap claude(or cursor/aider) injects a token-budgeted memory block into your AI before the session opens. Your AI starts experienced, not blank.Estimated ROI Score —
pjm scoreoutputs a letter grade (A+ → F) with the tool's own estimates of debugging hours saved, tokens avoided, and dollars saved. CI-friendly JSON output and shields.io badge for your README.Cross-Project Memory — Lessons learned in one repo follow you forever. Library gotchas, decisions, and patterns live in
~/.projectmem/global/and are inherited by new projects. A project with a manifest (pyproject.toml,requirements.txt,package.json,Cargo.toml,go.mod) is offered only the lessons for its stack.Real-time File Watcher — Background daemon detects rapid edits to the same file (debugging sessions) between commits. Battery-aware, gitignore-aware, auto-started by
pjm init.Native MCP Server — Plugs into Claude Desktop, Cursor, Antigravity, Codex, and any MCP-compatible tool. 17 native tools force the AI to read context, check files for known failures, read your
plan.md, and log work automatically. Verified end-to-end in all four clients at first release; the 0.3.3 acceptance suite was re-run in Antigravity, Claude, and Codex.Interactive Dashboard (expanded in 0.1.6) —
pjm visualizeopens a six-tab local dashboard: Overview, Story Map (failure heatmap with collapse/focus controls), ROI Dashboard, Project Map (Flow / Tree / Graph, now over your real code structure), Timeline (Time Spine / Details), and Showoff — animated story scenes with a built-in video recorder.One MCP server for every project (new in 0.3.0) — configure your client once instead of once per repository. Calls name their project (
project="ossdrop"), or fall back to the active one; every write reports which repo it landed in, and a pinned--rootserver refuses to write outside its own. Existing single-project setups are untouched.Global Dashboard (new in 0.2.0) —
pjm dashboardis one cross-project view over every repo you'vepjm init-ed: grades, issues, savings, and per-project drill-in. A global view, never a global store — each repo's memory is aggregated at read time and never leaves its folder. Serverless by default;--servefor an ephemeral live server (Ctrl+C to stop).Code Structure + Judgment (new in 0.2.0) —
pjm map --buildreads your codebase into a real import graph, and the Project Map overlays failure heat from your event log on top: the files that keep breaking, glowing red over the structure that actually connects them. The structure cache is derived from code and gitignored — never committed.Intent, separate from memory (new in 0.2.0) —
plan.mdholds ideas and plans (what you mean to do), kept deliberately apart from the append-only event log (what happened).pjm plan, or the MCPget_plan(); the AI edits it directly and a plan never becomes an event.100% Local — No cloud, no telemetry, no accounts. Your code, your memory, your machine.
How It Compares
Capability | projectmem | claude-mem | agentmemory | mem0 | Letta |
Core focus | Memory + judgment | Session capture | Memory engine | Chat / user memory | Agent harness |
Warns before a commit from a file's own failure history | ✅ | ❌ | ❌ | ❌ | ❌ |
Checks memory for staleness against git history | ✅ | ❌ | 🟡 links sessions to commits; time decay | ❌ | ❌ |
Failed attempts as typed events | ✅ worked / partial / failed | 🟡 bugfix type | 🟡 captures tool failures | ❌ | ❌ |
Keeps superseded memories (no deletion) | ✅ | ? | 🟡 versioned, but decay can evict | ✅ add-only since v3 | ✅ git-versioned memory |
Cross-project lessons | ✅ stack-scoped with a manifest | 🟡 opt-in flag | 🟡 cross-project search | 🟡 user-scoped | 🟡 per agent |
Runs locally with no LLM API key | ✅ | 🟡 local store, LLM compression | ✅ keyless mode | ❌ self-host needs a key | 🟡 local mode |
Native MCP server | ✅ 17 tools | ✅ | ✅ 54 tools | 🟡 hosted only | ❌ MCP client |
Price · licence | Free · MIT | Free · Apache-2.0, paid Pro | Free · Apache-2.0 | Free tier · Apache-2.0, paid cloud | Free tier · Apache-2.0, paid cloud |
✅ yes · 🟡 partial · ❌ not found in the project's own docs · ? not documented. Snapshot taken 2026-10-02 from each project's README, docs and changelog; design capabilities, not benchmark results. Corrections welcome — open an issue.
There is no database and nothing you have to keep running: the MCP server is a stdio subprocess your AI client spawns, and everything else is plain files. The only server anywhere is the optional pjm dashboard --serve, an ephemeral local viewer you start and stop with Ctrl+C.
🚧 Upcoming
Import your existing memory —
pjm import(planned for 0.4.0) will migrate history from mem0, agentmemory, Letta, and Claude session logs into projectmem. It maps only to the core event vocabulary — issues, attempts, fixes, decisions, notes — so signal comes in and another tool's clutter stays out. Your judgment history moves with you.
Want a source supported? Open an issue and tell us what you're migrating from.
How AI Reads Your Memory (Token Efficiency)
The architecture is built around one rule: AI reads small, distilled files. Tools generate them from the big raw log.
Measured on 0.3.5 with the cl100k_base tokenizer, on nine real projects of
9 to 238 events. At session start an agent reads three files.
AI_INSTRUCTIONS.md is about 3,300 tokens and costs the same in every project.
summary.md ranged from about 400 to 3,500 tokens, and PROJECT_MAP.md from
about 100 to 900. A synthetic worst case with 40 open issues and long entries in
every record brings the summary to about 6,300. The baseline and pjm wrap rows
are estimates.
Access mode | Tokens / session | How it works |
No projectmem (baseline) | 5,000 – 20,000+ | AI re-reads source files every session |
Universal Mode (markdown) | ~3,700 – 7,600 | AI reads 3 distilled files once |
MCP Mode (recommended) | ~3,700 – 7,600 at session start | AI calls |
| 500 – 2,000 | Pre-generated, you set the budget |
AI never reads events.jsonl directly. That file is for tools (pjm score, pjm context, pjm wrap). Tools distill the raw log into compact AI-readable summaries.
One server, many projects
Since 0.3.0 a single MCP server serves every project you have registered. Paste
the config once and every repo you pjm init afterwards is reachable from it —
no second entry, no restart.
pjm project list # what this server can reach
pjm project use ossdrop # the default when a call names no project
pjm project alias ossdrop odYour agent picks the project per call:
log_issue(summary="stars come back empty", project="ossdrop")
→ Logged issue #0019 → ossdrop: stars come back emptyEvery write says where it landed. That echo is the point: in a one-project setup a misconfigured server simply fails, but a shared server can succeed against the wrong repository, which corrupts two audit trails at once. If the name in the reply is not the project you meant, stop.
How a call is routed, highest first:
Source | Notes | |
1 |
| A boundary, not a default. A pinned server refuses to write elsewhere, even when asked. |
2 |
| id, alias or path. An unknown name is an error. |
3 | The client's workspace root | Planned for 0.4.0 — the resolver supports it, but MCP clients don't pass their roots to it yet. |
4 | The active project |
|
5 | The working directory | Walks up looking for |
6 | — | Refuses, and lists what is registered. It never guesses. |
Once client roots are wired in, they will outrank the active project on purpose: the root is where you are now, the active project is a mode you set days ago. When they disagree, the stale one is the wrong answer.
Single-repo setups are untouched — pjm init --mcp-config-single still prints
the pinned config, and an existing --root entry keeps working exactly as before.
MCP Integration (Recommended)
For: Claude Desktop, Cursor, Antigravity, Codex — and any tool with native MCP support. The MCP server forces the AI to read memory and log every action automatically.
Since 0.3.0 you configure this once, not once per repository. The block below has no --root: the server serves every project you have registered, and each call resolves its own. Paste it, and every repo you pjm init from then on is reachable — no second entry, no restart.
"mcpServers": {
"projectmem": {
"command": "/opt/anaconda3/bin/python",
"args": ["-m", "projectmem.mcp_server"]
}
}Upgrading with projects you already have? The registry only ever recorded
projects you ran pjm init on since it existed (0.2.0), so anything older is
missing — and global mode routes through the registry. One command sorts it out:
pjm doctor # what's unregistered, what's stale, what's still pinned
pjm doctor --fix # register what it foundIt looks in the places code actually lives — ~/Developer, ~/code, ~/src,
~/projects and friends, plus every fixed drive on Windows, where projects sit
on D:\ and E:\ as often as under your home folder. To point it somewhere
specific:
pjm doctor --path ~/work --path /Volumes/ssd --fix
pjm project scan D:\ E:\ --depth 3 # the same walk, without the other checksNothing is scanned until you run it, and nothing is written without --fix.
After an upgrade the CLI mentions pjm doctor once — a wheel install can't run
code, so the first command you type is the only place to say it.
With one project registered, that is the whole setup — there is only one place a call can go. With several, your AI passes project="<name>", or you set a default with pjm project use <name>. pjm init prints this block with your own Python path already filled in.
Upgrading from 0.2.x? Your existing --root entry keeps working exactly as before, and a pinned server now refuses to write outside its own repo even if asked. Replace it with the block above when you want one server for everything.
The 3-minute workflow (let your AI do the setup)
Install + init.
pip install projectmem, thencdinto your project and runpjm init— or simply ask your AI to run it.Ask your AI to set up the projectmem MCP server for you — it can edit the client's config file itself. (It needs permission to do that: use Auto / accept-edits mode, or approve the file edit when asked. The exact config per client is in the sections below if you'd rather paste it by hand.)
Restart the AI tool so the MCP server loads, then start your session with this prompt:
Hi — I use projectmem as this project's memory. Before anything else,
call get_instructions(), then get_summary(), then get_project_map() to
load what we already know. As we work, log issues, attempts
(failed/worked), fixes, decisions, and notes with the projectmem tools,
and call precheck_file(file_path) before you edit a file. Ideas and plans go
in plan.md via get_plan() — never as events.Strictly speaking this prompt is optional — with the MCP server installed correctly the AI discovers the memory on its own. But saying it makes capture noticeably more consistent, so we recommend it.
Repeat for every project:
pjm init+ the same kickoff prompt.Coming back after closing the window? Open with a one-line reminder — "Reminder: we use projectmem as memory here." — and the whole setup carries on where you left off.
Prefer to wire it up by hand? The exact, verified config for each client follows.
Claude Desktop
Easiest — open the config from the UI:
macOS: Claude menu →
Settings…→Developertab → Local MCP servers → Edit Config.Windows / Linux: same path expected (
Settings → Developer → Edit Config) — open an issue if your platform differs and we'll update this.
If you prefer the raw file path: ~/Library/Application Support/Claude/claude_desktop_config.json on macOS, %APPDATA%\Claude\claude_desktop_config.json on Windows, ~/.config/Claude/claude_desktop_config.json on Linux (or $XDG_CONFIG_HOME/Claude/ if you have moved it). pjm init prints the right one for the machine you run it on.
Paste this block:
"mcpServers": {
"projectmem": {
"command": "/opt/anaconda3/bin/python",
"args": ["-m", "projectmem.mcp_server"]
}
}Two things to know about this block:
Use the absolute path to
python(e.g./opt/anaconda3/bin/python, or runwhich pythonto find yours). Claude Desktop subprocesses don't inherit your shellPATH, so bare"python"often fails.You no longer need the
cwdfield, and you never could rely on it. Claude Desktop's current build (with the Epitaxy / Cowork workspace system) silently ignorescwd— the server ends up running withcwd=/and can't find.projectmem/. That is why older releases needed--root. The registry replaces it: the server finds projects by name, not by where it happens to be running.
"mcpServers": {
"projectmem": {
"command": "/opt/anaconda3/bin/python",
"args": [
"-m", "projectmem.mcp_server",
"--root", "/absolute/path/to/your/project"
]
}
}A pinned server serves exactly that repository and refuses to write anywhere else, even when asked — the stricter choice if you want a hard boundary. pjm init --mcp-config-single prints this form.
Then fully quit Claude Desktop (Cmd+Q on Mac) and reopen — MCP servers only initialize on cold start.
Cursor
Two ways to register the MCP server — pick whichever fits your workflow:
Global (recommended): Cursor menu →
Settings…→ left sidebar Tools & MCPs → Installed MCP Servers → Add Custom MCP. Paste the JSON below.Per-project: drop the JSON into
<project-root>/.cursor/mcp.json— only active when that project is open.
{
"mcpServers": {
"projectmem": {
"command": "/opt/anaconda3/bin/python",
"args": ["-m", "projectmem.mcp_server"]
}
}
}Two things to know about this block (same gotchas as Claude Desktop):
Use the absolute path to
python(runwhich pythonto find yours). Cursor subprocesses don't reliably inherit your shellPATH.Don't bother with the
cwdfield. Cursor — like Claude Desktop — silently ignores it: the server ends up running withcwd=~. Since 0.3.0 that no longer matters, because projects are found by name in the registry rather than by where the server runs.
Registered globally, one entry covers every project. Per-project .cursor/mcp.json still works if you prefer the server to exist only when that repo is open — add "--root", "/absolute/path/to/your/project" to args there to pin it.
Then fully quit Cursor (Cmd+Q on Mac) and reopen. projectmem also auto-discovers .projectmem/ by walking up from CWD (like git does for .git/), and honors PROJECTMEM_ROOT and a --root <path> CLI argument.
Antigravity
Antigravity (Google's AI IDE) speaks standard MCP.
Easiest — open the config from the UI:
Open the Agent window (the chat panel on the right).
Click the ⋯ Additional Options button in the panel header.
Choose MCP Servers → Manage MCP Servers → Add new (or Edit Config).
The raw file is at ~/.gemini/antigravity/mcp_config.json if you prefer editing it directly.
Paste this block:
{
"mcpServers": {
"projectmem": {
"command": "python",
"args": ["-m", "projectmem.mcp_server"]
}
}
}Antigravity does honor the cwd field, so adding "cwd": "/absolute/path/to/your/project" works — but it ties the server to that one repo. Leave it out and the same entry serves every registered project.
Then fully quit Antigravity (Cmd+Q on Mac) and reopen — MCP servers only initialize on cold start. All 17 projectmem tools register identically to Claude Desktop / Cursor.
Codex
Codex stores MCP config as TOML (not JSON) in ~/.codex/config.toml. There's a UI form at Settings → MCP Servers → Add MCP Server, but during cross-client verification the form's Save button didn't reliably persist — the file-edit path is faster and more reliable.
Easiest — edit ~/.codex/config.toml directly:
Append this block (preserves any existing config):
[mcp_servers.projectmem]
command = "/opt/anaconda3/bin/python"
args = ["-m", "projectmem.mcp_server"]Three things to know about this block:
Use the absolute path to
python(runwhich pythonto find yours). Codex subprocesses don't reliably inherit your shellPATH.You no longer need
--rootorcwd. Earlier releases passed--rootas defense in depth (thecwdfield does appear to work in Codex, unlike Claude Desktop and Cursor). Since 0.3.0 the registry makes both unnecessary — add"--root", "/absolute/path/to/your/project"toargsonly if you want this server locked to a single repo.Set your reasoning effort to
mediumor higher. On low-reasoning Codex skipsget_instructionsfrom the session-start trio, which can cause the AI to miss the Setup Mode workflow rules. Medium+ honors the full trio automatically.
Validate the TOML:
python -c "import tomllib; tomllib.load(open('/Users/<you>/.codex/config.toml','rb')); print('OK')"Should print OK. If not, the parser tells you the offending line.
Then fully quit Codex (Cmd+Q on Mac) and reopen. Same cold-start rule as every other MCP client. Codex MCP servers spawn lazily on the first tool call in a chat session — if you don't see the process in ps aux right after reopening, send any message to a Codex chat and check again.
Reasoning-effort note: Codex's mode selector is at the bottom of the chat input. Set it to medium (not low) for the full session-start trio behavior. Once set, it persists per-session.
First-run permission prompts
On first use in any MCP-capable client (Claude Desktop, Cursor, Antigravity, Codex), your AI will ask permission before each projectmem tool call. This is expected security behavior — MCP clients require explicit consent for every new tool. Approve each tool once and the prompt won't reappear for that session.
Other MCP Tools
Any MCP-compatible client works — point your tool at
python -m projectmem.mcp_server and either set cwd to your project
root or rely on the parent-walk auto-discovery.
MCP Tools Exposed
All 17 tools your AI can call. Every repo tool takes an optional
project argument — see One server, many projects:
Read-side (12 tools):
Tool | When to use |
| Start of every session — load workflow rules |
| Start and end — distilled project memory |
| Start — understand repo structure |
| Read |
| Before editing any file — surface failure history |
| Read one specific issue's full history by ID |
| Plain-text search across all logged events |
| Token-budgeted memory block with optional focus filter |
| A+→F prevention score + ROI numbers |
| Cross-project library lessons inherited from past repos |
| See every registered project, and which one is active |
| Check which project a call would resolve to, without writing anything |
Write-side (5 tools):
Tool | When to use |
| Immediately when encountering a bug |
| Immediately after each fix attempt (outcome: |
| After confirming a fix resolves the issue |
| When making architectural / design decisions; pass |
| When discovering gotchas, setup details, or constraints |
CLI Reference
Core memory
Command | Purpose |
| Initialize memory + auto-install hooks + inherit global memory |
| Start a new issue / debugging session |
| Record a fix attempt outcome |
| Record the confirmed fix and close the issue — |
| Record an architectural decision; optionally retire a prior one (old event stays in the log, tagged) |
| Record durable context or a gotcha |
| Print |
| Print the current summary |
| Plain-text search across all events; |
| One-screen session-start briefing: warnings, stale memories, open issues, decisions, score |
| Compile live memory into CLAUDE.md / .cursorrules for agents without MCP |
Intelligence layer
Command | Purpose |
| Real-time file churn watcher |
| Warn about repeating failed approaches before commit; snooze politely (audited) when needed |
| Inject token-budgeted memory into Claude/Cursor/Aider |
| Generate token-budgeted project context |
| Letter-grade prevention score |
| Manage cross-project memory |
Projects (global MCP)
Command | Purpose |
| Find unregistered projects, stale entries and pinned client configs. |
| Every project this server can reach, and which one is active (new in 0.3.0) |
| Walk for projects with memory and register them |
| Add a project that already has memory ( |
| Set the default project for calls that name none; omit the name to clear it |
| Give a project a shorter name |
| Tag a project |
| Forget a project — its repo and |
Visualization & utility
Command | Purpose |
| Open the six-tab local dashboard (Overview, Story Map, ROI, Project Map, Timeline, Showoff) |
| Cross-project global dashboard over every |
| Print the Project Map; |
| Token ROI summary in the terminal |
| Auto-populate memory from git history |
| Manage git hooks manually |
| Rebuild |
Use
--at "file.py:42"with any logging command to attach precise location metadata.
plan.md — intent, kept separate from memory
pjm init scaffolds a .projectmem/plan.md: your ideas and plans — what you mean to do, in plain Markdown (Ideas · Active plans · Next · Someday · Shipped). It's the one file that is deliberately not the event log:
events.jsonl → summary.mdrecords what happened (append-only, never rewritten).plan.mdrecords what you intend — and you (or the AI) edit it directly, likePROJECT_MAP.md.
Your AI reads it at session start via get_plan() and updates it in place: adding ideas, checking items off, moving finished work down to Shipped. A plan is never logged as an event, so intent stays cleanly out of your memory's audit trail. pjm plan prints it; pjm plan "auto-batch the exporter" appends an idea. It's committed (not gitignored) so intent is shared with your team.
Example: Pre-Commit Warnings in Action
$ git commit -m "switch auth to JWT"
projectmem: Pre-Commit Check
─────────────────────────────────────────────
src/auth/middleware.py
WARN What already failed here (2 attempts):
✗ tried switching to JWT middleware (2d ago)
✗ patched session timeout to 60min (5d ago)
WARN HIGH CHURN: 5 changes in last 30 days
WARN 1 possibly-stale memory cites this file
decision [evt_9db5a3f8…] "auth uses session
cookies, 30min timeout" — predates 7 commits
Confirm it still holds, or retire it:
pjm decision "..." --supersedes <id>
─────────────────────────────────────────────
3 warning(s). Review before committing.Need it quiet for a refactor sprint? pjm precheck --snooze 2h — warnings pause, the pause itself is logged, and every commit shows one dim line so silence is never mistaken for a clean check.
Privacy & Security
By default, projectmem commits the distilled files (summary.md, PROJECT_MAP.md, AI_INSTRUCTIONS.md, issues/) and gitignores the raw log + runtime files (events.jsonl, watch.pid, watch.log). This means your teammate's AI inherits your team's knowledge automatically — just git clone and the AI already knows what your team learned.
Want total privacy? Add a single line .projectmem/ to your .gitignore. Nothing leaves your machine.
Full security policy and threat model: SECURITY.md · Privacy & Security guide
Design Principles
Local-first — No cloud, no telemetry, and no network calls unless you turn on the update check. Your data never leaves your machine.
Project-scoped — Memory lives in the repo. When the code moves, the memory moves.
AI-tool-agnostic — Works natively via MCP, or universally via Markdown instructions. Any AI tool, any workflow.
Built With
projectmem stands on the shoulders of these excellent open-source projects:
Typer — the CLI framework that makes
pjmfeel ergonomicModel Context Protocol — Anthropic's open spec that lets AI agents talk to local tools
watchdog — cross-platform filesystem event monitoring (the heart of
pjm watch)D3.js — the interactive visualizations in
pjm visualize
Research & Citation
projectmem is described in a peer-readable research paper:
PROJECTMEM: A Local-First, Event-Sourced Memory and Judgment Layer for AI Coding Agents Ripon Chandra Malo, Tong Qiu — University of Utah arXiv:2606.12329 · cs.AI
The paper introduces the Memory-as-Governance framing — memory that doesn't merely answer the agent but acts on its next action — and reports the design, the deterministic pre-commit judgment gate, a capability comparison against 12 contemporary memory systems, and a two-month, 207-event dogfooding study across 10 real projects.
If projectmem is useful in your research or writing, please cite:
@misc{malo2026projectmem,
title = {PROJECTMEM: A Local-First, Event-Sourced Memory and
Judgment Layer for AI Coding Agents},
author = {Malo, Ripon Chandra and Qiu, Tong},
year = {2026},
eprint = {2606.12329},
archivePrefix = {arXiv},
primaryClass = {cs.AI},
url = {https://arxiv.org/abs/2606.12329}
}License
MIT — free for personal, commercial, and enterprise use forever.
Help Us Reach More Developers
We don't need money. We need you.
projectmem was started by one developer and is now shaped by contributors from the open-source community. Every star, every share, and every contribution helps the project survive and grow.
Star the repo — takes one click, helps massively with discovery
Share on X / LinkedIn — tell other devs they don't have to keep paying AI to relearn their codebase
Open an issue — bug, feature request, or just feedback
Contribute code — PRs welcome; for anything large, open an issue first
Using
projectmemat work or in a commercial product? Reach out to support@projectmem.dev so we know who's shipping with us. It's free — we just love hearing about it.
Stars and shares matter more than money — but if you really want to: sponsor on GitHub →
Available Tools
17 toolsadd_decisionA
Record an architectural or product decision permanently.
Call when you make a choice that future sessions or contributors
should know about. Decisions show up in `summary.md` and in
`pjm wrap` context blocks.
Side effects: appends a `decision` event and updates summary.md.
Decisions are append-only — to revise, pass `supersedes` with the old
decision's event id instead of editing history.| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Which project this call is about — a registered id, alias, or absolute path (e.g. 'ossdrop'). Omit it when the server was started for a single repo, or when an active project is set with `pjm project use`. Call list_projects to see the registered names. | |
| summary | Yes | One-line description of the architectural or product decision (e.g., 'use bcrypt rounds=12 for password hashing'). Becomes part of the project's permanent record — write it for a future contributor. Keep it under 300 characters: summary.md clips longer text. | |
| location | No | Optional file path or scope where the decision applies (e.g., 'src/auth/' for a module-level choice). Helps precheck_file cite the decision when the file is later touched. | |
| supersedes | No | Optional event id (evt_...) of a prior decision this one retires. The old event stays in the log tagged (superseded); only the new decision appears in summary.md. Use when precheck_file flags a decision as possibly stale and you are revising it. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does it well: it states the side effects (appends a `decision` event, updates summary.md), the append-only immutability, and the correct revision mechanism. It omits error/edge behavior — e.g. what happens with an unregistered project or a bad `supersedes` id — which keeps it from a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the purpose, then usage, then side effects — a sensible order with little waste. There is minor redundancy with the schema on `supersedes`, and the 'shows up in summary.md' detail is repeated by the side-effects sentence.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and the description covers purpose, trigger, side effects, and the revision path. The main remaining gap is the absence of sibling differentiation for a tool set containing add_note, log_issue, and record_fix.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so all four parameters are already documented in detail, making 3 the baseline. The description's only parameter-adjacent content is the `supersedes` revision workflow, which the schema already spells out; it adds no syntax or format detail beyond that.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence gives a specific verb and resource ('Record an architectural or product decision') plus a persistence qualifier ('permanently'). It is clearly a decision-logging tool, but it never names or contrasts the adjacent siblings (add_note, log_issue, record_fix), leaving the agent to infer the boundary between a decision and a note or issue.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a concrete trigger: 'Call when you make a choice that future sessions or contributors should know about,' and explains the revision path via `supersedes` instead of editing history. It stops short of explicit exclusions — there is no 'use add_note instead when…' guidance despite several similarly-named siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
add_noteA
Record a gotcha, setup detail, or other durable context.
Use when you discover something important that doesn't fit as an
issue or decision. Notes survive across sessions and appear in
wrap context blocks.
Side effects: appends a `note` event. Notes prefixed `gotcha:`,
`lesson:`, or `warning:` are eligible for auto-promotion to
~/.projectmem/global/ for cross-project recall (L-046).| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Which project this call is about — a registered id, alias, or absolute path (e.g. 'ossdrop'). Omit it when the server was started for a single repo, or when an active project is set with `pjm project use`. Call list_projects to see the registered names. | |
| summary | Yes | One-line description of the gotcha, setup detail, or context worth preserving. Prefix with 'gotcha:' or 'lesson:' to enable cross-project promotion — e.g., 'gotcha: bcrypt v4 silently truncates passwords longer than 72 bytes'. Keep it under 300 characters: summary.md clips longer text. | |
| location | No | Optional file path or library this note applies to (e.g., 'bcrypt' for a library-specific gotcha). |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With zero annotations the description carries the full burden and does so well: it declares the mutation explicitly ("appends a `note` event"), states durability ("survive across sessions"), and discloses a non-obvious downstream effect (prefix-triggered auto-promotion to a global store). It doesn't say whether notes can be edited or deleted, or how duplicates are handled — minor gaps rather than omissions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the purpose, then a when-to-use paragraph, then a clearly labeled "Side effects" block — good scanning structure. The final sentence duplicates the prefix/limit detail already carried by the schema, which is the only wasted space.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and the description covers the durability and side-effect model an agent needs before writing. The only unresolved question is failure behavior when `project` can't be resolved, which the schema partially handles by pointing at `list_projects`.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so `project`, `summary`, and `location` are already fully documented, and the baseline is 3. The description repeats the prefix convention and the 300-character clip that the `summary` schema already states; the repetition is consistent but adds no new semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ("Record") and a concrete payload ("a gotcha, setup detail, or other durable context"), and immediately distinguishes itself from `log_issue` and `add_decision` by the "doesn't fit as an issue or decision" clause. An agent can classify a candidate note correctly without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear use trigger ("when you discover something important") plus an explicit exclusion (things that fit as an issue or decision), which routes the agent toward the siblings. It stops short of naming `log_issue`, `add_decision`, or `get_global_gotchas` outright, so the alternative is implied by category rather than named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
current_projectA
Show which project a call would resolve to, without writing anything.
Use this before a write when several projects are in play — it answers "where would this land?" cheaply. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Which project this call is about — a registered id, alias, or absolute path (e.g. 'ossdrop'). Omit it when the server was started for a single repo, or when an active project is set with `pjm project use`. Call list_projects to see the registered names. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden. It clearly discloses the read-only nature with 'without writing anything' and 'Read-only,' which is the key safety-relevant behavior for this tool. It also signals low cost ('cheaply'), giving agents confidence to call it during write planning.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, with the core action and the read-only guarantee front-loaded, and the usage context in the second sentence. No filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter read-only tool with an output schema, the description supplies the necessary usage context (before writes, multi-project situations) and the safety profile. The schema documents the parameter, and the output schema handles return shape, so nothing needed to call the tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already documents the single 'project' parameter at 100% coverage, including how to omit it. The description adds no parameter-specific detail beyond affirming the tool is about where a call would land, so a baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and object: 'Show which project a call would resolve to,' which precisely identifies the tool's function as a resolution check rather than a listing or mutation. The phrase 'without writing anything' further clarifies scope and separates it from sibling tools like list_projects or log_issue.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use it: 'before a write when several projects are in play,' and frames it as a cheap way to answer where a call would land. It doesn't name alternatives or when-not conditions, but the primary trigger is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_contextA
Generate a token-budgeted memory context block.
Use when you don't want to read the full summary. ``focus`` (e.g.
'src/auth/') biases the context toward a specific area.
Read-only; assembles a freshly-budgeted context block from
events.jsonl.| Name | Required | Description | Default |
|---|---|---|---|
| focus | No | Optional path prefix or keyword to bias selection toward (e.g., 'src/auth/'). When omitted, the context is project-wide. | |
| tokens | No | Approximate target token budget for the returned markdown (default 2000). Output may be slightly over or under as events are included as whole units. Recommended range: 500-8000. | |
| project | No | Which project this call is about — a registered id, alias, or absolute path (e.g. 'ossdrop'). Omit it when the server was started for a single repo, or when an active project is set with `pjm project use`. Call list_projects to see the registered names. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and it delivers: 'Read-only' explicitly rules out side effects, and 'assembles a freshly-budgeted context block from events.jsonl' discloses the data source and non-cached, freshly assembled nature. This is exactly the kind of behavioral context an agent needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: purpose first, use-case second, behavior note last. Every sentence earns its place; there is no fluff or repetition of schema details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description plus the fully-covered schema and existing output schema provide everything needed to decide when to call the tool, what parameters to pass, and what side effects to expect. The project parameter is handled by the schema, including a pointer to list_projects, so no critical guidance is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description's mention of focus only restates what the schema already documents ('Optional path prefix or keyword to bias selection toward'); it adds no meaning beyond the schema for tokens or project.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Generate a token-budgeted memory context block.' It clearly differentiates from get_summary by stating this is for when you don't want to read the full summary, so an agent can distinguish it from the most similar sibling without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit condition: 'Use when you don't want to read the full summary.' This implies get_summary as the alternative and covers the main routing concern, though it does not name the sibling tool explicitly or list when-not-to-use cases.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_global_gotchasA
Query cross-project library gotchas from ~/.projectmem/global/.
Returns lessons learned in past projects that apply to the libraries
you're about to use. Call whenever working with an unfamiliar library
or starting a new feature.
Read-only. Reads from ~/.projectmem/global/ (cross-project memory,
not this repo's .projectmem/).| Name | Required | Description | Default |
|---|---|---|---|
| library | No | Optional library name to filter by (case-insensitive substring match — 'react' also matches 'react-router'). When omitted, returns all gotchas across every library — useful when starting a new feature to scan for any relevant past lessons. | |
| project | No | Which project this call is about — a registered id, alias, or absolute path (e.g. 'ossdrop'). Omit it when the server was started for a single repo, or when an active project is set with `pjm project use`. Call list_projects to see the registered names. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral burden. It clearly states the operation is read-only, names the exact source location, and clarifies that it reads cross-project memory rather than the repo's own .projectmem/. This is solid transparency for a read-only query tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences front-load the main action and source, followed by usage guidance and safety context. There is minor redundancy between 'Read-only' and the subsequent 'Reads from' clause, but no wasteful filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers what the tool does, when to call it, the source path, and the read-only safety property. Since an output schema exists and the parameter schemas are rich, nothing critical is missing for an agent to select and invoke this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and both parameters already have detailed descriptions in the schema (case-insensitive substring match for library, project resolution for project). The tool description does not add parameter-specific semantics, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb ('Query') and a specific resource ('cross-project library gotchas' from ~/.projectmem/global/), and it explicitly contrasts with this repo's .projectmem/. The focus on library gotchas makes it clearly distinct from siblings like get_summary or get_project_map.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides an explicit trigger: 'Call whenever working with an unfamiliar library or starting a new feature.' It does not, however, name sibling alternatives or provide when-not-to-use exclusions, so it falls slightly short of a perfect score.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_instructionsA
Read the project's mandatory AI instructions.
MANDATORY: call this at session start. The instructions describe the
workflow rules you MUST follow while working in this project — they
are not advisory.
Read-only; does not modify memory.| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Which project this call is about — a registered id, alias, or absolute path (e.g. 'ossdrop'). Omit it when the server was started for a single repo, or when an active project is set with `pjm project use`. Call list_projects to see the registered names. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure. It explicitly states 'Read-only; does not modify memory,' which covers the main safety-relevant behavior. It could add more context about what happens if no instructions exist or whether the returned content is cached, but the simple read-only trait is transparently disclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is short and front-loaded with the core purpose, followed by the mandatory usage instruction and a read-only safety note. The repetition of 'MANDATORY' and 'MUST' is somewhat redundant, but the text is still efficient and every sentence contributes useful information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple, low-complexity tool with one optional parameter, a detailed schema, and an output schema, this description is complete. It tells the agent why this tool exists, when it must be called, and that it is side-effect-free. Nothing essential is missing for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema provides 100% coverage of the single optional parameter, including when to omit it and how to resolve a project identifier. The description adds no parameter-specific detail, so baseline 3 is appropriate since the schema already takes care of documenting the parameter fully.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the exact action ('Read') and resource ('the project's mandatory AI instructions'), and its emphasis that these are mandatory workflow rules distinguishes it from sibling information tools like get_summary or get_project_map. This is specific, actionable, and immediately tells an agent what the tool is for.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly commands calling this tool at session start, states that the instructions are not advisory, and makes clear the agent MUST follow the returned rules. This is stronger and more explicit than a mere contextual hint; it tells the agent exactly when and how the tool should be used, leaving no ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_issueA
Read one specific issue's full history by ID (token-efficient).
Use this when you only need one issue's context instead of the whole
summary. Example: get_issue('0042').
Read-only.| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Which project this call is about — a registered id, alias, or absolute path (e.g. 'ossdrop'). Omit it when the server was started for a single repo, or when an active project is set with `pjm project use`. Call list_projects to see the registered names. | |
| issue_id | Yes | Zero-padded 4-digit issue ID returned by log_issue (e.g., '0042'). Numeric strings without padding (e.g., '42') are also accepted. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the safety burden. It explicitly states 'Read-only,' which is a meaningful behavioral disclosure for an agent deciding whether a call is safe. It also mentions 'token-efficient' and 'full history,' giving useful behavioral context beyond a bare schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded with the core action, followed by a usage condition and a concrete example. Every sentence earns its place, and there is no redundant restatement of schema fields.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
This is a simple read tool with only two parameters, both fully documented in the schema, and an output schema is present. The description closes the remaining gaps by stating use case, example, and read-only behavior, so an agent has enough to select and invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the schema already explains both issue_id and project in detail. The description adds only a concrete call example with get_issue('0042'), which reinforces but does not materially extend the schema meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Read one specific issue's full history by ID'. It also functionally distinguishes itself from the sibling summary tool by saying it provides one issue's context 'instead of the whole summary', so an agent can tell it apart from get_summary.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a clear usage condition: 'Use this when you only need one issue's context instead of the whole summary.' It implies the alternative is a summary-level tool, aligning with get_summary, though it does not explicitly name the sibling or state when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_planA
Read plan.md — the project's INTENT file (ideas + plans).
Call this at session start alongside get_summary(). plan.md records what
the team MEANS to do (ideas, active plans, next steps) — distinct from
the event log, which records what HAPPENED. When the user shares an idea
or a plan, edit plan.md directly (add a bullet, check items off, move
done work to Shipped); do NOT log plans as events.
Read-only. Returns 'No plan found.' if plan.md hasn't been initialized.| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Which project this call is about — a registered id, alias, or absolute path (e.g. 'ossdrop'). Omit it when the server was started for a single repo, or when an active project is set with `pjm project use`. Call list_projects to see the registered names. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the behavioral burden and meets it: it states 'Read-only' and discloses the edge-case return value, "Returns 'No plan found.' if plan.md hasn't been initialized." This is the key behavioral information an agent needs for a simple file-read tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose in the first sentence and every subsequent sentence adds distinct value: session-start usage, intent-vs-event distinction, editing guidance, read-only behavior, and missing-file result. There is no redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-optional-parameter read tool with an output schema, the description fully covers what the tool does, when to invoke it, how it relates to other data sources, and its behavior on uninitialized input. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the one optional project parameter is already fully documented in the schema with format, aliases, and omission rules. The description adds no parameter-specific meaning, which matches the baseline for complete schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description opens with 'Read plan.md — the project's INTENT file', giving a specific verb and resource. It clarifies the semantic scope by distinguishing plan.md (what the team MEANS to do) from the event log (what HAPPENED), so it is not confused with event-log read tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly states when to call it: 'Call this at session start alongside get_summary().' It also gives a when-not instruction: when the user shares an idea/plan, edit plan.md directly and 'do NOT log plans as events', preventing misuse of event-log tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_project_mapA
Read PROJECT_MAP.md to understand the repo structure.
Call this at session start when structure matters (file layout,
entry points, ownership). Cheaper than scanning the filesystem.
Read-only. Returns 'No project map found.' if PROJECT_MAP.md hasn't
been initialized — run `pjm init` first if so.| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Which project this call is about — a registered id, alias, or absolute path (e.g. 'ossdrop'). Omit it when the server was started for a single repo, or when an active project is set with `pjm project use`. Call list_projects to see the registered names. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations supplied, the description carries the full burden and does well: it declares 'Read-only,' specifies the exact return message when PROJECT_MAP.md is missing, and notes the prerequisite to run `pjm init` first. It also adds a performance trait ('Cheaper than scanning the filesystem').
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three concise sentences, each with a distinct purpose: what it does, when to use it, and its read-only/missing-file behavior. No filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-optional-parameter read tool with a full output schema, the description covers the important operational details: when to call it, read-only nature, missing-file behavior, and initialization prerequisite. The parameter semantics live in the schema, so nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already documents the optional project parameter in depth (registered id, alias, path, omit conditions, and a pointer to list_projects), and coverage is 100%. The description adds no parameter-specific guidance, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource ('Read PROJECT_MAP.md') and explains its purpose ('understand the repo structure'). It further distinguishes this tool from filesystem traversal by noting it is 'Cheaper than scanning the filesystem,' and its unique focus on file layout, entry points, and ownership separates it from sibling tools like get_summary or get_context.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit timing ('Call this at session start') and conditions ('when structure matters'), and names an alternative approach (filesystem scanning) with a cost comparison. It does not explicitly list when-not-to-use cases, but the conditional 'when structure matters' implies the boundary, so clear context but no formal exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_scoreA
Get the project's failure-prevention score.
Returns an A+→F grade with concrete ROI numbers: debugging hours
saved, tokens prevented, dollars protected. Use when the user asks
about progress or value.
Read-only; computes the score from events.jsonl on each call.| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Which project this call is about — a registered id, alias, or absolute path (e.g. 'ossdrop'). Omit it when the server was started for a single repo, or when an active project is set with `pjm project use`. Call list_projects to see the registered names. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
There are no annotations, so the description carries the behavioral burden. It explicitly says 'Read-only' and 'computes the score from events.jsonl on each call,' which tells the agent the tool is safe and reflects current data rather than cached results. It does not discuss failure modes or file-missing behavior, but for a simple read-only computation the disclosure is strong.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three short, purposeful sentences: what it does, what it returns, when to use it, and how it behaves. The most important info is front-loaded, with no filler or repetition of schema details. It is concise without being under-specified.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given that the output schema exists, the description does not need to explain return shape in detail, yet it already summarizes the grade and ROI components. The optional parameter is fully documented in the schema, and the description covers usage timing and read-only behavior. Nothing essential is missing for an agent to call this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Parameter schema coverage is 100%, and the schema description already explains the optional 'project' parameter, its default, when to omit it, and how to discover valid values via list_projects. The tool description adds no new parameter semantics, so the baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Get the project's failure-prevention score.' It clarifies what the tool produces (an A+→F grade plus ROI numbers), making it easy to distinguish from siblings like get_summary or get_context. This is more than a tautology and directly supports correct selection.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description states clearly when to use it: 'Use when the user asks about progress or value.' It does not explicitly name alternative tools or provide when-not-to-use guidance, but the when-to-use condition is concrete and actionable. The read-only note also helps set expectations.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_summaryA
Read the project memory summary.
MANDATORY: call this BEFORE answering ANY question about the project.
Do NOT answer from conversation history alone.
Do NOT re-scan source files (package.json, README, src/) to understand
the project — `summary.md` is the distilled authoritative source and
stays bounded as the project ages (a few hundred tokens on a young
project, a few thousand on an aged one), far less than re-deriving it.
Your prior assumptions about this project may be stale. Call this
cheaply at session start (and again before ending) to verify your
work is recorded.
Read-only; does not modify memory or trigger event logging.| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Which project this call is about — a registered id, alias, or absolute path (e.g. 'ossdrop'). Omit it when the server was started for a single repo, or when an active project is set with `pjm project use`. Call list_projects to see the registered names. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations present, the description carries the full burden, and it delivers the key traits: read-only, does not modify memory, does not trigger event logging, and returns a size-bounded payload that grows only modestly with project age. It omits error/empty behavior (e.g. what happens for an unregistered project) and any latency or rate context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose is front-loaded in the first line and the guardrails are short and scannable. There is mild redundancy — the staleness point and the 'don't re-derive' point are restated across the middle and final paragraphs — but the emphasis is defensible for a mandatory-call tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return shape need not be explained, and the one optional parameter is fully covered by the schema. What remains missing is how this tool relates to sibling memory-read tools (map, plan, instructions) and what it returns when no summary exists yet.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single `project` parameter is fully documented in the schema, including alias/path forms and when to omit it. The description adds nothing about the parameter, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb and resource ('Read the project memory summary') and characterizes the resource as a bounded, distilled `summary.md`. It does not, however, distinguish itself from close siblings like get_project_map, get_plan, or get_instructions, which an agent could reasonably confuse with a 'summary' read.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It is unusually explicit about when to call: before answering any project question, at session start, and again before ending. It also names what to do instead of this tool ('Do NOT re-scan source files') and warns against the wrong alternative ('Do NOT answer from conversation history alone').
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_projectsA
List the projects this server can reach, and which one is active.
Call this when a tool answers "No project selected", or when you need the
exact name to pass as `project`. Read-only; touches no project memory.| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so the description carries full behavioral burden. It discloses 'Read-only; touches no project memory', which is a meaningful side-effect guarantee the agent could not infer from the schema. It also reveals the output's key trait (active project) beyond a mere listing.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences in logical order: what it does, when to call it, and its safety guarantee. Every sentence earns its place; the trigger conditions are front-loaded and the read-only note closes it efficiently.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter list tool with an output schema present, the description covers what is returned, the two scenarios that warrant calling it, and the safety profile. Nothing an agent needs to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Tool has 0 parameters, so the baseline is 4. The schema is an empty object and the description appropriately doesn't invent parameter details. Mentioning the `project` parameter of other tools is contextual routing guidance, not parameter documentation, and it aids correct invocation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('List'), a defined resource ('projects this server can reach'), and the distinguishing output ('which one is active'). This differentiates it from the sibling current_project, which presumably returns only the active project rather than the full set.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit trigger conditions: 'Call this when a tool answers "No project selected"' and 'when you need the exact name to pass as `project`'. It gives clear context for when to invoke, though it doesn't name sibling alternatives or spell out when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
log_issueA
Open a new issue. Returns the issue ID.
MANDATORY: call this IMMEDIATELY when you encounter a bug, regression,
or unexpected behavior — BEFORE writing fix code. Logging up-front
means the issue survives interruptions and session boundaries.
Side effects: appends an `issue` event to .projectmem/events.jsonl,
creates an issue file in .projectmem/issues/, updates summary.md,
and marks this issue as the active one for subsequent
record_attempt calls.| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Which project this call is about — a registered id, alias, or absolute path (e.g. 'ossdrop'). Omit it when the server was started for a single repo, or when an active project is set with `pjm project use`. Call list_projects to see the registered names. | |
| summary | Yes | One-line description of the bug or unexpected behavior. Becomes the issue title and is matched by search_events. Keep it under 140 characters. | |
| location | No | Optional file path or component where the issue manifests (e.g., 'src/auth.py' or 'login/double-submit'). Used by precheck_file to surface this history later. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and does so: it enumerates every side effect (appends to events.jsonl, creates a file under issues/, updates summary.md) and the stateful consequence of marking the issue active for record_attempt. That is exactly the write-scope information an agent needs before mutating persistent project memory.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the action and return value, then the mandatory trigger, then side effects. The capitalized MANDATORY block is justified because it encodes a hard behavioral requirement, and the one-line rationale for it earns its space by explaining why up-front logging matters.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return details need not be repeated, and the description still flags the returned issue ID. Combined with full schema coverage and complete side-effect disclosure, nothing an agent needs to invoke this correctly — scope, timing, persistence effects, downstream coupling — is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the parameters are already fully documented, including the project resolution rules and the summary/location usage hints. The description adds no additional parameter-level meaning beyond what the schema states; it focuses on workflow and side effects instead, which is the correct baseline of 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("Open a new issue") and the return value ("Returns the issue ID"), which separates it from read-side siblings like get_issue and from follow-up writers like record_attempt/record_fix. An agent knows immediately this is the creation entry point of the issue workflow.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit trigger conditions are given ("when you encounter a bug, regression, or unexpected behavior") along with an ordering constraint ("BEFORE writing fix code") and the rationale for that ordering. It also names the downstream relationship to record_attempt, so the agent understands where this fits in the sequence rather than guessing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
precheck_fileA
Check a file's failure history BEFORE modifying it.
MANDATORY: call this BEFORE proposing any change to a file.
Surfaces failed past approaches, unresolved issues, and high churn
so you don't repeat known dead-ends. Cheap (~100 tokens) and prevents
expensive re-debugging cycles.
Read-only; does not modify memory.| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Which project this call is about — a registered id, alias, or absolute path (e.g. 'ossdrop'). Omit it when the server was started for a single repo, or when an active project is set with `pjm project use`. Call list_projects to see the registered names. | |
| file_path | Yes | Project-relative or absolute file path to check (e.g., 'src/auth.py'). Matched against the `location` field of logged events — no file content is read from disk. Returns 'no warnings' if the file has no failure history. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and meets it: it discloses read-only behavior, no memory modification, what the tool surfaces (failed approaches, unresolved issues, high churn), and approximate cost. This gives the agent an accurate safety and side-effect profile.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: the core purpose and mandatory instruction appear first, followed by cost, output value, and safety in short sentences. No sentence is filler; every sentence contributes to correct usage.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter, single-required-field tool with a rich output schema and no annotations, the description provides all needed context: when to use it, what it surfaces, cost, and side-effect safety. Nothing critical is missing for an agent to select and invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and both parameters are richly documented in the input schema, including project resolution and file_path matching semantics. The main description adds no additional parameter-level meaning, so this sits at the high-coverage baseline of 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence names a specific verb and resource — checking a file's failure history before modification — which clearly differentiates it from the generic sibling tools like search_events or get_issue. The focus on per-file past failures and churn makes the tool's purpose unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly instructs agents to call this tool before proposing any change to a file and explains why: to avoid repeating failed approaches and expensive re-debugging. It does not name excluded cases or alternative tools, but the when-to-use guidance is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
record_attemptA
Record a fix attempt on the current issue.
MANDATORY: call IMMEDIATELY after each distinct fix attempt — do NOT
batch multiple attempts into one call.
`outcome` must be 'worked', 'failed', or 'partial'. Pass `issue_id`
explicitly to attach to a specific issue; otherwise the attempt
attaches to the active issue. If no active issue exists, an implicit
parent issue is auto-created from this attempt's text (L-008).
Side effects: appends an `attempt` event and updates the issue file.
Does NOT close the issue — call record_fix for that.| Name | Required | Description | Default |
|---|---|---|---|
| outcome | No | Result of the attempt. Must be exactly one of 'worked', 'failed', or 'partial'. Defaults to 'failed' — the safer default when an outcome is uncertain. | failed |
| project | No | Which project this call is about — a registered id, alias, or absolute path (e.g. 'ossdrop'). Omit it when the server was started for a single repo, or when an active project is set with `pjm project use`. Call list_projects to see the registered names. | |
| summary | Yes | One-line description of what you tried (e.g., 'tried contain: layout — preview still jumps'). Put further evidence into another attempt, not this one. Keep it under 300 characters: summary.md clips longer text. | |
| issue_id | No | Optional zero-padded issue ID (e.g., '0042') to attach this attempt to. When omitted, attaches to the active issue; if no active issue exists, an implicit parent issue is auto-created from this attempt's text. | |
| location | No | Optional file path or component touched by this attempt. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With zero annotations, the description carries the full burden and does so: it declares the writes ("appends an `attempt` event and updates the issue file"), the latent side effect (implicit parent issue auto-created when no active issue exists), and the operation it does not perform. Minor omissions exist (idempotency, error behavior) but the mutation surface is disclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the action and the mandatory timing rule, then side effects and the boundary with record_fix. Every clause is functional; the internal reference "(L-008)" is the only noise an agent cannot act on.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 5-parameter mutation with no annotations, the description covers trigger, scoping fallback, written artifacts, and the excluded follow-up, while the output schema covers return values and the schema covers field syntax. Nothing needed to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema already specifies the outcome enum/pattern, the issue_id fallback chain, and the summary length guidance. The description largely restates those constraints (allowed outcome values, issue_id vs. active issue) rather than adding format or precedence detail, so it earns the baseline for a fully documented schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("Record a fix attempt") and immediately bounds it against the sibling that does more: "Does NOT close the issue — call record_fix for that." An agent can distinguish record_attempt from record_fix, log_issue, and search_events without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit trigger ("call IMMEDIATELY after each distinct fix attempt") plus an explicit anti-pattern ("do NOT batch multiple attempts into one call"), and names the alternative tool for the adjacent need. When-to-use and when-not-to-use are both present with no inference required.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
record_fixA
Record a confirmed fix and close an issue.
Only call AFTER you have evidence the fix works: test passes, error is gone,
or the user confirmed.
If `issue_id` is provided, the fix is attached to that specific issue.
If `issue_id` is omitted, the active issue is closed.
Side effects: appends a `fix` event and updates summary.md. The active-issue
marker is cleared only when the active issue is the issue being fixed.| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Which project this call is about — a registered id, alias, or absolute path (e.g. 'ossdrop'). Omit it when the server was started for a single repo, or when an active project is set with `pjm project use`. Call list_projects to see the registered names. | |
| summary | Yes | One-line description of the confirmed fix (e.g., 'guarded submit handler with isSubmitting ref'). Keep it under 300 characters. | |
| issue_id | No | Optional zero-padded issue ID (e.g., '0042') to close. When omitted, closes the active issue. Numeric strings without padding are accepted. | |
| location | No | Optional file path or component where the fix was applied. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so well by naming side effects: appends a `fix` event, updates summary.md, and conditionally clears the active-issue marker. It stops short of stating idempotency, whether re-recording a fix duplicates events, or any permission requirements.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, then precondition, then parameter branching, then side effects. Four short blocks with no redundant restatement of the title or schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with no annotations, the description covers purpose, gating precondition, per-parameter behavior, and side effects; return values are covered by the existing output schema. An agent has everything needed to decide and invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description adds real behavioral meaning: issue_id present means the fix attaches to that issue, absent means the active issue is closed. That conditional semantics goes beyond the schema's plain 'optional zero-padded issue ID' text.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource pair ('Record a confirmed fix and close an issue') and immediately clarifies the two modes of operation based on issue_id. An agent can distinguish this from log_issue or record_attempt without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides an explicit precondition gate: 'Only call AFTER you have evidence the fix works' with three concrete qualifying conditions (test passes, error gone, user confirmed). It does not name sibling alternatives such as record_attempt for unverified attempts, so the routing is implied rather than exhaustive.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_eventsA
Plain-text search across all logged events.
Token-efficient alternative to get_summary when you only need events
matching a keyword. Returns matching event summaries with type and
timestamp.
Read-only. Case-insensitive substring matching against each event's
summary and notes. Empty result returns a friendly message, not an
error.| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of matching events to return (most recent first). Defaults to 10. Recommended range: 1-100. | |
| query | Yes | Case-insensitive substring matched against each event's summary and notes. Plain text only — no regex or boolean operators. | |
| project | No | Which project this call is about — a registered id, alias, or absolute path (e.g. 'ossdrop'). Omit it when the server was started for a single repo, or when an active project is set with `pjm project use`. Call list_projects to see the registered names. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It states the operation is read-only, specifies case-insensitive substring matching against summary and notes, and explains that an empty result returns a friendly message rather than an error.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three short, front-loaded paragraphs. Every sentence adds value: the search scope, the alternative tool, the matching behavior, and the empty-result behavior. There is no filler or redundant restatement of the tool name.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the 100% schema coverage and presence of an output schema, this description is complete enough for an agent to call the tool correctly. It explains the search scope, the matching rules, the read-only nature, and how empty results are handled.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already documents all parameters with 100% coverage. The description mostly restates the query semantics already present in the schema rather than adding new parameter-level meaning, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: 'Plain-text search across all logged events.' It also clearly states the return value (matching event summaries with type and timestamp) and distinguishes itself from get_summary, making its purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly names get_summary as the alternative and gives the condition for choosing this tool: when you only need events matching a keyword. This is direct, actionable usage guidance with no need for inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v0.3.5- Changed
add_decision1 field changed- changed
Input schema / properties / summary / descriptionPrevious value: -"One-line description of the architectural or product decision (e.g., 'use bcrypt rounds=12 for password hashing'). Becomes part of the project's permanent record — write it for a future contributor."New value: +"One-line description of the architectural or product decision (e.g., 'use bcrypt rounds=12 for password hashing'). Becomes part of the project's permanent record — write it for a future contributor. Keep it under 300 characters: summary.md clips longer text."
- Changed
add_note1 field changed- changed
Input schema / properties / summary / descriptionPrevious value: -"One-line description of the gotcha, setup detail, or context worth preserving. Prefix with 'gotcha:' or 'lesson:' to enable cross-project promotion — e.g., 'gotcha: bcrypt v4 silently truncates passwords longer than 72 bytes'."New value: +"One-line description of the gotcha, setup detail, or context worth preserving. Prefix with 'gotcha:' or 'lesson:' to enable cross-project promotion — e.g., 'gotcha: bcrypt v4 silently truncates passwords longer than 72 bytes'. Keep it under 300 characters: summary.md clips longer text."
- Changed
log_issue1 field changed- changed
Input schema / properties / summary / descriptionPrevious value: -"One-line description of the bug or unexpected behavior (~140 chars recommended). Becomes the issue title and is matched by search_events."New value: +"One-line description of the bug or unexpected behavior. Becomes the issue title and is matched by search_events. Keep it under 140 characters."
- Changed
record_attempt1 field changed- changed
Input schema / properties / summary / descriptionPrevious value: -"One-line description of what you tried (e.g., 'tried contain: layout — preview still jumps')."New value: +"One-line description of what you tried (e.g., 'tried contain: layout — preview still jumps'). Put further evidence into another attempt, not this one. Keep it under 300 characters: summary.md clips longer text."
- Changed
record_fix1 field changed- changed
Input schema / properties / summary / descriptionPrevious value: -"One-line description of the confirmed fix (e.g., 'guarded submit handler with isSubmitting ref')."New value: +"One-line description of the confirmed fix (e.g., 'guarded submit handler with isSubmitting ref'). Keep it under 300 characters."
17 tool updates
v0.3.2- Changed
add_decision1 field changed- added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Which project this call is about — a registered id, alias, or absolute path (e.g. 'ossdrop'). Omit it when the server was started for a single repo, or when an active project is set with `pjm project use`. Call list_projects to see the registered names.", + "title": "Project" +}
- Changed
add_note1 field changed- added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Which project this call is about — a registered id, alias, or absolute path (e.g. 'ossdrop'). Omit it when the server was started for a single repo, or when an active project is set with `pjm project use`. Call list_projects to see the registered names.", + "title": "Project" +}
- Added
current_project - Changed
get_context1 field changed- added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Which project this call is about — a registered id, alias, or absolute path (e.g. 'ossdrop'). Omit it when the server was started for a single repo, or when an active project is set with `pjm project use`. Call list_projects to see the registered names.", + "title": "Project" +}
- Changed
get_global_gotchas1 field changed- added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Which project this call is about — a registered id, alias, or absolute path (e.g. 'ossdrop'). Omit it when the server was started for a single repo, or when an active project is set with `pjm project use`. Call list_projects to see the registered names.", + "title": "Project" +}
- Changed
get_instructions1 field changed- added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Which project this call is about — a registered id, alias, or absolute path (e.g. 'ossdrop'). Omit it when the server was started for a single repo, or when an active project is set with `pjm project use`. Call list_projects to see the registered names.", + "title": "Project" +}
- Changed
get_issue1 field changed- added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Which project this call is about — a registered id, alias, or absolute path (e.g. 'ossdrop'). Omit it when the server was started for a single repo, or when an active project is set with `pjm project use`. Call list_projects to see the registered names.", + "title": "Project" +}
- Changed
get_plan1 field changed- added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Which project this call is about — a registered id, alias, or absolute path (e.g. 'ossdrop'). Omit it when the server was started for a single repo, or when an active project is set with `pjm project use`. Call list_projects to see the registered names.", + "title": "Project" +}
- Changed
get_project_map1 field changed- added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Which project this call is about — a registered id, alias, or absolute path (e.g. 'ossdrop'). Omit it when the server was started for a single repo, or when an active project is set with `pjm project use`. Call list_projects to see the registered names.", + "title": "Project" +}
- Changed
get_score1 field changed- added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Which project this call is about — a registered id, alias, or absolute path (e.g. 'ossdrop'). Omit it when the server was started for a single repo, or when an active project is set with `pjm project use`. Call list_projects to see the registered names.", + "title": "Project" +}
- Changed
get_summary1 field changed- added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Which project this call is about — a registered id, alias, or absolute path (e.g. 'ossdrop'). Omit it when the server was started for a single repo, or when an active project is set with `pjm project use`. Call list_projects to see the registered names.", + "title": "Project" +}
- Added
list_projects - Changed
log_issue1 field changed- added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Which project this call is about — a registered id, alias, or absolute path (e.g. 'ossdrop'). Omit it when the server was started for a single repo, or when an active project is set with `pjm project use`. Call list_projects to see the registered names.", + "title": "Project" +}
- Changed
precheck_file1 field changed- added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Which project this call is about — a registered id, alias, or absolute path (e.g. 'ossdrop'). Omit it when the server was started for a single repo, or when an active project is set with `pjm project use`. Call list_projects to see the registered names.", + "title": "Project" +}
- Changed
record_attempt1 field changed- added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Which project this call is about — a registered id, alias, or absolute path (e.g. 'ossdrop'). Omit it when the server was started for a single repo, or when an active project is set with `pjm project use`. Call list_projects to see the registered names.", + "title": "Project" +}
- Changed
record_fix1 field changed- added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Which project this call is about — a registered id, alias, or absolute path (e.g. 'ossdrop'). Omit it when the server was started for a single repo, or when an active project is set with `pjm project use`. Call list_projects to see the registered names.", + "title": "Project" +}
- Changed
search_events1 field changed- added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Which project this call is about — a registered id, alias, or absolute path (e.g. 'ossdrop'). Omit it when the server was started for a single repo, or when an active project is set with `pjm project use`. Call list_projects to see the registered names.", + "title": "Project" +}
1 tool update
v0.2.0- Added
get_plan
1 tool update
v0.1.5- Changed
record_fix1 field changed- added
Input schema / properties / issue_idAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Optional zero-padded issue ID (e.g., '0042') to close. When omitted, closes the active issue. Numeric strings without padding are accepted.", + "title": "Issue Id" +}
1 tool update
v0.1.4- Changed
add_decision1 field changed- added
Input schema / properties / supersedesAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Optional event id (evt_...) of a prior decision this one retires. The old event stays in the log tagged (superseded); only the new decision appears in summary.md. Use when precheck_file flags a decision as possibly stale and you are revising it.", + "title": "Supersedes" +}
10 tool updates
v0.1.3- Changed
add_decision2 fields changed- added
Input schema / properties / location / descriptionAdded value: +"Optional file path or scope where the decision applies (e.g., 'src/auth/' for a module-level choice). Helps precheck_file cite the decision when the file is later touched." - added
Input schema / properties / summary / descriptionAdded value: +"One-line description of the architectural or product decision (e.g., 'use bcrypt rounds=12 for password hashing'). Becomes part of the project's permanent record — write it for a future contributor."
- Changed
add_note2 fields changed- added
Input schema / properties / location / descriptionAdded value: +"Optional file path or library this note applies to (e.g., 'bcrypt' for a library-specific gotcha)." - added
Input schema / properties / summary / descriptionAdded value: +"One-line description of the gotcha, setup detail, or context worth preserving. Prefix with 'gotcha:' or 'lesson:' to enable cross-project promotion — e.g., 'gotcha: bcrypt v4 silently truncates passwords longer than 72 bytes'."
- Changed
get_context4 fields changed- added
Input schema / properties / focus / descriptionAdded value: +"Optional path prefix or keyword to bias selection toward (e.g., 'src/auth/'). When omitted, the context is project-wide." - added
Input schema / properties / tokens / descriptionAdded value: +"Approximate target token budget for the returned markdown (default 2000). Output may be slightly over or under as events are included as whole units. Recommended range: 500-8000." - added
Input schema / properties / tokens / maximumAdded value: +20000 - added
Input schema / properties / tokens / minimumAdded value: +100
- Changed
get_global_gotchas1 field changed- added
Input schema / properties / library / descriptionAdded value: +"Optional library name to filter by (case-insensitive substring match — 'react' also matches 'react-router'). When omitted, returns all gotchas across every library — useful when starting a new feature to scan for any relevant past lessons."
- Changed
get_issue1 field changed- added
Input schema / properties / issue_id / descriptionAdded value: +"Zero-padded 4-digit issue ID returned by log_issue (e.g., '0042'). Numeric strings without padding (e.g., '42') are also accepted."
- Changed
log_issue2 fields changed- added
Input schema / properties / location / descriptionAdded value: +"Optional file path or component where the issue manifests (e.g., 'src/auth.py' or 'login/double-submit'). Used by precheck_file to surface this history later." - added
Input schema / properties / summary / descriptionAdded value: +"One-line description of the bug or unexpected behavior (~140 chars recommended). Becomes the issue title and is matched by search_events."
- Changed
precheck_file1 field changed- added
Input schema / properties / file_path / descriptionAdded value: +"Project-relative or absolute file path to check (e.g., 'src/auth.py'). Matched against the `location` field of logged events — no file content is read from disk. Returns 'no warnings' if the file has no failure history."
- Changed
record_attempt5 fields changed- added
Input schema / properties / issue_id / descriptionAdded value: +"Optional zero-padded issue ID (e.g., '0042') to attach this attempt to. When omitted, attaches to the active issue; if no active issue exists, an implicit parent issue is auto-created from this attempt's text." - added
Input schema / properties / location / descriptionAdded value: +"Optional file path or component touched by this attempt." - added
Input schema / properties / outcome / descriptionAdded value: +"Result of the attempt. Must be exactly one of 'worked', 'failed', or 'partial'. Defaults to 'failed' — the safer default when an outcome is uncertain." - added
Input schema / properties / outcome / patternAdded value: +"^(worked|failed|partial)$" - added
Input schema / properties / summary / descriptionAdded value: +"One-line description of what you tried (e.g., 'tried contain: layout — preview still jumps')."
- Changed
record_fix2 fields changed- added
Input schema / properties / location / descriptionAdded value: +"Optional file path or component where the fix was applied." - added
Input schema / properties / summary / descriptionAdded value: +"One-line description of the confirmed fix (e.g., 'guarded submit handler with isSubmitting ref')."
- Changed
search_events4 fields changed- added
Input schema / properties / limit / descriptionAdded value: +"Maximum number of matching events to return (most recent first). Defaults to 10. Recommended range: 1-100." - added
Input schema / properties / limit / maximumAdded value: +100 - added
Input schema / properties / limit / minimumAdded value: +1 - added
Input schema / properties / query / descriptionAdded value: +"Case-insensitive substring matched against each event's summary and notes. Plain text only — no regex or boolean operators."
14 tool updates
v0.1.1- First observed
add_decision - First observed
add_note - First observed
get_context - First observed
get_global_gotchas - First observed
get_instructions - First observed
get_issue - First observed
get_project_map - First observed
get_score - First observed
get_summary - First observed
log_issue - First observed
precheck_file - First observed
record_attempt - First observed
record_fix - First observed
search_events
TDQS
Scored across 17 tools
Each tool has a fairly distinct role, and the descriptions actively differentiate the read paths (get_summary vs. get_context vs. search_events vs. get_issue) and the write paths (log_issue vs. record_attempt vs. record_fix). The only real overlap is between list_projects and current_project, and between get_summary and get_context, but both pairs are explicitly contrasted in their text.
Most names follow a clean verb_noun snake_case pattern (get_summary, add_decision, record_fix, search_events). Minor deviations: current_project is noun-only with no verb, and the create-style verbs are mixed between 'log' (log_issue) and 'add' (add_decision, add_note), plus precheck_file reads as a bare verb prefix, but nothing is genuinely confusing.
17 tools is on the high side for a project-memory server, but nearly every tool maps to a distinct lifecycle step (read context, open issue, record attempt, record fix, persist decision/note, query history). The several read variants (summary, context, plan, map, instructions, score, gotchas) are justified by token-budgeting concerns rather than duplication.
The write lifecycle is well covered: issue -> attempt -> fix, plus decisions and notes, with reads for summary, plan, map, instructions, single issue, event search, context, and score. Gaps remain: there is no list_issues/enumerate-open-issues tool, no way to edit or supersede a note, and no delete/close-without-fix operation, though get_summary and search_events let agents work around most of these.
Maintenance
Related MCP Connectors
Shared memory for coding agents. Stop re-explaining your codebase every session.
One memory for every AI you work with: your rules, notes and decisions in your own Git repo.
Shared project memory for AI coding agents: decisions, lessons, risks and tasks in one graph.
Persistent engineering memory designed to follow developers across coding agents.
Related MCP Servers
- AlicenseNot gradedqualityNot gradedmaintenanceA robust server for managing long-term agent memory using Mem0, providing efficient storage and retrieval of agent memories with a lightweight Python-based implementation.MIT
- AlicenseAqualityDmaintenanceProvides versioned, structured memory for AI agents, allowing them to store facts, detect conflicts, and track knowledge history via a hosted SaaS platform. It enables efficient hierarchical information retrieval and semantic search while keeping token usage constant as memory scales.732 npm8Apache 2.0
- AlicenseAqualityFmaintenanceSelf-improving, verifiable memory for AI coding agents. Learns how you work, stops repeating mistakes, models each project, recalls the right lesson at the right moment. Every memory is signed and tamper-evident. Local-first.82Apache 2.0
- AlicenseAqualityDmaintenanceLocal-first project memory for AI coding agents. Records failed attempts, fragile files, and decisions per repo, and warns the agent via hooks before it repeats a recorded mistake.689 npmMIT