I was adding files one at a time to a Project for a client site I maintain. Meeting notes, text lifted from the old site, the decisions we had made about color and type, draft copy for each page. Handing over everything I had felt like the considerate thing to do.
Then one morning I asked the usual question — give me three heading options for this page — and the answer came back blander than it had the week before. Every option would have worked for any site at all.
There was more material in the Project, and less of the site in the answers.
The file count and the quality moved in opposite directions
The thinning had a particular shape. Nothing was factually wrong. What came back was broadly correct and simply drifted toward language you could paste anywhere.
For a calligrapher's site, where I expected words like brush, negative space, and the time spent facing a single sheet, I got "convey the appeal" and "deliver your feelings" instead. Because none of it was incorrect, it was hard to push back on.
For a while I assumed the problem was my prompting, so I kept rewriting the question. Longer, shorter, with extra constraints, with examples attached. None of it helped.
What helped was the opposite move. I removed three files. On the next question, words that belonged to that specific site came back into the heading options.
The cause was overlap, not volume
Files you upload to a Project are not read end to end on every turn. Relevant passages are retrieved and used as grounding. Most people know that much.
The part that is easy to miss comes next. When similar statements are scattered across several files, there is no way to settle on which one is the source. What survives is the material the files have in common — the most abstract part — and the specific detail that exists in only one of them drops out.
Contradictions are worse. Halfway through the build, a spec changed, and I left both the before and after notes in place. Twice I took an answer grounded in the older one at face value. I noticed the second time just before sending it to the client, which is the kind of moment that sits in your stomach for a while.
Adding a file does not add grounding. It adds one more thing to choose between. Once I had it phrased that way, I started pausing before every upload.
Overlap is easier to see as a number than as a read-through
Comparing ten or twenty documents by hand to hunt for duplication is tiring work. So I started getting a number first: how much does each file in a folder repeat the others?
The method is deliberately plain. Strip whitespace from each file, turn the text into the set of its three-character sequences, and measure how much of that set already appears in the other files. Japanese does not split into words on spaces the way English does, so comparing character sequences is the least fussy approach that works for both.
#!/usr/bin/env python3
"""Measure how much the knowledge files in a Claude Project repeat each other.
Usage: python3 kb_overlap.py <folder holding your knowledge files>
Output: coverage = share of this file's phrasing that already exists elsewhere"""
import sys, pathlib, re
EXT = {".md", ".txt", ".mdx"}
N = 3 # Japanese has no word boundaries, so compare 3-character sequences
def grams(text):
t = re.sub(r"\s+", "", text)
return {t[i:i + N] for i in range(len(t) - N + 1)}
def main(folder):
files = sorted(p for p in pathlib.Path(folder).iterdir()
if p.is_file() and p.suffix.lower() in EXT)
if len(files) < 2:
print("Put at least two knowledge files in the folder first")
return
sets = {p: grams(p.read_text(encoding="utf-8", errors="ignore")) for p in files}
rows = []
for p, g in sets.items():
if not g:
continue
others = set().union(*[s for q, s in sets.items() if q != p])
covered = len(g & others) / len(g)
near, near_ratio = max(((q, len(g & s) / len(g)) for q, s in sets.items() if q != p),
key=lambda x: x[1])
rows.append((covered, p.name, near.name, near_ratio))
rows.sort(reverse=True)
print(f"{'coverage':>9} file")
for covered, name, near, near_ratio in rows:
flag = " <- fold candidate" if covered >= 0.60 else ""
print(f"{covered*100:8.1f}% {name}{flag}")
print(f" closest: {near} ({near_ratio*100:.1f}%)")
if __name__ == "__main__":
main(sys.argv[1] if len(sys.argv) > 1 else ".")Run against a folder holding an invoice format note, a quote format note, and a note about setting up a photo shoot, the output looks like this.
$ python3 kb_overlap.py ./knowledge
coverage file
72.1% invoice_format.md <- fold candidate
closest: quote_format.md (72.1%)
69.4% quote_format.md <- fold candidate
closest: invoice_format.md (68.1%)
2.9% shooting_setup.md
closest: quote_format.md (2.9%)The invoice and quote notes turned out to specify almost the same layout. The only difference was the last few lines — bank details in one, an expiry window in the other. Those two fold into one file. The shoot note overlaps with nothing and stays as it is.
A word about the 60% mark, since I would rather not present it as more than it is. It is not a researched threshold; it is where things settled for my own material. Japanese prose shares particles and verb endings, so two unrelated documents still land around 20%. Files that contain layout rules or boilerplate climb past 50%. So I treat 60% as the line where I can reasonably suspect I wrote the same thing twice. Use 50% or 70% if that fits your material better. The value is not in getting the threshold right — it is in having an order to work through from the top.
Three questions decide whether a file stays, folds, or leaves
Once the numbers are in front of me, the rest is judgment. I ask these three in order.
| Question | What I do when the answer is no |
|---|---|
| Can I say this file is currently correct? | Remove it. Old specs, superseded copy, and abandoned directions carry more risk of leaking into an answer than value, so they come out of the Project and into a separate folder |
| Is the same thing written in another file? | Fold it. Merge the shared portion into a single file and keep only the few lines that are unique. Start with the highest-coverage pair |
| Is this a fact to reference, rather than a rule to follow? | Move it. Standards, writing rules, and priorities work far more reliably as custom instructions than as retrievable knowledge |
The third one is where I was wrong the longest. Rules like "keep the tone warm" and "add a short gloss after any jargon" were sitting in a knowledge file alongside everything else. A rule is not something you want retrieved when it happens to match; it is something you want in effect every turn. I wrote up how I structure those separately in Writing Effective Custom Instructions for Claude Projects, if you want the other half of this.
What I landed on after folding was one index file plus a handful of thin, specific ones. The index lists what lives in each file and which file is current. Since putting that first, Claude has been far less likely to reach for the wrong place.
After folding, I ask the same three questions again
You cannot feel the effect of pruning. So I settle on three questions in advance and ask the identical set before and after.
- One that only your site or project could answer — heading options, a tagline, naming
- One that checks a single fact — an agreed deadline, a settled spec value
- One that asks for a judgment — which of two directions to recommend, with reasons
I also ask once, "which file did you base that on?" If a filename comes back, that material is landing. If some files never come up, they may not be useless so much as filed in the wrong place. Moving them to custom instructions, or pasting them into just the one conversation where they matter, is often quicker.
As an indie developer I do the same thing with store copy for apps I have run for years. Multilingual store descriptions share so much structure that splitting them per language sends the coverage number straight up. They live in one file now, with the per-language differences as a short bulleted list underneath. There is less material in the Project than before, and the drafts that come back pick up each language's habits more closely than they used to.
If you work from the desktop app, it is also worth reconsidering where the material lives at all. I covered referencing local folders in Claude Desktop in 2026.
Start by taking down your oldest file
If you do one thing today, remove the file with the oldest date from your Project and re-ask a single question you ask often. If the answer does not change, that file was not doing harm. If it does change, move on to the next one.
Adding files came easily to me. Taking them down took much longer to learn. Put the inventory on a schedule — once a month is enough. That is the one part I try not to skip, even in a busy month.
Thank you for reading. I hope you find the one file worth keeping.