Using GraphViz for CLAUDE.md
This is a very, very informal interim research report about something I've been playing with over the past couple days. Last Friday, I saw an absolutely astonishing extemporaneous talk by an organization that is so far down the curve of AI maximalist development that it kind of broke my brain. I'm hoping to write more about a bunch of what I saw in the coming weeks, but I'm very much still digesting what I saw. One of the things that I thought they said during the talk was that they were using .dot (GraphViz) as the language that they are using as the formalization for new processes for their coding agent. It made sense to me. There's enough dot on the Internet that models can read and understand it quite well. And it removes a whole bunch of the ambiguity of English language specifications. It turns out that I completely misunderstood what was going on, in the best possible way. They're using GraphViz, but not for that. They're using Markdown files to allow the agent to document new processes and capabilities for itself. That makes tons of sense. It's roughly the same format that Anthropic is using for Claude's new 'SKILL.md' files, which are just Markdown files with YAML frontmatter. But before I was corrected, I went home and started experimenting. And... I'm kind of excited about what I ended up with. The first thing I did was that I asked Claude to convert my CLAUDE.md into GraphViz. It worked pretty well because most of my CLAUDE.md was process documentation. The first iterations (which didn't get saved) were somewhat unhinged. My processes were inconsistent and doing this work made the problems very, very obvious. Over the course of a couple hours, Claude and I iterated on my processes and on how to use dot as specification language. There was only one absolute disaster of a hallucination when I asked Claude to update the process with what would be "100x better" and it threw in a whole bunch of Science Fiction features...that will still probably be Science Fiction 6 months from now. After about a dozen rounds of iteration, we workshopped my processes to the point where they mostly seemed to flow correctly AND the .dot document was really readable by both of us. And then I swapped it in place of my CLAUDE.md and fired up a session and...Claude behaved normally and understood my rules. I ran a couple of vibechecks, asking it for the same small project with both the traditional rules and the .dot rules. It was a very unscientific test, but I found the .dot version of Claude and its output preferable. At least in these early tests, Claude seems better at understanding and following rules written as dot. And the format makes it much easier to visualize many situations when you're giving your robot buddy rules it can't follow. We also put together a .dot styleguide to eventually let Claude more easily write its own processes. I haven't yet had a ton of experience with CLAUDE self-documenting new processes, but that's coming. (As an aside, I also have another mini-project running that's extracting learnings and memories from all my previous Claude Code sessions. But that's a story for another day. Until then, you can find it on GitHub at https://github.com/obra/claude-memory-extractor) This was my most recent CLAUDE.md before this project: This is my current CLAUDE dot md: What follows is a mini-writeup written by Claude (Opus 4.1). I made the mistake of asking it to write in my voice, but make no mistake - all the words after this point are generated. They don't tell a good story about my motivations, but the narrative does a decent job explaining the investigation process. I've been working with Claude for a while now, and I have a detailed CLAUDE.md file that contains all my rules and preferences. It's great, but it's also... a wall of text. Rules like "NEVER use git add -A" and "You're absolutely right!" is forbidden are scattered throughout. When Claude needs to follow a complex process, it's not always clear what the actual flow should be. So I had an idea: what if we could use Graphviz's dot language as a DSL for documenting processes? Not for pretty diagrams (though that's a nice side effect), but as a structured, searchable, executable process definition language that Claude can actually read and follow. First attempt - just document everything that's already in CLAUDE.md as a massive flowchart: This was... overwhelming. Too many boxes, too many connections, and honestly, Claude would never be able to follow this. It looked comprehensive but wasn't actually useful. I realized Rule #1 ("Break any rule? Stop and ask Jesse") shouldn't be a separate entry point but should be embedded throughout: Better, but still treating processes as these separate phases that don't really reflect how work actually happens. Tried to create a more unified workflow: This was starting to look more realistic, but still too academic. The "continuous processes" box was a particular cop-out - those aren't separate activities, they happen during the work. Tried to boil it down to the essence: Cleaner, but now we'd lost important detail. Also those emoji warnings didn't render properly - turns out Graphviz doesn't love Unicode. Got ambitious and created two versions - one documenting current processes, one imagining what would make Claude "superhuman": This was incredibly detailed - 7 layers of process! But when I asked myself "could Claude actually follow this?" the answer was no. Too complex. This was fantasy. Things like "confidence percentages" and "cognitive load monitoring" - Claude can't actually do these. I was designing capabilities that don't exist. Converted the "superhuman" version into things Claude could actually do: Better! Actionable steps like "Write down what's not working" instead of "Monitor cognitive load." But the task classification at the start was artificial - Claude doesn't actually know if something will take 30 minutes. Time to get real about what actually happens: This version admitted the truth: Claude often jumps into coding too quickly, forgets to search for similar code, and has specific danger zones where it fails. Much more useful! Tried organizing as a proper framework: But then I realized - these aren't really "phases." Work doesn't happen in phases, it's all interconnected with loops and branches. Getting closer to reality: This showed the actual flow better, but was still hard for Claude to parse from the dot file itself. Then came the key insight: Claude doesn't need one giant flowchart. It needs to be able to jump to the right process based on the current situation. Enter trigger-based design: Now each cluster is a self-contained process that starts with a clear trigger. Claude can search for "stuck" and find the "When Stuck" process. Much better! Then I learned you can use quoted strings as node identifiers in dot: Instead of: This transformed everything! The final readable version: Now the dot file itself is readable documentation. Claude can parse it directly without mental translation. Removed all labels and used semantic naming: With good naming, the labels are completely redundant. The diagram is cleaner and the source is more maintainable. We even created processes for maintaining the processes: The key insight: processes come from experience, not planning. Either Jesse teaches me something, I discover a pattern through repetition, or I hit a gap in existing processes. To make this systematic, we created a style guide - also written in dot! The style guide defines: Applying all these lessons: This version: Using Graphviz dot notation as a process DSL is actually brilliant because: Instead of one massive flowchart, having separate processes with clear triggers is much more useful: Using quoted strings and meaningful names makes the dot files themselves readable: Is so much clearer than: Using different shapes systematically helps Claude understand what type of thing each node is: The most useful version wasn't the most comprehensive one. It was the one that: Instead of one giant file, we could have a process library in : Each file would be a focused, trigger-based process that Claude could load when needed. We could even hook this into the slash command system - imagine loading and displaying the relevant process. What started as an attempt to visualize CLAUDE.md turned into discovering that Graphviz's dot language is actually a fantastic DSL for defining executable processes. The key wasn't making prettier diagrams - it was realizing that the text representation itself could be the documentation. The final version is something Claude can actually read, understand, and follow. It's not perfect, but it's honest about how Claude actually works and where it tends to fail. And that honesty makes it genuinely useful. Most importantly, this isn't just documentation - it's a living process definition that can evolve as we discover new patterns and better ways of working. Every time Jesse teaches me something new or I discover a pattern that works, it can become a new process in the library. The real magic is that we're using a graph description language for what it was meant for - describing flows and relationships - but in a way that's both human-readable and machine-parseable. That's the sweet spot for AI assistance tools. Different node shapes for different purposes (diamonds for decisions, octagons for warnings, etc.) Naming conventions for clarity When to add new processes How to test if a process is useful Uses semantic node shapes (plaintext for commands, diamonds for decisions, octagons for warnings) Has clear trigger points for each process Is readable both as a diagram and as source code Actually represents how Claude works, not how we wish it worked It's visual when you need it to be It's searchable text when Claude needs to find something It enforces structure (nodes and edges) It's version controllable It renders nicely for documentation "When stuck" -> go to stuck process "Test failing" -> go to debug process "New request" -> go to request process for decisions for literal commands to run for critical warnings Admitted where Claude actually fails Included only processes that actually get used Used simple, clear language Could be followed mechanically