Codebase intelligence
See how your software
actually works.
Your architecture, your slow paths, your risky files — one map built from the repository you already have and the traffic it already serves. Every answer points at the line of code that proves it.
- Know what a change will reach before you merge it
- Find the one query that is costing you the request
- Hand your coding agent a prompt that is already correct
Runs on your machine firstNothing stored, nothing trained onOne repository at a time
Most of the request
is one database read
1 critical finding
a live key in source
01 · What you are working with
A file list is not an answer.
checkout/page.tsx
screen
cart/page.tsx
screen
CartRow.tsx
component
PriceTag.tsx
component
api/checkout
route
api/orders
route
api/invoice
route
api/auth
route
OrderService.ts
318 lines
26 dependantsPriceRules.ts
142 lines
discount.ts
96 lines
copyauth/session.ts
74 lines
invoice/render.ts
88 lines
mailer.ts
51 lines
utils/money.ts
31 lines
copynightly-settle.ts
job
db · orders
table
db · users
table
db · invoices
table
legacy/payments.js
unread
Two duplicates, one shortcut, one overloaded file, one region nothing can read.You would have found these in a week. The scan finds them in one pass, on every push.
So this is what MLReps does with it
One pass over the code you already have. Four lenses on the same map. No guessing.
A deterministic analysis builds the graph first. Language only comes in at the end, to word what the analysis already found — so the answer survives the model being switched off.
Architecture
What exists, what calls what, and what one change will reach.
Performance
Your own traces, joined to the exact file that spent the time.
Risk
Secrets in source, reads with no authorisation, dangerous calls.
Optimization
Work done twice, work done in a loop, work done on everything.
02 · It reads, then it understands
Watch a folder become a system.
- $npx mlreps scan --publish
- reading files141
- following call sites1,244
- could not follow32
- graph edges4,063
- routes with a traced path32 of 32
ANY /user/:id{/:op}
DELETE /user/:id
GET /
GET /:sub
GET /403
GET /404
GET /500
GET /api/repos
GET /api/user/:name/repos
GET /api/users
GET /client.js
GET /fail
GET /files/*file
GET /forget
GET /login
GET /logout
GET /middleware
GET /middleware-locals
GET /next
GET /posts
GET /Readme.md
GET /restricted
GET /search/{:query}
GET /user/:id
GET /user/:id/edit
If you change lib
At least 10 things depend on it.
A floor, not a total — 16 call sites inside it could not be followed.
- routes8
- modules2
- not followed16
03 · Then it starts carrying traffic
The same map, with real requests on it.
Where the time goes
- Browsernot observed
- Next.js server48 ms
- /api/checkout842 ms
- postgres · orders610 ms
- Paymentsnot observed
p95 latency
842 ms
threshold 500 ms
database p95
610 ms
73% of the request
error rate
4.2%
173 of 4,120
throughput
2.9 /s
mean, 24 h
Checkout is slow because one database read takes 73% of the request — and it runs once per order, inside a loop.
OrderService.ts:42 · 14 calls per request · p95 610 ms · over 3,980 of 4,120 observed requests
04 · What should never have been there
The same map finds the risk.
With the GitHub App, our copy of your code is read in a container with no network access, and that copy is removed from our servers when the scan ends. Your repository is never changed. Only the map is kept — never the source, and never a line of it inside a model prompt.
- 9export async function POST(req: Request) {
- 10 const body = await req.json()
- 11 // quick fix before the demo, move later
- 12 const key = "sk_live_…"
- 13
- 14 const order = await db.order.findFirst({
- 15 where: { id: body.id } })
- 16 return Response.json(order)
- 17}
A live secret key is written into source at route.ts:12.
2 screens reach this route. The key is also in git history.
Do this: rotate it, move it to an environment variable, purge it from history.
This handler reads an order by id with nothing checking that the caller owns it.
Reachable from checkout/page.tsx and admin/orders.
Every rule that could apply ran across everything that was read. The ones that could not run on a language nothing reads yet are listed by name — this says so rather than calling those files clean.
05 · What to do about it
From “this is slow” to a change you can check.
PROBLEM
A query inside a loop, at line 42
IMPACT
73% of checkout's time
REACH
4 screens, 3 routes
- 38for (const o of orders) {
- 42 await db.line.findMany(
- 43 { where: { orderId: o.id } })
- 47}
- 38const all = await db.line.findMany(
- 39 { where: { orderId: { in: ids } } })
- 40const by = groupBy(all, l => l.orderId)
- 41orders.forEach(o => o.lines = by[o.id])
In lib/OrderService.ts, the loop at lines 38–47 calls db.line.findMany once per order (line 42). Replace it with one findMany for every order id in the batch, then group the rows in memory by orderId. Keep the signature and return shape unchanged; order-service.test.ts must still pass.
Written by MLReps from its own analysis, and checked against the measured facts before you saw it.
06 · And you can just ask
Ask in your own words. Get an answer with its workings.
Radh answers from the map — code, structure, dependencies, history, telemetry — and the answer beside this is the real one for a real file in a real repository, computed without calling a model at all.
It cannot invent anything. The map answers and the model only words it — so where the evidence is missing, it tells you what is missing instead of filling the gap.
What is lib/express.js connected to?
Changing lib/express.js could reach 117 files — 97 of them directly.
- module: lib
- feature: none — shared infrastructure
- symbols recorded: 11
- uses: 3 files
- used by: 97 files
- imports: 4 packages
- 78% of the call sites in lib resolved, so 16 calls in this module were not followed. Anything reached only through those is not listed here.
A lower bound — some calls resolve for no static tool.
Answered without calling a model. Yours is answered the same way.
Ask it about your codeWhat you end up with
Not a dashboard you check. A loop you work in.
Every screen hands you to the next with the subject already carried over. You never retype a file name to ask about it.
Understand
The architecture, and which file owns which feature.
See
Latency, errors and queries on those same nodes.
Explain
Why, with the decomposition that proves it.
Fix
A recommendation, and the prompt that carries it out.
Verify
The next scan and the next traces say whether it worked.
Access, in plain words
You decide what it can see. One repository at a time.
Not an “enterprise-grade security” sentence. The actual boundary, on the page, before you install anything.
What it can do
- Read one repository you approved, read-only
- Publish the map to your own organisation
- Receive the telemetry you choose to send
The approval screen names the machine, the folder, the repository and the organisation — before anything is created.
What it never does
- Write to your repository or open a pull request
- Put your source into a model prompt
- Train anything on your code
- Show one customer’s data to another
- Give you a per-developer view of who wrote what
What telemetry never carries
- Log lines and query text
- Span names, URLs, your trace ids
- Exception messages and stack traces
- Host names, device names, mount points
Aggregates 14 days · samples 3 days · your source not kept at all.
Every machine, every repository — one list, with a Revoke beside each
your dashboard- Revoke
dev-mbp-14 · ~/code/storefront · 20 Oct
may act on acme/storefront, acme/admin
- Revoke
ci-runner-7 · /home/runner/work · 14 Oct
may act on acme/storefront · 1 taken back
Where this stands today
Six of the eight rungs are built. Two are begun.
You should read that here, not find it out in week two.
Observe
built
Understand
built
Verify
built
Predict
built
Explain
built
Fix
built
Optimize
begun
Learn
begun
What it refuses to say
The reason to believe the numbers is the ones it will not print
A score it did not measure.
Three of the six indices are uncalibrated, and they say so instead of printing a number.
A map of a codebase it could not read.
Below 70% resolution no picture is drawn at all; between 70 and 90 it is drawn with its gaps named.
That a change is safe.
An empty blast radius means we found nothing, never that nothing is affected.
Anything about a person.
No per-developer score, no leaderboard, and no column anywhere for who dismissed a finding — and debt is hours, never a letter grade.
Start
Connect your repository. See what it finds.
One repository, one command, about two minutes. It runs on your machine first, and you approve that repository by name before anything is published.
Free — there is no paid plan, and nothing is held back waiting for one.
Or read what it finds: your real architecture, traced from the code · the query a loop runs once per item · what fast-written code leaves behind