Skip to main content

From CLAUDE.md to workflow-atlas: a year of planning patterns, then Dave Jeffery's tweet

12 min read By Craig Merry
claude-code workflow-atlas claude.md opencastor planning plugins tokens rediscovery-tax enterprise

Working across the OpenCastor ecosystem — the Python runtime, robot-md and its satellites, opencastor-client, opencastor-ops, the RRF registry — meant collaborating with Claude across a lot of repos. Over the past year I settled into five overlapping planning patterns. They worked, until they didn’t, and then Dave Jeffery posted a tweet that named the missing layer.

This is the story of what I’d been accumulating, what it kept hitting, and what I shipped in response.

The pattern stack I’d been accumulating

  1. CLAUDE.md at every repo root — the file Claude reads first in any session. Conventions, common commands, weird invariants, the “don’t echo the service-account JSON” warnings. By early 2026 every active repo in my orbit had one — HeatSentry, OpenCastor, opencastor-ops, opencastor-client, robot-md, RobotRegistryFoundation, plus several robot-md satellites.

  2. Per-CWD memory at ~/.claude/projects/<encoded-path>/memory/ — Claude’s auto-memory directory. One Markdown file per fact, with name / description / metadata.type frontmatter. Cross-session continuity for things I didn’t want to repeat: “this branch already has slice-2 work piggybacked on slice-3,” “the HeatFlag.displayName already includes the word ‘Flag’,” etc.

  3. docs/superpowers/specs/ and docs/superpowers/plans/ — once I picked up the brainstorming → spec → plan workflow from the superpowers plugin, those structured docs became the durable trail. Each non-trivial change in opencastor-ops gets a dated design doc and an implementation plan, both committed.

  4. ECOSYSTEM_STATUS.md and PEER_RUNTIMES.md in opencastor-ops — umbrella docs that explain how the repos relate. I’d reach for these whenever a new conversation needed cross-repo context.

  5. READMEs as installable knowledge — install instructions, quickstart, file layout, gotchas. The same content I’d type into a session if asked.

All five surfaces have one thing in common: they’re text. Markdown, mostly, with some JSON sprinkled in. They work — Claude reads CLAUDE.md at session start, the MEMORY files surface relevant facts as [[name]]-linked recall during planning, the spec/plan docs are durable references checked into git.

But text has a ceiling. Once you have a dozen repos talking to each other, the shape of the system matters: which package handles which step, which surface a user’s request first lands on, what the call chain looks like end-to-end. Asking Claude “how does NWS fall back to Open-Meteo for weather in HeatSentry?” or “what’s the lifecycle of a ROBOT.md file from author to runtime?” usually meant a grep tour even when the prose docs were good — because the docs described pieces, and the answer needed the graph.

I’d been noticing the gap for months without naming it. Then Dave Jeffery did.

Dave Jeffery’s tweet

This was the open tab I kept coming back to. Dave posted:

Ask Claude to document and describe the main flows in your app and output in a single page html + json data file.

Incredibly useful for humans and the JSON file is very useful for explaining the flow to the LLM when working on new features/bugfixes.

A reply with the prompt:

Create a single page html that documents workflows between packages and components in the app. Have all the components/packages on the page and I can click on different actions like “Invite new user” or “todesktop build” or {insert other flows here} and then it will highlight the flow between the packages and annotate how things are passed between each package to complete the action. This should be driven from a JSON document which documents all the flows. Does that make sense? Any questions?

That was the missing layer. Not a replacement for CLAUDE.md or the spec/plan docs — a graphical companion. The same information, expressed as a clickable graph backed by a JSON file the LLM could load alongside its existing context.

The two-audience framing is what made me sit up. Humans see a graph and find their bearings in 30 seconds. LLMs read a small JSON file and get the architecture in ~2k tokens instead of grep-touring through 50 files for ~80k. The single artifact serves both.

What I built

I started small. A per-repo docs/workflows/ directory in HeatSentry with index.html, nodes.json, and flows.json. The HTML rendered the nodes via Cytoscape.js + dagre, with a left-rail flow list, side-panel step details, edge highlighting on click. I did the same for opencastor-ops as the umbrella ecosystem view — three families (OpenCastor / robot-md / RRF) with their repos as nodes inside, plus an example robot-md lifecycle flow that traversed all three.

