Claude Code is great when you’re working solo. Get a few people using it across a few dozen project repos, though, and the cracks show.

Two engineers reach for it at the same time and end up with two completely different approaches to the same problem. Someone discovers a clever pattern on a Tuesday and the rest of the team finds out about it three months later. The project that someone set up beautifully with CLAUDE.md and skills and slash commands ages out of relevance because nobody updates it. New starters see Claude Code as “that thing some people use,” not the way the team works.

That’s the problem we set out to solve at 3 Degrees North. The result is the TDN Claude Boilerplate, a shared, versioned set of Claude Code extensibility components that we drop into every project as a git submodule. This is a writeup of how it works and the decisions behind it, in case it’s useful to anyone else thinking about scaling Claude Code beyond a single workstation.

What it actually is

The boilerplate lives at .claude/ in each project. Mechanically it’s a git submodule pointed at a single shared repo. So every project shares the same set of:

  • 39 custom slash commands covering tdn-sys-*, tdn-req-*, tdn-arch-*, tdn-dev-*, tdn-test-*, and tdn-pm-*. Each one is a markdown file Claude Code reads as a /command.
  • Auto-activating skills under skills/{name}/SKILL.md that Claude pulls in based on context. No manual invocation needed.
  • Hooks, currently a block-env-read.sh hook that prevents Claude from reading .env.claude directly (more on this below).
  • Templates, files copied from .claude/templates/ into the project root during setup. This is how we ship things like a requirements.txt, a .gitignore.append, an api_explorer.py script, and structural folders for requirements and architecture tracking.

The setup ritual is two prompts the developer pastes into Claude Code from the project root:

Add the TDN Claude boilerplate to this project:

1. Add the submodule:
   git submodule add <repo-url> .claude

2. Read .claude/SETUP.md and execute all the setup instructions in it.

Claude reads .claude/SETUP.md (which is written for Claude, not for the developer) and walks through copying templates, updating .gitignore, setting up a Python venv for the helper scripts, and configuring optional MCP servers. The developer just confirms when prompted and restarts Claude Code at the end.

That deliberate split between a quickstart for humans and setup instructions for Claude turned out to be one of the more useful design choices.

The four workflow domains

The 39 commands cluster into a few coherent jobs.

Requirements (/tdn-req-*, 13 commands)

This is the most-used domain. It’s an end-to-end pipeline:

  • Discovery transcript to structured extraction. /tdn-req-process-transcript chews through a recorded call and pulls out facts, assumptions, decisions, and questions into a structured shape.
  • Validation loop. /tdn-req-generate-questions produces a list of clarifications, /tdn-req-validation-view renders an HTML page we can screen-share with the customer, and /tdn-req-record-responses captures what they said.
  • Formalisation. /tdn-req-generate turns validated extractions into formal requirements. /tdn-req-signoff-doc produces a customer-facing version. /tdn-req-record-signoff logs the approval.
  • Push to delivery. /tdn-req-create-tasks writes the approved requirements out as tasks in Productive (our PM tool), via a custom MCP server.
  • Change management. /tdn-req-change and /tdn-req-status handle change requests and reporting.

What this gives us, practically, is that a discovery call can become a structured spec sitting in our PM tool by end-of-day, with the audit trail intact. None of it is magic. It’s just a pipeline that happens to be tireless.

Architecture (/tdn-arch-*, 6 commands)

A guided iterative Q&A session for capturing architecture decisions, producing ADRs and ASCII diagrams along the way, and generating a review document at the end. We use this when we need to lock in a design before writing code, exactly the moment most projects skip.

Development (/tdn-dev-*, 7 commands)

Per-session and per-sprint workflow. /tdn-dev-init to set up a project, /tdn-dev-plan and /tdn-dev-session to work in plan mode, /tdn-dev-handoff to produce a handoff document, multi-environment deployment tracking. This is the layer that makes the day-to-day rhythm consistent across the team.

System / meta (/tdn-sys-*, 7 commands)

The interesting domain. These are the commands that maintain the boilerplate itself:

  • /tdn-sys-search searches Azure Artifacts packages first, then code across all 80+ project repos in our org, with semantic matching and recency sorting. It’s our “is there already a TDN.Imis package for this?” reflex made executable.
  • /tdn-sys-api-explore lets Claude make authenticated API calls against an endpoint described in .env.claude, without ever showing the credentials in conversation. The hook above blocks Claude from reading .env.claude directly; the explorer script reads it at runtime and injects the auth.
  • /tdn-sys-learn is the meta-system. When Claude iterates to find a solution to a tricky problem, this command captures the pattern as a new auto-activating skill that future Claudes will reach for without prompting.
  • /tdn-sys-doctor analyses a project’s Claude Code config and recommends improvements.
  • /tdn-sys-boilerplate-pull and /tdn-sys-boilerplate-push are the distribution mechanism. Pull updates from the shared repo into a project, or push improvements back so they spread to everyone.

Some decisions worth flagging

Submodule, not template

It would have been easier to scaffold a project from a template on day one and then let it diverge. We chose a submodule specifically because of the divergence: when the boilerplate updates, every project picks up the change next time the developer runs /tdn-sys-boilerplate-pull. Templates fork; submodules sync.

The cost is git submodule weirdness, which is real. But the alternative is dozens of slowly-rotting copies, which we’ve lived through before.

Setup instructions written for Claude, not for humans

SETUP.md reads like a runbook addressed to Claude: “Step 1: Copy template files. Step 2: Update .gitignore. Step 3: Set up Python venv.” The developer doesn’t have to follow it. Claude does. This sounds like a small thing but it changes who carries the cognitive load. The developer types one prompt; everything else is delegated. It also means the setup stays self-correcting: if Claude flubs a step, the developer notices in the next message and corrects, and we update SETUP.md to make it foolproof for next time.

A custom MCP server backs the workflows

The slash commands are fronts for a real persistence layer. The TDN Admin MCP server holds requirement state, architecture state, dev session state, and sprint plans. Without it, every command would be a one-shot generation; with it, /tdn-arch-design can resume a session you started yesterday, and /tdn-req-status can produce a real status report. This is the part that took the longest to build and is the most under-appreciated.

/tdn-sys-learn is the bet

Most enablement frameworks decay because they’re top-down: someone publishes a guide, nobody updates it, and a year later it’s stale. /tdn-sys-learn flips that. When an engineer iterates with Claude to solve a thorny problem, the command captures the working pattern as a skill in .claude/skills/. The next person who hits a similar problem gets the skill auto-activated. The team’s collective debugging history becomes a substrate the team can stand on.

It’s the same idea as a postmortem template, except it’s executed by the tool that solved the problem in the first place, which is the only honest way to keep documentation in sync with reality.

Security: the hook nobody thinks about

Claude is happy to read .env.claude and recite the contents. So we put a PreToolUse hook on Read that blocks it. The API explorer script reads the file at runtime and injects auth into requests, but Claude never sees the secret. This is a five-line hook that prevents a category of mistake we’d otherwise have to be careful about. Every Claude Code setup with credentials should have one.

What’s next

A few things on my list:

  • Open-sourcing the workflow patterns (the commands themselves are tied to our customers’ shapes, but the patterns generalise).
  • Skill curation. We have a small library now. As /tdn-sys-learn produces more, they’ll need pruning and consolidation. I’m watching how that decays.
  • Better feedback loops, measuring which commands actually get used, which skills auto-activate, what falls flat. Right now we run on intuition.

If you’re thinking about Claude Code at team scale and want to talk about any of this, I’m at j@jaym.cc. Happy to compare notes.