Fetching
Two temporary copies, and what removes them
Commit history comes from a metadata-only clone — --bare --filter=blob:none — so git sends us trees and commit metadata and never the contents of your files. Structure, security and dependency analysis needs the actual files, so for those we download the repository archive and extract it to a temporary directory on the server. The parsers read it there.
deleted when the analysis is doneThe analysis process removes the temporary directory as soon as it has finished with it, and on the failure paths — a refused download, a full disk, a malformed archive.
the gap we do not round offIf the process itself is killed mid-analysis, whatever it had extracted stays until the host clears its temporary directory. Nothing sweeps it. We do not claim deletion is guaranteed on every path, because it is not.There is no shutdown handler and no reaper over the system temp directory. A redeploy in the middle of a sweep is the realistic case.
Keeping
We keep the result, not your files
A finished analysis is stored as one JSON file. It holds repository metadata, git-history summaries, file paths, symbol names, computed metrics, dependency and vulnerability lists, and the findings. That is enough to describe the shape of a codebase and not enough to reconstruct it.
“We never store your source code” would be a cleaner sentence and it would be false. Some verbatim text from your repository is kept as the evidence behind a finding, because a finding you cannot check is worth nothing. Here is all of it:
one source line per dynamic-execution findingWhen we flag an eval, new Function or exec call, we store that single line so you can see what was matched instead of taking our word for it.Capped at 200 characters per line and 200 findings per analysis.
short strings your code declaresFunction, class, field and enum names, type annotations, import paths, test-case descriptions, and the actions referenced in your CI workflows.
text your team wrote in gitCommit subjects with their author names and email addresses, and pull-request titles — as they appear in the repository’s own history.
never the credential itselfWhen the secret scanner matches a credential-shaped string it stores the file, the line number, and a redacted preview — first six characters and last four. The matched value is never written.A credential sitting on a line we flagged for dynamic execution would still be captured by that check.
never a function bodyFor each function we keep its path, name, line range, complexity and container. The duplicate detector works from a structural fingerprint that hashes AST node types and operator tokens only — never identifiers, never literals.
Deleting an analysis removes that file. Two derived artifacts outlive it: a parse index of paths, symbol names and per-file hashes — no file contents — evicted on a size budget rather than a timer, and a small record of the last commit we saw.
Sending
What reaches a model, and when
The analysis engine calls no AI at all. Cloning, parsing, the call graph and every signal are computed by code; with no API key configured the AI features return nothing and the rest of the product is unchanged. The AI layer sits on top, in three shapes that are not the same as each other.
computed signals onlyThe health check, the grade narrative and the “where to start” note receive the signal JSON — paths, counts, percentages, contributor names — and are instructed to add nothing to it. No file contents, no commit messages.
metadata, plus up to 18 commit messagesThe repository briefing also sends the description and topics, language mix, contributor logins with commit counts, hotspot paths, and up to eighteen recent commit messages as written. It draws on the model’s own knowledge of well-known projects too, which is why we call it a briefing and not a finding.Commit messages are free text your team wrote; they can carry ticket ids, customer names and unreleased feature names.
one function's source, on your clickAsking for a plain-English explanation of a function sends that function to Anthropic for that one request. It is not written to your analysis; the returned explanation is held in server memory and cleared on restart.Capped at 400 lines or 16,000 characters. This is the only path in the product that sends file contents to a model.
private repositories ask firstThe first time you use that explainer on a private repository, in either the Source view or the Flows diagram, it asks before anything is sent.One prompt per browser, not per repository, and it is a consent prompt rather than a permission boundary — the server checks who is asking, not that they were asked.
AI features run on Anthropic’s standard commercial API. What Anthropic does with what it receives is governed by Anthropic’s own terms, not by anything we can promise on their behalf. We hold no zero-retention or enterprise agreement with them.
Reading
Who can open an analysis
private repositories — the account that ran itEvery page, API route and export for that analysis returns “not found” to anyone else. The README badge is the one endpoint that answers at all — it cannot check who is asking, because GitHub’s image proxy strips cookies — and it returns the same neutral marker whether the analysis is private or has never existed.Visibility is recorded at sweep time, not checked live: if a repository becomes private after you analyzed it, re-run the sweep so the lock applies.
public repositories — anyone with the linkA public-repo analysis is shareable the way the repository itself is: no sign-in needed, and the whole report is readable by anyone holding the URL.Plan limits control what the interface renders, not who can fetch the data. If a result should be restricted, analyze the repository privately.
the list is not publicListing analyses requires signing in and returns only your own. It did not always: until recently the endpoint returned every public-repo analysis on the instance to anyone, with an identifier for the account that created each one. That is fixed, and it is the kind of thing this page exists to make us check.
Access
What we ask GitHub for
Public repositories need no authorization at all. Signing in with GitHub requests the repo scope so private repositories can be read — and GitHub issues that scope as read and write, because it publishes no read-only equivalent. We only ever read. You can revoke it at any time from your GitHub application settings, and a per-repository install with read-only access is on the roadmap.
The token is stored server-side and is never sent to the browser. The full picture of what we collect and why is in the privacy policy.
Honestly
What CodeTrawl is not
Every claim above is checkable. These are not, so we are not making them:
no certificationsNo SOC 2, no ISO 27001, no penetration test, no external audit. If your procurement process requires one, CodeTrawl does not clear it today.
no data processing agreementWe cannot sign a DPA, and we hold no sub-processor agreements beyond each provider’s standard terms.
one operatorCodeTrawl is built and run by one person. There is no on-call rotation and no security team. Ownership of the code is deliberately narrow for the same reason.
not yet a registered companyThe terms say so plainly, and this page will say so until it changes. If something here is wrong, or you need a detail this page does not cover, write to [email protected].