I lost most of a weekend to the same shape of NGO bug twice on the same project. By the end of the postmortem I was angry at myself, but I was also pretty sure I’d repeat it on the next prototype if I didn’t change something. The thing I changed was small: I started a separate repo for the rules I keep forgetting, and wired each rule into Claude Code as a Skill that triggers itself the next time I write that kind of code.
https://github.com/tang3cko/standards
This post is about that repo, what’s actually in it, and why I think the rule-shaped version of a lesson outlives the blog-post-shaped version.
The trigger
The honest answer to “why a standards repo” is that I didn’t trust myself to remember.
The Wave 3 MTU bug on my NGO prototype was the proximate cause. I picked an Unreliable ClientRpc for a periodic snapshot, the snapshot crossed ~1200 bytes at the third wave, and the host started throwing OverflowException because Unity’s NGO does not fragment unreliable sends. The full writeup is here:
What made me start the repo was that this was the second Wave-3-flavoured failure on that project. Different layer, same lesson about caching state that should have been queried on demand. Two weeks earlier I would have shrugged and added a comment in CLAUDE.md. This time I wrote down the rule in a place I could actually pull into the next project.
What’s in tang3cko/standards
It’s a public repo with a flat skills/ directory. Today there are eight skill folders, each with a SKILL.md and a references/ subdirectory:
unity-core— naming, namespaces, runtime/editor boundary, InputReader pattern, null safetyunity-architecture— ScriptableObject architecture rules (the Reactive SO side of things)unity-async— async / coroutine conventionsunity-networking— NGO payload budget, mechanism decision tree, snapshot streaming, anti-patternsunity-testing— test layout and conventionsunity-ui— UI Toolkit conventionsunity-mcp— rules for using the Unity MCP server from Claude Codegame-design— game-design notes that I want pulled in during design conversations
The repo installs as a Claude Code plugin in one line: /plugin marketplace add tang3cko/standards. Each SKILL.md carries the frontmatter that Claude Code expects — name, a description packed with trigger phrases, a model hint, and allowed-tools. Docs: Claude Code Skills.
Every standard inside the references is tagged with one of three priority labels: must fix, should fix, nice to have. The point is that a review produces something with a clear cut line instead of a wall of suggestions I’ll ignore.
How a single skill is shaped
unity-networking is the one that came directly out of the Wave 3 bug, so it’s the most honest example.
The SKILL.md description carries the triggers that auto-fire it: NGO, Netcode, RPC, NetworkVariable, ClientRpc, ServerRpc, snapshot, MTU, OverflowException, fragmentation, bandwidth, plus the Japanese equivalents (同期, ネットワーク, 帯域). If I open a file and start typing any of those, the skill loads itself.
The body is short. It states three principles — payload size is part of the design contract, unreliable means MTU-bound, mechanism is chosen by frequency × persistence — and routes to one of four flows: designing a new sync system, debugging an overflow, reviewing existing code, or picking between RPC / NetworkVariable / CustomMessage. Each flow pulls in a specific reference file:
_core-rules.md— auto-loaded, the size budget and the decision treesync-mechanisms.md— full comparison of NetworkVariable, RPC, CustomMessage, OnSynchronizerpc-payload-rules.md— Reliable vs Unreliable, MTU detailssnapshot-streaming.md— chunking, quantization, sequence reassemblyanti-patterns.md— the failure modes, including the one I shipped
The Wave 3 lesson lives in _core-rules.md as a number, not as prose. ~1200 bytes safe payload for Unreliable. The reason it’s a number is that the bug was a number, and a paragraph would have let me round it up the next time I was in a hurry.
unity-core is shaped the same way. A small SKILL.md that branches into references — naming.md, code-organization.md, editor-tooling.md, error-handling.md, input-system.md, comments.md. The runtime/editor boundary rule (no OnDrawGizmos in committed runtime classes, escalate to an editor asmdef instead) lives in code-organization.md. That’s the file I would have wanted Claude Code to load the third time I noticed gizmo code creeping into a runtime asmdef.
Why a repo and not a doc
Three things I actually use.
A SKILL.md has a commit history. When I read a rule now I can git blame it back to the failure that produced it, and that’s saved me at least twice from softening a rule I’d already paid for.
Plugins distribute. One line — /plugin marketplace add tang3cko/standards — and a new prototype picks up the whole rule set. No copy-pasting CLAUDE.md fragments between repos.
Triggers run themselves. When a rule only fires if I remember to read it, I tend to forget it exists. The Skill description’s trigger list is what does the work for me — I don’t have to remember the standard, I just have to be typing code that mentions ClientRpc.
The lifecycle of a rule, in practice
The pipeline I keep ending up with looks like this:
- A failure happens in a project. (Wave 3 took two prototypes to notice.)
- I write the long-form postmortem as a blog post draft, because writing it down is how I figure out what actually went wrong.
- The lesson gets boiled into one or two numbered rules with priority labels in
standards/skills/<domain>/references/. - If a new trigger phrase is needed, it goes into the relevant
SKILL.mddescription. - The next project pulls the plugin, and the skill fires the next time I touch that domain.
For me the blog post and the rule do different jobs. The post is where I work out the story; the rule is where I pin down the number I keep getting wrong. I want both around, but only the rule needs to travel with me into the next project.
What I’d push back on (myself)
This was overkill while I was one project deep. Back then a paragraph in CLAUDE.md did the job, and a separate skills repo would have been ceremony. The standards repo only earned its place once the same shape of bug was about to happen on a different project, which is roughly when I started building it.
The repo also isn’t anything close to a style guide. The README still lists a repository-setup entry I haven’t migrated into the current skills/ layout, and there’s a Mirror networking reference under unity/networking/mirror/ that I should either turn into a skill or delete. I’d rather ship it half-tidy and actually pull rules into my own next project than wait for a clean version that never lands.
Wrap-up
The shift that mattered wasn’t writing down standards — I’d done that before in CLAUDE.mds that nobody read, including me. The shift was attaching the standards to triggers, so they fire on the keywords I’m already typing.
If you want to see the actual files, the repo is here:
https://github.com/tang3cko/standards
And the postmortem that started it:
PostHow a 1200-byte ceiling on an NGO Unreliable RPC quietly capped my Wave 3Wave 3 enemies vanished on the client while still hitting the player. The host was throwing OverflowException. Here's the failure story behind a hidden MTU ceiling in Unity Netcode for GameObjects, and what the industry actually does about it.The first time I shipped the bug, I chalked it up as tuition. The second time, on a different project, was what finally pushed me to start the repo.
Carving out time to write the rule after each failure isn’t easy alongside the day job, but the next prototype now picks up the whole rule set in one line, and that’s been worth it for me so far.