Skip to main content

Command Palette

Search for a command to run...

Code got cheap. Understanding didn't.

Updated
•7 min read•View as Markdown

For most of my career, writing code was the slow part and understanding it came along for free. You understand how it works when you spent week debugging some minor bugs. Either knew how something worked because you had built it, line by line, and all that time spent typing was also time spent thinking.

For good or for bad - this times are gone.

Working with agents has changed that, at least for me. I can open a repository I've never seen, describe a change, and a little later have something that compiles and passes its tests across a dozen files. The writing is mostly done for me. While writing is done, the understanding isn't, and I've noticed it no longer comes along automatically. You can't efficiently prompt a change without understanding neither you can access changes by reading 3000 lines of MR. Unless you wrote app yourself before. So, code review, in my view for agentic coding is not feasiable in my humble opinion

People have started calling this cognitive debt. The term appeared in an MIT Media Lab study last year about what happens when people hand their thinking to an assistant, and it seems to fit software well. Each change I accept without really understanding it is a small loan against my future understanding of the system. I don't notice it when I take it. I notice it later, when something goes wrong in a part of the code I'm supposedly responsible for and I have to rebuild my picture of it from scratch.

The usual answer is to read the diff carefully. I do that, but in an unfamiliar codebase it is only gets me so far - whether this all actually does not raise any firedrill in my head given general knowledge, not specific repository. A diff tells me what changed. It doesn't tell me what those files are connected to, what depends on them, or which parts of the system nothing tests. When I review a colleague's work in a system I know, I bring a mental model with me. In a new repository I don't have one yet, so I'm reading individual sentences without knowing the plot.

What I wanted was a way to see the shape of the thing first: where it starts, how it's layered, which files everything else leans on, and how the pieces connect. Building that picture used to take me weeks of reading around. So I made a small tool that draws it.

It's called Strabo. It scans a local repository and draws its files and dependencies as a map I can move around in. I can click a file to see what it imports and what imports it, or click a connection to see the line in the source that created it. After an agent session I can also see which files changed and what else in the codebase can reach them.

The one rule I held to while building it was that the map should only show what it can actually find in the code. If an import can't be resolved to a real file, or it's ambiguous, the tool reports that instead of guessing. That mattered to me because of why I needed the tool in the first place. The problem was that I couldn't fully trust generated code I didn't understand, and solving that with a generated description of the generated code felt like going round in a circle. There's an optional language-model summary, but it only sees what the scanner recorded and is clearly labelled as a summary, kept apart from the facts.

The name comes from Strabo, the Greek geographer, who compiled his map of the known world mostly from other people's accounts and was open about which sources he trusted. That seemed like a reasonable attitude for mapping code other people, or other things, wrote [credits goes for AI who did this research to find name ]

In practice, getting oriented in a new codebase now takes me an hour or two instead of weeks. I look at the map, find the layers and the heavy files, follow a few paths, and only then start reading. The reading goes much better when I already have a rough picture. The tool doesn't tell me whether a change is right, though. It shows structure, not intent, and deciding whether something makes sense is still my job.

What strikes me most is how the tool came to exist at all. A few years ago I'd have looked for something off the shelf, found nothing that quite fit, and lived with it. Now it's realistic to spend some evenings building exactly the instrument I need, with an agent doing much of the typing. I don't think Strabo needs to become a product or find users. It's more like a workbench tool I made for my own hands, and I suspect many people will end up with small tools like this that were never meant to be sold.

If there's a lesson, it's probably that now that producing code is cheap, the work that stays with us is understanding it. I'd rather have tools that help me do that than tools that write even more.

What it does, briefly

  • The map. Strabo scans a local repository and draws its files and dependencies as an interactive graph. It can show whole directories or individual files. Node size reflects how much depends on a file, colour shows which top-level directory it belongs to, and tests are drawn as a different shape.

  • Evidence behind every connection. Clicking a file shows what it imports and what imports it. Clicking a connection shows the source line and how the import was resolved. Imports it can't resolve cleanly are listed as diagnostics instead of being drawn.

  • Inside a file. For a single file it lists types, fields, methods and functions. Where the scanner recorded it, it also shows which methods read or write which fields, a simple view of how data moves through a class.

  • Change review. After an agent session it lists what changed in the working tree or in a given commit, with line counts, plus every file that can reach those changes through the dependency graph.

  • Overlays. On top of the map it can mark circular dependencies, modules no test reaches, and functions with deep nesting or high complexity.

  • Languages. It resolves imports for TypeScript and JavaScript, Python, Java, Kotlin, C#, Rust, C++ and SQL. For SQL, the connections come from which files use which tables.

  • Optional extras. These are all off by default: a language-model summary that only sees recorded evidence, dependency vulnerability and licence checks, and analysis across several repositories at once.

  • Local by design. Everything runs on your machine, and it only reads within a folder boundary you set.

At some point I started pointing Strabo at itself. It's an odd loop: a tool built largely with an agent, used to understand the code that agent wrote. The screenshot shows the file that finds a repository's entry points. The timeline on the left lists the day's changes, including a fix to that very file. The member map shows three constants and thirteen functions spread over sixteen small clusters, with almost nothing linking them, and the cohesion score comes out at 15%. A few years ago I'd have read that number as a problem. Here it just describes the file accurately: it's a set of separate readers for package.json, Cargo.toml and pom.xml that happen to sit side by side, not a class that ought to hang together. That's how I've come to use the quality scores. They point me to where I should look, and after that I still have to understand the code myself before deciding anything.

The code is on GitHub if anyone is curious: github.com/ArtemKunik/strabo.

5 views