A queryable architecture map for my C# codebase
Claude Code gathers context by grepping and reading files. That works for a lot of things. On a composition-first framework it gets expensive fast.
CodiushMaximush is composition-based: classes implement interfaces, inherit base types, get registered in systems the call sites don’t know about. Grep for a class and you find its definition. You don’t find how it fits into the system, what it composes with, what already exists before you try to build it again.
The answer is a structural map of the custom code. Not the whole thing dumped into context: a 422-type index pasted up front is just noise. A queryable map: ask for the slice you need, get compact Markdown back.
That’s Blueprint.
What it does
Blueprint runs Roslyn static analysis over the project’s custom .cs files, builds an on-disk index (namespaces, types, method and field signatures, attributes), and serves slices via three commands:
blueprint summary: top-level namespace and type table of contentsblueprint show <namespace|class>: drill into one branchblueprint show <class> --members: that class’s methods, fields, and full signatures
The drill ladder is ls, cd, cat for the codebase. Orient first, then zoom.
The design calls
CLI, not MCP. MCP re-sends tool schemas every turn. Schema overhead for a structural query you might hit twice in a session adds up. A CLI rides Bash, which is already loaded. The CLI also controls the output format: compact Markdown that fits into context, not a JSON blob that bloats it.
Roslyn syntax trees. Roslyn reads from source without executing anything, so it works even when the project doesn’t compile clean. A build error mid-session doesn’t break the map. Trade-off: signatures are rendered as written, not as resolved symbols. For a structural index that’s the right call.
No LLM in the loop. Filtering a structural map by a query is a deterministic operation. An LLM adds latency and a hallucination risk to something that has to be exact. A code map that lies is worse than no map.
JSON quarantine. The index lives on disk. The CLI returns the queried slice as Markdown. The whole index never enters the agent’s context.
Freshness by mtime. Cache at ~/.cache/blueprint/, keyed by repo. Cold build of ClassicRPG’s custom layer (327 files, 422 types, 87 namespaces) runs in about half a second. Touch one file and only that file re-parses, roughly 0.1s. A cached, unchanged response serves in about 0.02s.
The --docs flag
One addition after the initial build: opt-in /// doc-comment summaries. Pass --docs at the show stage and Blueprint appends <summary> text inline per type or member, extracted from XML doc-comment trivia. No semantic model, no new dependency. Roslyn exposes doc comments as syntax trivia when you ask it to.
Off by default. The compact structural map is the main event. --docs is for when you’ve already navigated to the right spot and want semantic annotation on top.
The honest boundary
One thing v1 doesn’t answer: what references this? Blueprint is a definition map. It knows that DataPipeRegistry exists and what its members are. It doesn’t know which classes hold a reference to it, because that information lives in method bodies, which v1 doesn’t index. You use Blueprint to orient and Bash for the reference queries.
Reverse cross-reference is in the backlog. It’ll come when it’s needed.
Where it stands
Built and smoke-tested against ClassicRPG’s full custom C# layer. The drill ladder works, freshness is correct, and --docs surfaces the /// summaries I’ve been adding to CodiushMaximush. Haven’t put it through a real hard task yet. That’s next.