It worked. For about a day. Then it became obvious it should be a plugin: I wanted to install it once and init into any repo, the way the robot-md plugin installs using-robot-md once and binds to any repo’s ROBOT.md.

So I extracted. The public home is workflowatlas.cc — a Cloudflare-hosted single-page app, no install needed to look around. The plugin documents itself there, alongside a LiveCaptionsXR example and a multi-repo combined view.

The install path — for the moment, gated; see Where it stands now below — looks like this:

/plugin marketplace add RobotRegistryFoundation/claude-code-plugins
/plugin install workflow-atlas@robotregistryfoundation
/workflow-atlas init       # scaffolds docs/workflows/ + registers in CLAUDE.md

The data plane

Five JSON files at docs/workflows/ in any repo that runs init:

  • nodes.json — packages and components, optionally with paths globs that bind each node to source files
  • flows.json — named action paths between nodes (“Invite new user”, “todesktop build” — Dave’s examples; mine include “Real-time caption pipeline” for the LiveCaptionsXR example and “robot.md file lifecycle” for the ecosystem)
  • sprints.json — auto-derived from git activity and Claude Code session JSONLs. Each entry covers one 5-hour Claude Code Max token window with real input / output / cacheRead / cacheCreate counts pulled from message.usage on each assistant message
  • milestones.json — target dates + step weights for burn-down forecasting
  • activity.json — per-node commit attribution computed by matching changed-files against the paths globs

Plus two AI-readable outputs the generator writes alongside:

  • atlas.md — a Markdown summary the LLM reads instead of parsing the JSON. The init command writes a ## Workflow Atlas section into the repo’s CLAUDE.md telling Claude to read atlas.md first
  • badge.svg — an embeddable thumbnail for the repo’s README, showing flow count, milestone count, and recent cache hit rate

The pattern: hand-author what only a human can know (the architecture map and the named flows), auto-derive what activity logs already contain (sprints, commits-per-node), and emit AI-readable views alongside.

The view plane

Seven tabs in the rendered page, each one a different question the atlas can answer at a glance:

TabWhat it answers
AtlasHow do the packages talk to each other?
Sprint LogWhat did this 5-hour token window cost, and what shipped?
ForecastWhat’s the burn-down for milestone X, and how many sprints to clear at current pace?
BacklogWhat’s planned, sorted by milestone target date?
KanbanWhere is each step right now? Drag to change.
UsageLike Claude Code’s /usage but scoped to this repo — cache hit rate, effective tokens per commit, rediscovery-tax savings
(History scrubber)Slider that replays the atlas over time — heat-map and Sprint Log update to “now = scrubber date”

The piece that surprised me most after shipping it: the Kanban → Claude hand-off loop. Drag a “planned” card to “in progress,” the dialog asks who’s working on it. Pick Claude. A follow-up dialog gives you a copy-able claude "..." command pre-filled with the step’s label + detail, plus a claude://new-session?prompt=… deeplink. One click, one paste, new Claude session live with the right context. The activity heat-map (toggle on the Atlas toolbar) tints nodes by recency — open the atlas after a week away and you immediately see which packages got changes.

The token-economics math

The framing I keep returning to: every cold Claude Code session pays a rediscovery tax. File reads, grep tours, “how does X talk to Y?” — reconstructing context that should already be on disk. A 5KB workflow atlas + one relevant flow loaded once costs ~2k tokens. The grep-tour equivalent costs 20–80k each time. Multiply by however many cold sessions you start per week.

The atlas isn’t free — you have to author nodes.json and flows.json once, and update them when the architecture genuinely changes. But the JSON files are short. Twenty packages, fifteen flows, two milestones, sized to fit in your head. After that, the generator does the rest.

The catch I didn’t appreciate at first: the atlas only pays off if Claude is actually told to read it. v0.2.0 of the plugin solved that by having init append a section to CLAUDE.md pointing at the atlas. v0.7.x went further and made atlas.md the recommended first-read — cold sessions hit the Markdown summary before any JSON parsing, and the explicit ## Workflow Atlas section in CLAUDE.md says so in plain English.

What this changes about the planning patterns

I haven’t dropped any of the five surfaces I started with. CLAUDE.md still tells Claude how to work in a given repo. MEMORY files still capture cross-session facts. Spec and plan docs in docs/superpowers/ are still where the brainstorming → spec → plan flow lives. Ecosystem-status docs still describe umbrella relationships.

