An open-source Claude Code agent that audits an app end to end and hands back one risk-tiered report of everything broken, wasteful, exposed, slow, or invisible. Ten dimensions, from "does the primary button actually do anything" to "is there an API key in your git history." Every finding is calibrated to how mature the app is, because a missing sitemap on a day-one prototype and the same gap on a live product are not the same problem.
CODY checks and proposes. CODY never applies. Every finding in the report carries a suggested fix; deciding whether to take it, and making the change, stays with a human. That split is the design, not a limitation, and it is explained below.
It grew out of auditing a small fleet of side projects and is published as a reference implementation of a read-only agent with a capability boundary and stage-calibrated output. App auditing is the concrete example, but the pattern (measure, tier, propose, never apply) generalizes to any place you want an agent's judgment without its hands on the keyboard.
See the output before you run anything: examples/cody-report.example.md is a full report against a fictional app.
Three honest reasons to keep reading, so you can decide quickly whether this is for you:
- It covers a layer that is genuinely unserved. Linters read syntax and reviewers read diffs. Neither notices that your analytics beacon has been 404ing for six weeks, that a key was committed in January and is still reachable, or that a query which is instant at 300 rows becomes a table scan at 300,000. That is the layer CODY works on.
- The reusable idea is the constraint, not the checklist. Ten audit dimensions are easy to copy. The argument worth taking away is that an agent which can fix what it finds acquires an incentive to find things it can fix, and stops being a second opinion the moment it becomes a second author. That applies to any evaluating agent you build, in any domain.
- It is meant to be forked, not admired. The audit spec, the risk model and the house rules are plain Markdown and JSON, and the shipped conventions are explicitly somebody else's. docs/MAKE-IT-YOURS.md walks you through replacing them. There is a worked example report so you can judge the output before installing anything.
If you only take one thing: read the boundary and ignore the dimension list.
Everybody knows what a code review is for. Almost nobody has a good answer for the layer above it: the app works on your machine, the PR looked fine, and you still have no idea whether analytics has been silently dead for six weeks, whether there is a key in your git history from a commit in January, or whether the dashboard query that is instant at 300 rows becomes a full table scan at 300,000.
Those failures share a shape. They are invisible from inside the diff, they are boring to look for, and they are only discovered by someone deliberately going and checking. Which nobody does, because it takes a focused afternoon and produces nothing you can demo.
CODY is that afternoon, automated. It exercises the real thing rather than reading it: real clicks, real requests, real connection pings, because "analytics snippet is present" and "analytics works" are different claims and only one of them matters. Then it sorts everything by risk, so the fix order is the read order.
It is not built to replace a senior engineer, a code reviewer, or a security audit. It is built for the gap those people do not fill: the unglamorous sweep nobody schedules. If you have a great reviewer, this hands them a shorter list of better questions. If you are one person shipping alone, this is the closest thing to a second pair of eyes you are going to get at 11pm.
- Exercises the real app. Clicks every interactive element, hits every route, pings every external dependency. Anything mocked, stubbed, or unreachable is a finding rather than a skip
- Sweeps for secrets in the working tree and, on request, across every commit in history. Anything ever committed is HIGH and needs rotating, even if it is gone from HEAD, because the commit is still reachable
- Checks the things that fail silently: analytics that never reaches the collector, error tracking with a dead DSN, a pipeline that drops records without complaining, cache keys with no TTL quietly growing forever
- Calibrates to stage. Prototype, MVP, or production. The same finding lands in a different tier, and CODY states the stage so the tiers are auditable
- Grills on request. Adversarial mode assumes every design decision is wrong until defended, and produces questions rather than defects
- Writes one file.
cody-report.mdin the target app, grouped by risk, with an appendix by dimension so you can trend each one over time
| # | Dimension | The question |
|---|---|---|
| 1 | Functional | Does it work? |
| 2 | Data pipelines | Is data moving correctly? |
| 3 | Code quality & structure | Is the code clean? |
| 4 | Secrets | Is anything sensitive in the repo or its history? |
| 5 | Performance | Is it speedy? |
| 6 | Efficiency | Is it lean? Indexes, unbounded queries, pooling, TTLs |
| 7 | Observability | Can you see what users do and what breaks? |
| 8 | Discoverability | Will it show up, in search and in LLM answers? |
| 9 | Accessibility & compliance | Usable by everyone, and legal? |
| 10 | Grill | Would each decision survive being argued with? |
Full detail on what each one checks is in INSTRUCTIONS.md.
There is no service to deploy. CODY is a Claude Code agent: a spec, a persona, and three slash commands.
your target app (cwd)
│
▼
/cody-check ─────► .claude/agents/cody.md (persona + boundary)
/cody-secrets │
/cody-grill │ reads
▼
.claude/settings.json the deny list
INSTRUCTIONS.md the audit spec
config/dimensions.json what runs
config/risk-model.json how it is tiered
config/conventions.json your house rules
config/learned.json the ratchet (human-edited)
│
▼
./cody-report.md one file, grouped by risk
│
▼
(optional) SPRINT_BOARD_URL — run status PATCHed
to a shared kanban. Unset = no-op.
Read-only is enforced in three layers, in descending order of how hard they are to argue with:
- The tool list.
.claude/agents/cody.mdgrantsRead,Grep,Glob,BashandWebFetch. NoEdit, noWrite. A tool that was never handed over cannot be invoked. - The deny list.
Bashis the honest gap in layer 1: a shell can write..claude/settings.jsondenies the commands that would route around the missing tools:git add/commit/push/reset/checkout/stash,gh pr create,rm,mv,chmod, and the rest. Permission rules are evaluated by Claude Code before the call runs, so this layer does not depend on the model's cooperation either. - The prompt. The
## Neverlist in the persona covers what a pattern cannot: don't refactor, don't send real messages, don't print a full secret.
Be clear-eyed about what layer 3 is worth. It is a rule a model can talk
itself out of at 6am, which is exactly why the first two layers exist and why
the interesting work went into them. One residual gap stays open by design:
CODY writes cody-report.md through the shell, so shell redirection cannot be
denied outright, and a determined model could write elsewhere with it. Layers 1
and 2 make that require deliberate circumvention rather than a plausible
misreading of an instruction. If you need a guarantee rather than a boundary,
run CODY against a read-only checkout.
One thing to know before you clone. Permission rules in Claude Code are
project-wide, not per-agent, so the deny list constrains anything running in
this repo, including your own session. Edit and Write are deliberately left
out of it, because you need those to work on CODY and CODY was never granted
them. But git commit and friends are denied, so Claude Code cannot commit
here. Commit from your terminal, or drop the git entries if you would rather
have the convenience. That trade-off is the honest cost of layer 2, and
docs/MAKE-IT-YOURS.md §7 covers how to make the same
call for a target app.
git clone https://github.com/juliedemoyer/cody-coding-agent.gitThen either point Claude Code at this repo directly, or copy the agent into a project you want audited:
cp -r cody-coding-agent/.claude/agents/cody.md your-app/.claude/agents/
cp -r cody-coding-agent/.claude/commands/ your-app/.claude/From inside the target app:
/cody-check --stage mvp
/cody-secrets --history
/cody-grill
The report lands at ./cody-report.md. Before your first real run, answer
the questions in docs/MAKE-IT-YOURS.md, mostly
config/conventions.json, which is where your house rules go and which
ships with someone else's.
- Read-only is the whole design. No
Edit, noWrite, and a deny list over the shell. See the boundary for what each layer actually buys. CODY proposes a fix in the report'sactionfield; taking that suggestion is always a human decision, made outside the audit. - Stage calibration, not a fixed bar. A single severity scale produces reports where a prototype has 40 HIGH findings and you stop reading. The stage is declared or inferred, and always stated, so the tiers can be argued with.
- Test the real thing, or it is not a pass. Mocked verification is itself a finding. Most of the failures worth catching are invisible to static analysis and obvious the moment you actually click.
- Stop at a broken baseline. If the dev server will not start, CODY reports that and stops rather than generating 60 downstream findings. Volume from a broken baseline reads as thoroughness and is the opposite.
- One file, not a conversation. Findings go to
cody-report.md, never narrated in chat. A file can be diffed between runs, and a chat log cannot. - Uncertainty resolves downward. If CODY cannot tell whether something is a bug or intentional, it tiers it LOW. A confident wrong HIGH costs more trust than a quiet LOW costs coverage.
- It ratchets, and a human holds the ratchet.
config/learned.jsonaccumulates suppressions, promoted conventions, and per-repo severity calibration, so the same argument never happens twice. CODY proposes entries at the end of each report; you paste in the ones you agree with. It never writes that file, because an auditor that can edit its own rules can make its findings disappear. - Checks the live source when the answer moves. CVEs, deprecated APIs,
current framework guidance: training data has a cutoff and the ecosystem
does not, so those get a
WebFetchand a citation rather than a confident guess. - Truncated secrets, always. Reports show the first six characters and nothing more, because a report full of live credentials is a new problem rather than a solution to the old one.
| File | Controls |
|---|---|
config/dimensions.json |
Which dimensions run, and the grill heuristics |
config/risk-model.json |
Stage definitions, tier meanings, stop conditions |
config/conventions.json |
Your house rules. Ships with an example set: replace it |
config/learned.json |
The ratchet: suppressions, promoted conventions, retuned tiers. Grows one accepted proposal at a time |
INSTRUCTIONS.md |
The full audit spec: what each dimension actually checks |
.claude/agents/cody.md |
The persona, and the tool list that is layer 1 of the boundary |
.claude/settings.json |
The deny list: layer 2 of the boundary. Project-wide, so read the boundary before copying it into an app you also work in |
config/conventions.json is the one that repays real thought. It is where
"we always do X" becomes a check, and the shipped set is somebody else's
conventions.
- CODY does not write to the target: no edits, no commits, no PRs, nothing
destructive. Don't take that on trust. It is two files and a minute's
reading: check the
tools:line of.claude/agents/cody.mdand the deny list in.claude/settings.json, and read the boundary for the one gap those two leave open, before pointing it at a repo you care about. - Reports never contain a full secret. First six characters, then
.... Check this before pasting a report anywhere, including into an issue. cody-report.mddescribes your app's weaknesses in detail, including unfixed HIGH findings. It is gitignored here by default. Think before committing one to a public repo.--historyreads your entire git history. Run it on repos you own.- The secrets sweep is pattern-based. It will miss a credential that does not look like one, and it will flag test fixtures that do. It reduces the odds of an accident; it is not a guarantee, and it is not a penetration test.
CODY runs perfectly well alone. It was built as one member of a small fleet
of domain agents that coordinate through a shared Markdown vault and a shared
kanban board. Set SPRINT_BOARD_URL and CODY PATCHes run status there after
every audit; leave it unset and the call is a clean no-op.
Sibling repos:
- josh-career-agent: a daily-autonomous career transition agent
- One-page overview: three-page visual summary (PDF). The HTML version is at
docs/one-pager.html; enable GitHub Pages (Settings → Pages → deploy from/docs) to serve it live - INSTRUCTIONS.md: the full audit spec, dimension by dimension
- docs/MAKE-IT-YOURS.md: the questions to answer before your first run
- examples/cody-report.example.md: a full report against a fictional app
- CLAUDE.md.example: runtime operations, if you want CODY on a schedule
MIT. See LICENSE.