How to Run a Claude Repo Audit Your Clients Would Pay a Consultant to Do
One prompt turns a repo read into a findings report and a work plan your models execute, so one person delivers what a review board delivers. A scoped ai repo audit prompt comes back three findings deep with a P0 webhook hole at the top and every fix already assigned, where the unscoped version returns forty style nits.
>This is the first deliverable. Claude Fable 5 turns the audit into a plan, a handoff contract, and a metered ledger that proves which seat should have done each fix.

Hello builders,
One prompt turns a repo read into the two things a consultant hands a client: a findings report with the P0 at the top, and a task list where every fix is already assigned to the model that should do it. Unscoped, the same request comes back with forty style nits and twelve dollars on the bill while the webhook signature never gets verified; scoped, it is 3 findings and 4 tasks for about a dollar sixty. That is what an ai repo audit prompt is for, and there is no --audit flag behind any of it: an audit is a prompt plus the model’s ordinary ability to read your files, grep, and run commands in the repo.
So the structure of the prompt is doing all the work, and we are going to build the version that gets you the second number.

Three findings and four tasks. Not forty. That length is the point, and the prompt below is what produces it.
The four-phase prompt
Save this as audit-prompt.md. Each phase does one job, and the whole thing is analysis-only.
You are a senior staff engineer auditing this repository. Do NOT edit any
files. Your entire output is a written report. Ground every single claim in
a specific file:line reference. If you cannot point to a line, do not make
the claim.
Work in four phases and label them in your output.
## Phase 1 - Discovery
Map the codebase before judging it. List the entry points, the main data
flow, the external boundaries (APIs, webhooks, the database, third-party
calls), and where untrusted input enters the system.
## Phase 2 - Audit
Find real problems. For each finding, give exactly:
- WHAT: the problem, in one sentence
- WHERE: file:line
- WHY: the concrete consequence if left alone
- SEVERITY: P0 (ships-broken / security) - P1 (serious) - P2 (should fix)
- P3 (nit)
Do not pad the list. A short list of real P0s beats a long list of P3s.
## Phase 3 - Improvement strategy
Group the findings into themes (e.g., "input validation," "error handling").
For each theme, state the shape of the fix in two sentences.
## Phase 4 - Task plan
Turn the findings into an ordered task list. For each task give a size
(S/M/L/XL), a milestone bucket (M0 do now, M1, M2, M3), and an OWNER
MODEL: the cheapest model that can safely execute this fix. Use Haiku for
mechanical edits, Sonnet for specified logic, Opus or Fable ONLY where the
fix itself requires real judgment.
Output the whole report as markdown.
Two constraints in there do almost all of the work, and everything else is scaffolding.
The no-edit rule keeps the model in the reviewer’s seat instead of the editor’s. This matters for money, not just tidiness. Reading is input tokens and a compact report is a few thousand output tokens, so an audit is the cheapest possible shape of frontier-model work we can buy. The moment it starts fixing what it found, you are paying the expensive output rate to type.
The file:line requirement is what strangles the filler. A model asked for findings will happily produce “consider improving error handling” all day. A model told that any claim it cannot anchor to a line does not get made has to go and actually look. It also hands us a ten-second verification: open the file, go to the line, see whether the problem is sitting there.
Phase 4’s owner-model column is the part nobody else does. The audit does not just tell you what is broken, it pre-routes each fix to the cheapest seat that can handle it, which means the expensive model has already done the only genuinely expensive part of the job: deciding.
Now run it. Point it at the repo. Interactively, or headless so the report lands in a file we keep:
cd ~/code/invoicing-api
claude -p --model fable --effort high "$(cat ~/audit-prompt.md)" > audit.md
Every switch in that line is worth knowing exactly, because two of them change what we get back and one of them can save an afternoon:
--modelsets the model for the session, taking either an alias for the latest model (sonnet,opus,haiku,fable) or a full model name. It overrides both themodelsetting andANTHROPIC_MODEL.--effortsets the effort level:low,medium,high,xhigh,max, orultracode. Available levels depend on the model,highis the default, and the setting does not persist beyond the session.--print/-pprints the response without interactive mode.--output-formattakestext,jsonorstream-jsonin print mode, andjsonis how you get the run’s real cost back.--max-budget-usdis the maximum dollars to spend before stopping, and it works in print mode only. Spend from sub-agents counts toward it. (CLI reference, Claude Code docs)
An audit is pure reasoning, so effort is the dial that matters most here. Medium is plenty for one well-understood module. For a whole repo or a critical subsystem, we spend up to xhigh and let it think, because the payoff is catching the cross-file bug that only surfaces if the model reasons hard about how the pieces interact. I stop short of max on ordinary code, where it mostly buys cost and latency for depth you will not notice.
What a good finding looks like
Here is the shape, trimmed from a real run against a mid-size TypeScript billing service:
## Findings
### P0 - Webhook signature never verified
- WHERE: src/webhooks/payments.ts:41
- WHY: The handler parses the body and updates invoice status before
checking the provider signature. Anyone who knows the endpoint URL can
mark any invoice "paid" with a forged POST.
### P1 - Tax split rounds before applying the split
- WHERE: src/billing/totals.ts:118
- WHY: Math.round runs on the pre-split total, so three-way tax splits
drop or gain a cent per line item. Wrong money on real invoices.
### P2 - N+1 query on line items
- WHERE: src/db/invoices.ts:76
- WHY: Each invoice refetches its line items in a loop; a 200-invoice
report fires 201 queries. Slow now, a timeout at scale.
## Tasks
- verify webhook signature before processing -> Opus 4.8 (security judgment)
- move Math.round after the tax split -> Sonnet 5 (specified fix)
- batch line-item loading with a join -> Sonnet 5
- rename amt -> amountCents across billing -> Haiku 4.5 (mechanical)
Read the owner-model column, because that is where the money decisions live. The webhook fix touches security, so it needs real judgment and rides a heavier seat. The rounding fix is fully specified by the finding above it, so it is Sonnet’s typing. The rename is pure mechanical churn at a tenth of the price. One audit just sorted our entire fix list by which seat should do it.
And notice Phase 1, which most of us skim past. Discovery is the model proving it understood the system before it started judging it. When it maps the data flow and correctly names the webhook body and the invoice route bodies as where untrusted input enters, the P0 underneath is trustworthy, because we can see it traced the actual path rather than pattern-matching on scary-looking code. So when the map is vague or wrong, the findings sitting under it are guesswork, and that is worth checking before acting on any of them.
Telling a finding from noise
Now the honest part nobody selling you a prompt mentions. Not every audit is worth what it cost. A developer auditing old projects put it plainly: it found nothing useful, but burned through quota. That happens, and pretending otherwise would make everything else here less trustworthy.
A real finding survives three questions.
Can we open the file at that line and see the problem sitting there? If the line does not say what the finding claims then the model invented it, and that one comes straight out of the list.
Does the WHY name a concrete consequence, real money or a real security hole or a real outage, rather than something soft like “improves maintainability”? A soft consequence usually means the model padded the list to look thorough.
Would we have fixed it if a colleague flagged it in review? If not, it is noise.
The stop rule falls out of those. If the P0s and P1s do not survive the three questions, we do not rerun hoping for better. The problem is almost always scope, or your repo genuinely does not have serious issues, which is a fine outcome. Rerunning a whole-repo audit five times because you did not like the answer is exactly how people burn a day’s quota and then post about it.
Scope decides which audit you get
The root cause of most quota-burning audits has nothing to do with the model. It is that people point it at a hundred-thousand-line monorepo and say “find the bugs.” Given the entire haystack, even the best reasoner spreads itself thin, surfaces shallow nits, and misses the deep problem because it never held any one subsystem in focus long enough. Then the model gets blamed for noise that was scoped into existence.
Scope is the part of this we control, and it takes one added line:
Restrict this audit to the payments and webhook code paths
(src/webhooks/, src/billing/, and anything they call). Ignore the rest.
A focused audit is cheaper, faster, and finds deeper problems, because the model gets to reason about a system small enough to fully understand. We run the whole-repo pass once to get the map and the obvious P0s, then focused audits on the two or three subsystems where the money and the risk actually live, which is the sequence that gets thorough coverage without the bonfire.
At true monorepo scale, write the budget into the prompt itself:
## Budget (this repo is bigger than your context - obey these caps)
- Never read a file end to end: at most 150 lines per file, 200 files total.
- Sweep everything else with grep instead of reading it.
- After every 25 files, append findings to audit-evidence.md and drop the
raw text from your working memory.
- Every claim in audit-evidence.md carries a file:line receipt.
The exact numbers matter less than the habit: an audit that writes its evidence down as it goes can cover a codebase far bigger than any context window, and the evidence file it leaves behind ends up being the thing you keep.
One variant is worth running before any of this, and it is the highest value per dollar we get: point the same prompt at your configuration instead of your code. Your CLAUDE.md, your agent definitions, your setup docs. Ask it to read them as a new engineer who must follow them literally, and report contradictions, stale rules that reference files or flags that no longer exist, and gaps a new hire would have to guess at. Those files rot silently, and a stale command in a config does not break once, it breaks every single run until somebody catches it.
So save the prompt, pick a repo you actually care about, and run it once at --effort high on the whole tree. Then open audit.md and put every P0 and P1 through the three questions. Whatever survives is your real backlog, and it already tells you which model should fix each item.
Now go build something this weekend!
John Cook