pm
An operating discipline for AI coding agents
Persistent memory · Enforced workflow · Recorded decisions
You install it. Claude lives inside it. pm sits between your coding agent and your codebase — enforcing planning before edits, tracking scope, and recording every choice so the next session doesn't redo what the last one figured out.
$ npm install -g @piotrjura/pmView on GitHub →Free · Open source · MIT · Local-first · No telemetry
Every session, your agent starts from zero. It re-derives the same architecture, makes the same tradeoffs, and re-asks questions you already answered. pm injects prior decisions and workflow rules into every prompt via Claude Code hooks — context the agent sees whether it asks for it or not.
Three things pm enforces
Implemented as Claude Code hooks — hard-blocks on edits and prompt injection on every interaction.
Memory
- ▸Decisions, rationale, and history persist across sessions in .pm/
- ▸pm decide records every choice with what, why, and how to apply it
- ▸pm why searches the archive before re-deriving
- ▸Relevant decisions auto-injected into every prompt
Discipline
- ▸Two-phase work: Discovery (plan, ask, align) → Execution (autonomous)
- ▸Configurable planning, questions, and follow-up depth per project
- ▸At the strongest setting, edits hard-block until required doctrines are read
- ▸Settings appear in every prompt so the agent can't drift mid-feature
Guardrails
- ▸Edit without logged work? Blocked.
- ▸Issue grows past 4 files? Blocked — upgrade to a feature.
- ▸3+ reads without delegating? Subagent nudge surfaced.
- ▸Stale state, orphaned tasks? Auto-recovered on session start.
What the agent sees
When the agent tries to edit a file but hasn't pulled the doctrines your settings require, the pre-edit hook returns this:
At the strongest settings, this is a hard-block — the pre-edit hook returns an error and the agent cannot write to any file until it runs the listed commands.
What a session with pm looks like
- 1
Session starts
pm injects the doctrine router into context, briefs Claude on what's in progress, and resets the doctrine pull tracker. Claude sees the active task, recent work, and every recorded decision waiting to be searched.
- 2
You give a prompt
The prompt-context hook fires. Claude sees the active work, your workflow settings (
planning=all, questions=thorough, followup=thorough), relevant decisions matched against your prompt, and — if required doctrines weren't pulled yet — aBLOCKINGnotice with the exact commands to run. - 3
Doctrines pulled
Each
pm doctrine <name>call is recorded silently. Once all required doctrines are read, the pre-edit hook unblocks. - 4
Discovery
Claude reads the planning doctrine, runs
pm recap, runspm why "<keyword>"against past decisions, presents an approach, asks clarifying questions per your settings, and waits for your confirmation. - 5
Execution
Tasks are created. Claude starts the first one and writes code. Each edit is allowed because there's active work. Each scope creep past 4 files is hard-blocked. Each Read and Grep is counted — past 3, the prompt-context surfaces a nudge to delegate exploration to a subagent.
- 6
Decisions recorded
Every choice future-you would benefit from knowing gets logged with
pm decide— what, why, and how to apply it. The next session will see them. - 7
Sweep
pm sweepcloses outstanding items at the end of the conversation. Issues, stale tasks, orphaned drafts — gone. Every session leaves the project clean.
Decisions are always on
A decision is a five-line record: what you chose, why, and what future sessions should do about it. There is no toggle — decisions are recorded and surfaced on every prompt regardless of settings.
The prompt-context hook also surfaces matching decisions on every prompt — Claude rarely runs pm why on its own, so pm pushes them in.
Ten focused docs, pulled on demand
Small markdown files. The router is always loaded; the rest are pulled with pm doctrine <name>. Each pull is tracked, and the strongest settings hard-block edits until the right ones are read.
Five hooks in .claude/settings.json
pm writes these into .claude/settings.json on first run and re-verifies them on every invocation. They merge with your existing hooks. If any are missing, pm restores them.
Three settings, per project
Run pm settings to cycle. The values appear in every prompt-context injection so the agent can't drift away from your configured depth mid-feature.
How aggressively the agent must plan before writing any code.
How many initial clarifying questions during Discovery.
How deep the post-analysis follow-up conversation goes.
Everything stays on your machine
All state lives in .pm/ as JSON files. No database, no server, no network calls, no telemetry.
.pm/data.json.pm/config.json.pm/session.json.pm/doctrine-session.jsonAdd .pm/ to your .gitignore and you're done.
Two commands
.pm/, hooks, permissionEvery subsequent pm invocation re-verifies the hooks and silently restores them. Read the docs →
Sign up
Release notes, doctrine changes, new hooks. Never any spam.