A code scanner asks for an unusual amount of trust. You point it at your source — often a private, proprietary repository — and let it read everything. The reasonable question is the first one everyone asks: what does it send back?
Here’s the precise answer. Not a privacy policy written by a lawyer — the actual behavior, field by field.
Your source code never leaves the machine
This is the load-bearing fact: ik never uploads your file contents. When a scan finishes and you’ve opted into a hosted report, what gets sent is a description of what was found, not the code it was found in.
A finding is four things: a file path, a line number, a short message (“function too long,” “unused import”), and a severity. There is no field for the offending source line. No snippet. No surrounding context. The struct that gets serialized and uploaded simply has nowhere to put your code, because we never put it there.
So the report can tell you complexity is high in internal/auth/session.go at
line 142 — and to actually see line 142, you open your own editor. The map
travels; the territory stays home.
Secrets are masked before they’re even stored
The one place this principle could leak is the secret scanner — its whole job is finding things like API keys, and a naive implementation would attach the matched value to the finding so you know what it caught.
We don’t. The matched value is redacted the moment it’s parsed, down to a
first-and-last-character preview with a fixed mask in between — AK***LE — so the
finding can say which credential tripped the rule without the credential itself
ever entering the report. The mask is a constant width, so it doesn’t even leak
how long the secret was. The raw value never makes it into the data structure that
could be uploaded, which means it can’t leave the machine even by accident.
(We tightened this recently after auditing our own upload payload against the promise we make in the consent prompt — the kind of check-yourself discipline we try to apply everywhere.)
The AI runs on your hardware, not ours
Two of ik’s checks use a language model — semantic duplicate detection and magic-number labelling. Plenty of “AI-powered” tools would mean your code gets POSTed to an inference API for that. Ours doesn’t.
The model is a small one that ships inside the binary and runs in-process on your CPU. There is no inference endpoint, no API key, no network request for the AI features — your functions are embedded and labelled entirely on the machine they already live on. The smartest part of the scanner is also the most private.
Paths are relative, so they can’t leak your machine
A subtle one: every file path in a report is relative to the repository root.
You’ll see src/main.go, never /Users/jane/work/client-project/src/main.go.
Absolute paths would quietly disclose your username, your directory layout,
sometimes a client’s name. We normalize them away — forward slashes, repo-root
relative — before anything is written.
What does get uploaded (when you opt in)
Transparency cuts both ways, so here’s the full list of what a hosted report includes:
- Scores and grade — the numbers and the letter.
- Finding metadata — path, line, message, severity. (Not contents.)
- Repository statistics — language mix, file count, repo age, commit count, and contributor information drawn from git history.
- Project identity — the project name, and the contact email/company you entered during setup.
That’s it. It’s enough to render a report and track a project’s trend over time, and it’s deliberately not enough to reconstruct your code.
The consent prompt during ik init says the same thing, in fewer words:
inkode will collect and upload:
• File paths of issues found (no file contents)
• Aggregate scores and check summaries
• Git history statistics (commit count, age, contributors)
• Language and tech-stack signals
No source code or secrets are transmitted.
Or send nothing at all
If even metadata is more than you want to share, ik runs fully local. It’s not a degraded mode — every check still runs, you still get the full report as a self-contained HTML file on disk. The only thing you skip is the hosted copy.
Two ways to get there:
- During setup, the wizard offers “No — local checks only” as a first-class choice. Pick it and no config that points at our API is written.
- Any time after, set
api.upload: false(or leave the API endpoint blank) in your.ik.yaml. The scan runs, the report renders locally, nothing is sent.
Local-only works offline, too — because the analysis and the AI are all in-process, you can scan on a plane with the wifi off and get an identical result.
Why we build it this way
The principle underneath all of this is simple: the tool should be trustworthy on a machine you didn’t set up and a repo you can’t email to a third party. That rules out “send the code to a server and trust us with it” as an architecture. So your source stays put, secrets are masked at the source, the AI is local, and the upload is opt-in metadata you can switch off entirely.
If you point ik at something and find a case where it sends more than this post describes, we want to know — tell us, and we’ll treat it as a bug. Holding ourselves to the promise is the whole point.
Want to try it — locally, with nothing uploaded? Install the CLI — one line, about a minute, no account required.