See it as a diagram
Everything below, as a diagram you can edit. Describe yours and see it in seconds.
No account needed · Editable canvas, not a picture
Start with the files that cannot lie
Not all files in a legacy repository are equally honest. Comments lie, READMEs lie, and the docs directory usually describes an intention from 2018. The deployment descriptors do not, because if they were wrong the thing would not be running. Dockerfiles, compose files, Kubernetes and Helm manifests, infrastructure as code, CI workflows, and package manifests are the shortest path from a repository you do not understand to a list of what actually runs.
That is why a repository read should take files in that priority order, infrastructure as code first and prose last, up to a bounded budget of 40 files and 250KB, rather than trying to read everything. On a legacy codebase the bound is a feature: it forces the highest-signal files to the front instead of drowning them in twelve thousand lines of business logic.
The exclusions matter as much as the ordering on an old repository. Vendored directories, node_modules, target, dist, and __pycache__ are never candidates, and neither are lockfiles or binaries. A file above 400KB is skipped outright, and anything above 30KB is truncated with a visible marker so a reader can tell a cut tail from an absent one. Legacy repositories are exactly where those rules earn their keep, because they are where a checked-in dependency tree or a 40MB fixture would otherwise eat the entire budget.
A summary of the top three directory levels rides along with the selection, so you can see the shape of what was not read. On an unfamiliar repository that summary is often the single most useful artifact, because directory names are the last honest naming layer a codebase retains.
Nothing is executed
The first artifact is a map, not a manual
Aim for something to be wrong about in public. A generated diagram plus a written description gets you a concrete draft in minutes, and a draft with three errors in it is a far better instrument than a blank page, because it converts an impossible request into an easy one.
The easy request is this: take the picture to the two people who have been there longest and ask them what is wrong with it. Nobody can write a system description from memory on demand. Everybody can correct a diagram. That asymmetry is the whole technique, and it is why the generated draft matters more than its accuracy.
Run that loop twice and stop. The map does not have to be complete to be useful, it has to be good enough that the next person starts from it rather than from grep.
What the source cannot tell you, and where to put it
Source explains what, never why. Why the retry count is seven. Which single customer the special case in the invoicing path exists for. Which table looks unused but is read by a quarterly job that lives in a different repository. Which failure is known, understood, and deliberately unfixed. That is the knowledge that leaves with people, and it is the reason legacy systems are frightening rather than merely old.
Put it on the map. Annotations placed next to the node they concern keep the context attached to the thing it explains, which is the difference between knowledge that gets found and knowledge that sits in a document nobody opens. A canvas with editable text and labelled edges holds that kind of note naturally.
Those notes survive the regeneration, which is the part that decides whether anyone bothers adding them. A node put on the canvas by hand carries no id from the source, so every later sync is told to keep it as the reader's own work rather than reconcile it away, and anything dragged into position stays there. The map accumulates what people know instead of being flattened each morning by the read.
This is also the part to do while the person who knows is still reachable. Generated documentation makes their time cheap to use: instead of asking them to write, you ask them to correct, and a thirty minute session over a diagram extracts more than a week of good intentions.
Point at the ref that is actually deployed
Legacy systems routinely have a main branch that is not what is running. There is a release branch, a hotfix branch that never merged back, or a tag from three years ago sitting in production. Documenting main in that situation produces an accurate description of something nobody is operating.
A repository connection tracks a specific branch or tag, and one connection can back several diagrams, so you can hold the deployed tag and the current main side by side. Reading the two next to each other is frequently the most informative half hour of the whole exercise, because the divergence is a list of what was changed and never released.
Once the map exists, keep it alive rather than declaring victory. The daily sync regenerates from the tracked ref and skips the work when the commit has not moved, which on a legacy system means it costs almost nothing and quietly captures the day somebody finally touches it.
FAQ
Where do you start documenting a system nobody understands?
Is it safe to point a documentation tool at a legacy production repository?
What if the generated map has errors in it?
How do we capture knowledge that is not in the code?
Which branch should a legacy system be documented from?