The atlas sits next to them, not on top of them. It’s the graphical layer over the textual context Claude already reads. Its contribution isn’t more information — it’s the same information in a shape that humans grok in 30 seconds and LLMs grok in 2k tokens.

The way I think about it now:

  • CLAUDE.md is how to work here.
  • MEMORY is what’s been learned across sessions.
  • The atlas is how it’s wired and how it’s progressing.

Three nouns, three surfaces, one repo. They cross-link: the atlas’s node-hover popovers pull from CLAUDE.md heading sections (matched by node id); the Sprint Log shows commits grouped by Claude session id; memory files that reference a flow show up as 📌 chips on that flow’s side panel.

What’s in the box (today)

The plugin is at v0.10.0. Ten slash commands (init, refresh, open, add-flow, review, hand-off, install-hook, diff, spawn-pending, note). 68 unit tests on the pure-logic data layer. The generator auto-writes a Markdown atlas summary, an SVG badge, an activity index, a memory-refs index, and a CLAUDE.md-sections index in addition to the sprints file. A GitHub Action template that posts a sticky atlas summary on every PR. Five JSON Schemas at schemas/ for editor autocomplete + validation. Three example datasets shipped, including a multi-repo combined view.

/workflow-atlas review prints a one-screen sprint summary to your terminal. /workflow-atlas install-hook drops a git hook that auto-refreshes the atlas on every push. /workflow-atlas diff <sha1>..<sha2> tells you which nodes and flows a PR touches. /workflow-atlas note latest "<text>" lets Claude append commentary to the current sprint when it learns or decides something worth keeping. /workflow-atlas spawn-pending reads the Kanban hand-off queue and spawns those Claude sessions in fresh terminal windows for you — the bridge from “drag this card to In progress, assign 🤖 Claude” to a live session, with no copy-paste in between.

Ten releases in the build week. The renderer has no runtime dependencies, opens with file://, and otherwise just packages the same static assets you see at workflowatlas.cc — no server required.

Thanks, Dave

The tweet sat in my open tabs for the right number of hours. The two-audience observation — humans + LLMs both benefit from the same structural map — was the framing I’d been missing across a year of accumulating text-based planning surfaces. What I built ended up more involved than what the original prompt produced (sprints, milestones, heat-map, Kanban with Claude hand-off, a Usage tab modeled on /usage, an embeddable badge, an AI-readable Markdown export, JSON Schemas, a history scrubber). But the genome is the same: a clickable single-page HTML driven by JSON files, sized to fit alongside CLAUDE.md rather than replace it.

Where it stands now

A few hours after I first published this post, two things changed.

The landing got a proper redesign. The original gh-pages page was a markdown dump — install commands, a few example links, a URL grammar paragraph. The new home at workflowatlas.cc is a real landing: a hero with an animated mini-atlas that traces the init flow in real time, the rediscovery-tax math told with side-by-side stats (20–80k tokens vs. ~3k tokens), a six-view showcase that switches through Atlas / Sprint Log / Forecast / Kanban / Usage / Backlog miniatures, a “CLI ↔ atlas.md ↔ web” loop diagram, a 3-option install grid, the same four ?atlas=… example permalinks as cards, and a footer with everything else. Anthropic’s warm-cream + terracotta palette, JetBrains Mono for code, Instrument Serif italics for accent words. Hosting moved from GitHub Pages to Cloudflare Pages in the same change.

And the source repo went private. The plugin is moving toward an enterprise edition aimed at multi-user teams — shared atlases across an org, per-user Kanban assignment, attribution on the sprint log, role-aware hand-off. Single-user OSS install is paused while that takes shape. If you’re running a team on Claude Code and want early access, get in touch through workflowatlas.cc.

The build story above still holds — Dave’s tweet, the patterns it crystallized, the two-audience framing, the rediscovery-tax math, why a JSON+HTML shape pays back the authoring cost in cold-session tokens. That part doesn’t change with the distribution model. Multi-user teams just want all of it plus the things a team needs.

If you’ve felt the same ceiling on your own projects — that CLAUDE.md is doing real work but the structural-graph dimension is missing — the workflowatlas.cc examples are the fastest read.