Coding agents notice things. Most of what they notice is lost.
Give a coding agent a bounded task and it will usually do the task. Along the way it reads more of the codebase than any one person would for the same change, and it sees things: a latent bug two files over, a metric nobody is recording, a query that will not survive ten times the data, an evaluation that only covers English. None of that is what it was asked to do. The question is what happens to it.
I kept seeing two answers, and both are bad. The first is to fix everything on the spot. The pull request grows, the scope drifts, and a change that should have been reviewable in ten minutes turns into an afternoon. The second is to say nothing. The observation evaporates when the session ends, and the next person to find the same problem finds it in production.
Grounded Register is the third answer. It gives AI-assisted development a durable place for the sentence I wanted agents to be able to say: this is not what I was asked to work on, but it matters.

The contract
The plugin is built around one rule about what qualifies. A finding is recorded only when it is:
- outside the requested scope;
- material enough to matter;
- grounded by a file-and-line reference, a test, a trace, a log, a runtime observation or a documented invariant;
- not a duplicate of an existing root cause.
An incidental finding is logged and left unfixed. Work continues. A finding that makes the current task unsafe or materially incorrect is logged as a blocking P0, the affected work stops, and Claude surfaces it.
That last line matters more than it looks. The register is not a dumping ground for hunches. Every entry has to point at evidence that another engineer can open, and the validator rejects entries that do not.
What the plugin contains
- A capture skill that decides whether an incidental observation qualifies, so the agent is not left to guess.
- A SessionStart hook that injects the operating contract into every session.
- A SubagentStart hook that tells delegated agents to return structured candidates rather than quietly fix unrelated issues.
- A Stop hook that validates new entries, regenerates the report, and checks that any changed finding IDs appear in the final response.
- A deterministic CLI that creates IDs, validates evidence, checks file-and-line references and renders the Markdown report.
- A standalone skill, a lighter version for people who do not want hooks.
It uses Node.js built-ins only. There are no runtime package dependencies, and it sends no project data to any external service.
Installing it
Inside Claude Code, add the marketplace and install the plugin:
/plugin marketplace add William-Harvey/grounded-register
/plugin install grounded-register@grounded-register-marketplace
Then open the project you want to use it in and initialise it:
/grounded-register:initialise
To try a local clone first, load the plugin directly and initialise it inside a disposable test repository:
git clone https://github.com/William-Harvey/grounded-register.git
cd grounded-register
claude --plugin-dir ./plugins/grounded-register
It needs Claude Code with plugin support and Node.js 18 or later. Git is recommended but not required.
The skills
| Skill | Purpose |
|---|---|
/grounded-register:initialise |
Create project configuration, findings storage and the report |
/grounded-register:capture |
Capture an evidence-backed incidental finding |
/grounded-register:validate |
Validate entries and evidence references |
/grounded-register:report |
Regenerate and summarise the Markdown report |
/grounded-register:triage |
Review evidence, duplicates, impact and readiness without fixing code |
/grounded-register:resolve |
Close a finding with verification evidence |
Only capture is available for the model to invoke on its own. The other workflows need an explicit request from you, which is deliberate: the agent can notice and record, but triage and resolution stay human decisions.
What it leaves in your project
Initialising creates a small folder for findings and a generated report:
.grounded-register/
├── config.json
├── .gitignore
└── findings/
├── .gitkeep
└── GR-20260709-7F3C.json
docs/
└── system-risk-improvement-register.md
Each finding is its own JSON file, which keeps merge conflicts to a minimum when several people or agents are working in the same repository. The Markdown report is generated from those records and should not be edited by hand.
Every finding records what was found, its type and category, whether it is incidental or blocking, the exact evidence, impact (critical, high or moderate), effort (S, M or L), priority (P0 to P3), status, whether it concerns production, evaluation or both, its relationship to the current task, why it was not fixed inline, a bounded next step, creation and update metadata, and resolution evidence when it is closed.
Reporting that cannot be skipped
When entries change, Claude's final response must include a Grounded Register section naming each changed ID, title, impact, scope and whether work continued or stopped. The Stop hook checks for it. The point is that a finding never lives only in a file nobody opens: the person who asked for the work hears about it in the same message that delivers the work.
The generated repository report includes executive totals, the P0 and P1 items needing immediate attention, the full set of evidence-backed open findings, the history of fixed, accepted and dismissed entries, and the register's own controls and quality references.
The validator
The deterministic validator rejects:
- missing required fields;
- invalid IDs and filenames;
- broken or unsafe file references;
- line ranges outside the referenced file;
- missing evidence;
- P0 findings that are not blocking, and blocking findings that are not P0;
- secrets or likely credentials;
- closed entries without resolution evidence;
- fixed entries without test or runtime verification.
It warns about duplicate titles, unsupported fields, weakly grounded speculative language, and questionable combinations of impact and priority.
The CLI is plain Node:
node plugins/grounded-register/scripts/grounded-register.mjs help
Its commands are init, new-id, template, add, validate, render, summary, list and doctor.
Configuration
Everything lives in one file in your repository:
{
"schema_version": 1,
"register_title": "System Risk & Improvement Register",
"findings_path": ".grounded-register/findings",
"report_path": "docs/system-risk-improvement-register.md",
"strict_stop_validation": true,
"require_commit_reference": false,
"require_resolution_test": true,
"quality_reference_files": []
}
Project-specific quality examples can be listed in quality_reference_files, so the capture skill can judge findings against your own standards rather than generic ones.
What it cannot do
The plugin cannot read Claude's hidden reasoning, and it cannot guarantee that every possible issue is noticed. It governs the findings Claude explicitly identifies during visible work. What it does is make those findings structured, grounded, durable and difficult to omit from the final report. That turned out to be most of what I wanted.
Why this one is open source
I built it for my own projects, where an agent that silently fixes an unrelated problem is as much of a worry as one that silently ignores it. The same tension exists in every team using coding agents, so the plugin is on GitHub under an open licence, with tests and a changelog.
The repository is at github.com/William-Harvey/grounded-register. Issues and pull requests are welcome, especially examples of findings the capture skill got wrong in either direction.
