On this page
Blog

What an AI coding assistant actually reads from your code

8 min read

A magnifying glass resting on a pile of printed pages

Before someone hands over a project, they usually ask a version of the same question. You use AI tools. Does that mean my code ends up on somebody’s server?

It is a fair question and it deserves a number rather than reassurance. So I counted. On this site’s own repository, across every AI coding session I have run on it, the typical session opened 5 files out of 533. The widest one opened 48. Nothing resembling “the whole codebase” was ever sent anywhere.

Then I looked at what those same sessions opened outside the repository, and that number was 482, which is the part of this I did not expect and the part worth your attention.

Where the numbers come from

Claude Code, the tool I use daily, keeps a transcript of every session on my own disk, in plaintext, under ~/.claude/projects/, for 30 days by default.[1] Every tool call it made is in there: which file it opened, which command it ran, what came back. That is an unusually honest audit log, because the tool wrote it for its own session-resume feature and not to answer this question.

This repository has 185 of those transcripts. I parsed all of them.

One thing to pin down before the numbers: what “opened” means. I counted a file as read when a tool call named it directly, through Read, Edit or Write. I did not try to resolve the files touched by shell commands, and those transcripts contain 5,288 shell calls of which 2,748 begin with something like cat, head or sed. So every number below is a floor, not a ceiling.

import json, glob, os, re, statistics

DIR  = os.path.expanduser("~/.claude/projects/<your-project-folder>")
REPO = re.compile(r"^/path/to/your/repo")
READ = {"Read", "Edit", "Write", "MultiEdit", "NotebookEdit"}

per_session, outside = [], set()
for path in glob.glob(os.path.join(DIR, "*.jsonl")):
    inside = set()
    for line in open(path, errors="replace"):
        try:
            msg = json.loads(line).get("message") or {}
        except ValueError:
            continue
        for block in msg.get("content") or []:
            if not isinstance(block, dict) or block.get("type") != "tool_use":
                continue
            if block.get("name") in READ:
                fp = (block.get("input") or {}).get("file_path", "")
                inside.add(fp) if REPO.match(fp) else outside.add(fp)
    if inside:
        per_session.append(len(inside))

print("sessions that opened a repo file :", len(per_session))
print("repo files per session           : median %g, max %d"
      % (statistics.median(per_session), max(per_session)))
print("distinct files opened elsewhere  :", len(outside))
the whole measurement, minus the paths, which you would swap for your own
sessions that opened a repo file : 73
repo files per session           : median 5, max 48
distinct files opened elsewhere  : 482
what it printed on my machine, 2026-09-20

Of the 185 sessions, 73 opened a file belonging to the repo at all. The rest were not coding work: they were research, admin, browser tasks that happened to be started from that folder. The median and the maximum are over those 73.

Bar chart titled ‘533 files in the repo. The median task opened 5 of them.’ Three bars: text files in the repo 533, widest single session 48, median session 5, highlighted.

what the median session opened, against the whole repo

Why a coding agent reads so little

This is the mechanical part, and it is less mysterious than the marketing around it.

An agent works the way a contractor does on their first day. It is told what the task is, it goes looking for the two or three files that sound relevant, it reads those, and it stops. Nobody reads a codebase cover to cover before changing a config value, and neither does the tool. Its budget for a single request is finite and the repository is mostly irrelevant to any given task, so almost all of it never gets opened.

The most-opened files in my repo are exactly the ones you would guess: the two translation files, the data module behind the CV, the site config. They are the files that nearly every change touches.

This is also where I should say that “an AI coding tool” is not one thing, and the answer changes completely depending on which kind you mean.

An agent like the one I use reads on purpose, file by file, and each read is visible in a log. An autocomplete tool works the other way around. GitHub’s own documentation for Copilot code completion describes it plainly: the code around your cursor is pre-processed, combined with contextual information such as code snippets from open tabs in your editor, and sent to the model as a prompt.[3] That happens continuously, while you type, without anyone deciding that this particular file was relevant.

Neither is sinister. They are different shapes, and if you are the person asking the question, the shape is what you actually want to know.

The 482 files that were not in the repo

Here is the number I went looking for the code’s answer to and found something else instead. Grouped by where they live:

where the file was distinct files
scratch files the tool wrote itself 201
other project folders on the same disk 164
notes the tool keeps about how I work 71
elsewhere on the machine 23
its own config, skills and hooks 21
elsewhere in my home directory 2

The first row is fine. Temporary files it created to do the work, then read back.

The second row is the one to look at. A session started in one project opened 164 files across four other project folders. Not because anything went wrong, and not because the model went wandering. I asked for things like “check how the other site handles this” and it did exactly that, correctly, by opening files that belong to work that was not the work in front of it.

