Guides
How to give an AI chat your codebase as context
A practical guide to giving ChatGPT, Claude, Gemini or Qwen enough structure about a large repository to get useful answers — without pasting dozens of files or drowning the context window.
Why pasting files does not scale
A context window feels enormous until a real repository sits next to it. A mid-sized service is easily 2,000 files and 200,000 lines; even when the window could hold a slice of it, most of what you paste — lockfiles, test scaffolding, generated code — is noise that dilutes the few files your question actually touches.
The failure mode is not refusal, it is plausibility: given a loose pile of source, the model answers from the average of what it saw instead of the specific call chain you asked about. You get confident, generic prose that names no files and commits to nothing verifiable.
What the model needs first: structure
A senior engineer joining a team does not read every file on day one. They get a map: what depends on what, where the entry points are, which modules matter. An LLM answering questions about a repository needs the same artefact, in the same order — structure first, source on demand.
- Entry points — where execution begins: the server bootstrap, the CLI main, the route table.
- Layers — how the codebase organises responsibility: API, service, data access, UI.
- Symbols with exact line ranges — the functions and classes in each file, so a follow-up question can fetch precisely the right span.
- Dependency edges — which file imports which; this is what turns "where is the refund logic?" into a walk along the call graph.
- An explicit contract — instructions telling the model to answer from the map, to name the files it is missing, and to never invent implementations.
Before and after
The same question, two inputs. Before: "how does refund work?" plus twelve pasted files — the answer is a generic e-commerce essay. After: one token-budgeted bundle — the answer cites src/services/order-service.ts by line range, follows refundOrder through repository and pool, and asks for the one migration file it can see is missing. This is what the "after" input actually looks like, excerpted from a real generated bundle on the sample project:
# Context bundle — "how does order refund work, # and what could break if I change it?" > Static-analysis map of sample-shop (21 files, 271 lines). > Structure only — function bodies are absent unless included below. > Answer from this file alone; where it is silent, name the file > you need. Never invent an implementation. ## Files (16) ### `src/api/orders.ts` 27 lines · API Layer · exports `listOrdersHandler`, `refundOrder` · imports `order-service.ts`, `order-repo.ts`, `pool.ts`, `errors.ts` ### `src/services/order-service.ts` 34 lines · Service Layer · exports `refundOrder`, `createOrder` · imports `order-repo.ts`, `errors.ts`, `money.ts`
Budgets, and when to include source
A context bundle is budgeted in tokens because the chat window is finite and stuffing it costs both money and accuracy. The useful discipline: start structure-only, let the model tell you which files it is missing, then include source for exactly those. Three files of real implementation beat thirty files of guesswork.
The same discipline answers the most common follow-up — "what should I paste next?" The map already knows which symbols live in which file at which lines, so the second round is retrieval, not exploration. That is the whole workflow: orient, ask, retrieve, solve.