These are your father's dotfiles


These are your father’s parentheses

This famous XKCD keeps popping into my mind as I watch Claude Code insisting on running stuff like find . -name "*.py" | xargs grep "function_name" across a fifty-thousand-line codebase, burning tokens like mad, waiting, waiting — when ctags could have answered in milliseconds. The crazy thing isn’t that Claude is doing it, it’s that people are watching the madness and approve mindlessly… as if a better way wasn’t the standard just a short while ago.

These are your father’s dotfiles; A collection of more elegant tools, for a more civilized age.

The environment as craft

There was a time when the developer’s relationship with their tools was, above all else, a relationship. The old Unix Development Environment - which by the Unix philoshophy was the opposite of “Integrated” - kind of forced you to assemble your selection of tools and encouraged customizations and extenstion. The .vimrc that started as five lines and grew, over years, into four hundred. The .bashrc full of aliases assembled through accumulated pain — alias gs='git status' because you typed it a thousand times and finally said enough. The ctags setup, the custom grep wrappers, the script that reformatted logs into something readable, the snippet library that encoded hard-won knowledge about the company’s internal APIs.

Developers carried their dotfiles from job to job the way craftsmen carried their tools. The environment was never finished because the work was never finished. You hit a problem, you filed off a rough edge. You discovered a better way to navigate code, you wired it in. You were not just using your tools; you were evolving them.

This wasn’t nostalgia bait. It was practical. ctags gave you symbol-level navigation across a codebase with zero runtime cost. grep pipelines, chained and filtered, could answer questions that no GUI search box ever thought to ask. A well-tuned vim or Emacs with the right plugins did AST-aware indentation, completion from the project’s own symbol table, and macro replay over a selection — before the term “IDE feature” had been invented.

The crucial thing wasn’t any specific tool. It was the underlying assumption: if the environment doesn’t serve me well, I will fix the environment.

The IDE bargain

Then IDEs came along, and they were genuinely, substantially better. Integrated debuggers that stepped through code. Project-aware refactoring that renamed a symbol everywhere without a prayer and a regex. GUI git blame. Inline compiler errors. A generation of tooling that made the old scattered workflow feel cobbled-together by comparison.

This was real progress. But something subtle and unseen was being lost.

IDEs came pre-configured, opinionated, and — critically — packaged; New projects boasted about having “Batteries included”. Customization existed, technically, but it was no longer mandatory and encouraged. The culture shifted, almost without anyone noticing, from “I will build what I need” to “I will use what I am given.” The mindset of the tool builder began to atrophy. And then the fashion cycle accelerated.

People started changing tools faster than they were changing socks. Every month there was a new hype, and unlike the previous era, where changing a tool would entail redoing years of learning, habituation, customization and extension - changing a tool seemed easy and cheap. Each transition reset the learning clock. Nobody read the manual because by the time you’d finished reading it, everyone else had moved on. The implicit message from the community was clear: the specific tool matters less than looking current.

The tragedy is what got left on the table. IDEs are extraordinary pieces of software. IntelliJ’s indexer builds a complete model of your project’s type graph. VS Code’s language server protocol enables semantic understanding that makes ctags look primitive. Call hierarchy navigation, unused import detection, structural search-and-replace — features that could transform how you work, sitting idle because nobody bothered to learn they existed. I watched in horror young engineers use JetBrains IDEs — tools that cost hundreds of dollars a year and represent decades of engineering — as glorified text editors with syntax highlighting. They CMD+F’d through files. They copy-pasted method names by hand. They had no idea there was a “Find Usages” button let alone keyboard shortcuts and advanced refactoring.

No wonder Atom landed so easily. They couldn’t tell the difference.

Enter the AI editor

Now we’re here: Claude Code, Cursor, Copilot, Windsurf. The hot take writes itself — “who needs an IDE when you have AI?”

I get the appeal. The pitch is real — AI assistants are transformative.

Watch what actually happens when Claude Code navigates a large codebase without any augmentation. It reaches for find and grep. It reads files it doesn’t need, to triangulate where the thing it does need might live. It burns context on directory listings. When it wants to know what calls a function, it has no way to ask that question efficiently — it has to guess, search, read, guess again.

Claude Code is trained and tuned for the lowest common denominator: whatever works on any common environment, cold, with no setup. That’s a reasonable default, but a terrible ceiling. It’s slow, inefficient and consumes tokens faster than a drunk consumes free whiskey; if I was conspiratorial I’d suspect Anthropic is doing it on purpose.

(Codex, for what it’s worth, does have code indexing. The gap is real, known, and apparently not considered a problem worth solving in most AI editor setups. Draw your own conclusions.)

Your father’s dotfiles were right

Here’s the thing: this is a solved problem. A boring, old, well-understood solved problem. The buzz nowdays is that every developer is now a manager of a fleet of junior engineers - if that’s the case, go teach your AI engineers the basics.

The first order of business is replacing the blunt instruments Claude defaults to. ripgrep is what grep wishes it were — faster, .gitignore-aware, and with output that doesn’t require squinting. fd does the same for find. These are drop-in improvements you can wire into CLAUDE.md in five minutes and never think about again.

For structural navigation, the old tools hold up better than you’d expect. Universal ctags — yes, the program your father had in his .vimrc in 1998 — generates a symbol index Claude can query to find any definition or reference in milliseconds, no grep required. ast-grep goes further: structural search based on the actual parse tree rather than text patterns. Find every function that takes a nullable argument. Find every React component that renders a list without a key. Questions grep fundamentally cannot answer, answered in one command.

For deeper semantic understanding, tree-sitter-based tools build a full model of your codebase rather than just indexing symbols. codebase-memory-mcp is one approach — an MCP server that exposes tree-sitter analysis directly to Claude. graphify is another, turning code into a traversable knowledge graph Claude can query like a database. These are the rough equivalent of IntelliJ’s type graph, available without a JetBrains license.

And then there’s CLAUDE.md — the .bashrc for your AI environment. Project-specific instructions, conventions, which tools to prefer, what directories to stay out of. It’s the closest thing we have to dotfiles for the new era, and most projects don’t have one - let alone user level customisations.

Wiring these up is not a research project. It’s an afternoon. The knowledge required is exactly the knowledge your father applied when he added a function to his .bashrc to avoid typing the same twelve characters repeatedly: if the environment isn’t serving me well, I can fix the environment.

Most people don’t do this. They just accept the defaults. They burn tokens on recursive grep. They switch to the next tool when it gets slow, carrying nothing forward, having learned nothing.

The mindset is the tool

The dotfiles weren’t the point. The point was the relationship with tools — the assumption that you were entitled, even obligated, to understand them and improve them.

Once you adopt the mindset you start evolving Claude’s toolchain very quickly — especially after you figure out you can use Claude to build its own tools and skills, and spot opportunities for extension.

Every generation inherits better tools and a weaker grasp of what the tools are actually doing. The Unix hackers knew their environment down to the system call. IDE users knew their IDE’s feature set, roughly. AI editor users know how to write a prompt. Each step up the abstraction ladder is genuinely useful and carries a genuine cost. The cost isn’t capability — the tools are more capable than ever. The cost is agency — the attitude of not accepting things as they are and actively seeking to change your situation.

And isn’t that — agency — what human engineers are still needed for?

engineering-culture tools developer-experience ai
comments powered by Disqus