The third row is the uncomfortable one. Those are notes the tool has accumulated about how I like things done, built up over months so it stops asking me the same question. They are the most frequently read files in the entire dataset, well ahead of any source file. I am not printing their names, and the reason I am not is the point. They are about me, not about code.

This was my doing, not the tool’s

The default behaviour is a boundary. Anthropic’s own security documentation says that in Manual mode Claude Code starts with read-only permissions, can only write inside the folder it was started in, and asks you before reading paths outside that boundary with its file-reading tools.[2] Run it that way and the 164 would have been 164 prompts on my screen, each one answerable with no.

I do not run it that way. Of the 185 sessions, 152 started with permission prompts switched off, because I got tired of approving reads one at a time. That is a real convenience and I am not going to pretend I regret it day to day. It is also the entire explanation for the second and third rows of that table, and if I were the client asking the question at the top of this article, it is the answer I would want and would not have thought to ask for.

So the useful question is not “do you use AI tools”. It is “which one, and what did you turn off”.

What leaves the machine, and what happens to it after

The reading is only half of it. The other half is what the vendor does with what it receives, and you do not have to guess at that, because it is written down.

For the tool I use: prompts and model outputs go over the network encrypted in transit, and what happens next depends entirely on which account is paying.[1] On a commercial plan, Anthropic does not train models on the code or prompts sent through Claude Code unless the customer has explicitly opted in, and the standard retention period is 30 days. On a personal plan, data is used to improve future models when that setting is on, and retention stretches to five years when it is. Same software, same keystrokes, materially different answer depending on a billing tier and a toggle.

There is one more thing worth knowing if you are on the GitHub side, because it is the kind of detail that quietly invalidates a policy. Copilot lets an organisation exclude file paths from the tool, at repository, organisation or enterprise level. GitHub’s documentation also states that agent mode in Copilot Chat does not support content exclusion, and that a change to the rules can take up to 30 minutes to reach editors that have already loaded the settings.[4] An exclusion list that holds for completions and not for the agent is worth reading carefully before anyone signs off on it.

What I would actually check

If someone is about to let a contractor point these tools at their code, four questions get you most of the way:

  1. Which tool, and is it an agent or an autocomplete. The second one sends context you did not choose.
  2. Which account tier. That is what decides retention and training, not the software.
  3. Are the approval prompts on. Mine are off, and I would tell you so before you asked.
  4. Is anything else sensitive sitting on the same disk. This is the one I had not thought about until I ran the count.

Where this measurement stops

One machine, one person, one repository, one tool. A team with ten engineers and a monorepo would produce a different shape, and I cannot tell you what it is.

The floor problem above is the real limitation: shell commands can read files too, and I did not resolve which files those 2,748 commands touched. The true read surface is larger than 5 files per session. I would still expect it to be far below 533, because the reason it is small is the shape of the work rather than a limit anyone imposed, but “I expect” is not “I measured”.

And the count says nothing about what the model did with any of it. It tells you what was opened. That is a smaller claim than it first looks, and it is the one I can stand behind.

If the question of what software can quietly see interests you beyond this, I did the same kind of count on browser extensions, where the answer is much less reassuring. And for the version of this that is about the work instead of the data, there is what I actually use these tools for after a year of them.

Sources

Every claim below about something outside this site traces to a source in this list. Where a claim could not be sourced, it was removed rather than softened.

  1. Claude Code: Data usage

    Primary sourceAnthropic

    That the tool sends all user prompts and model outputs over TLS 1.2+ to run a request; that session transcripts are stored locally in plaintext under ~/.claude/projects for 30 days by default; and the retention and model-training policies, which differ between consumer plans (5 years when data use for model improvement is on, 30 days when it is off) and commercial plans (30 days, no training on code or prompts unless the customer opts in).

  2. Claude Code: Security

    Primary sourceAnthropic

    That in Manual mode the tool starts with read-only permissions, can only write inside the folder it was started in, and asks before reading paths outside that boundary with the Read, Grep and Glob tools.

  3. Responsible use of GitHub Copilot code completion

    Primary sourceGitHub

    That code completion pre-processes the code surrounding the cursor, combines it with contextual information such as code snippets from open tabs in the editor, and sends that to a large language model as a prompt.

  4. Exclude content from GitHub Copilot

    Primary sourceGitHub

    That content exclusion is configured with file path patterns at repository, organisation and enterprise level, that agent mode in Copilot Chat in IDEs does not support content exclusion, and that a change can take up to 30 minutes to take effect in IDEs that already loaded the settings.

New posts by email

One email when something new lands here. No schedule, no digest, no sales sequence - and you can leave from any of them.

Your address is used for these posts and nothing else.