When you first install Claude Code, it's tempting to treat it as a smart autocomplete. After running it for several months across four production sites, my mental model has shifted considerably: Claude Code works best when you treat it as the backbone of your development process rather than a side tool you occasionally consult.
By "operational design" I do not mean a collection of clever CLAUDE.md tricks or hand-crafted slash commands. I mean treating five concerns — project memory (CLAUDE.md), external integrations (MCP), workflow automation (skills), quality assurance (hooks), and parallelization (subagents) — as a single coherent system. Once these five pillars start reinforcing each other, Claude Code's behavior becomes remarkably stable.
This post distills what has actually worked for me across the four sites I run under Dolice Labs. Every snippet you see is taken from a system that runs in production every day.
Pillar 1: Concentrate project memory in CLAUDE.md
Claude Code's most underrated feature is its ability to load a single CLAUDE.md file at the root of your repository as persistent project memory. Every new session starts with that context already loaded.
For a long time I treated CLAUDE.md as just another README. The mental shift came when I started thinking of README as "documentation for humans" and CLAUDE.md as "a slightly drier instruction sheet aimed at an AI." The template I have settled on looks like this:
# Project Name — CLAUDE.md
## Scope of this article
(One or two paragraphs: what the repo is, who reads it.)
## Critical Rules
1. Always create JA + EN article pairs.
2. Verify file counts match before pushing.
3. Work inside /tmp/, never push from the workspace clone.
## Autonomous Execution Policy
- Do not ask for confirmation; pick the best option and proceed.
- On failure, attempt automated recovery before giving up.
## Troubleshooting Table
| Symptom | Fix |
|---|---|
| git push rejected | git pull --rebase, then retry |The three sections that earn their keep over time are Critical Rules, Autonomous Execution Policy, and the Troubleshooting Table. Critical Rules should be the three to five constraints Claude Code most often forgets. The autonomous policy defines how far Claude Code is allowed to act on its own. The troubleshooting table is a running log of past failures and their fixes — it stops you from losing the same hour twice.
Because CLAUDE.md grows quickly, push project-specific operations guides into separate files (I keep mine under _documents/) and have CLAUDE.md point to them rather than duplicate their content.
Pillar 2: Make external systems first-class via MCP
Model Context Protocol (MCP) is the standard way to expose external tools to Claude Code: GitHub, Slack, databases, internal APIs. Anything Claude Code is going to touch repeatedly should be reachable through an MCP server so you stop pasting context by hand.
The first MCP I install is always one that connects directly to the system I'm operating. For sites deployed on Cloudflare Workers, that means the Cloudflare MCP — Claude Code can then check Worker logs, manipulate KV namespaces, and inspect deploy state without leaving the session.
In the configuration file I always leave a comment explaining why each MCP is installed:
{
"mcpServers": {
"cloudflare": {
"command": "npx",
"args": ["@cloudflare/mcp-server-cloudflare"],
"comment": "Used for Worker logs, KV ops, and deploy status checks."
}
}
}The comment field is not part of the official spec, but Claude Code reads JSON comments fine, and your future self will thank you when you revisit the project six months later.
Pillar 3: Lock down repeatable work with skills
Slash commands and skills (.claude/skills/) are where you turn repeatable processes into something Claude Code can execute reliably. For my blogs, the entire publishing workflow lives in _skills/{site}/SKILL.md as a numbered sequence of steps.
What makes skills powerful is that Claude Code reads the description and decides on its own when to invoke them. The trick is to write descriptions in terms of how a user would phrase the request, not in terms of what the skill technically does:
---
name: site-content-update
description: "Generate and publish articles for site.net. Triggers: 'write an article', 'post a blog', 'update the site', 'generate content'."
---
# Article Update Skill
## Step 0: Prepare repository
... commands ...
## Steps 1-8
... each step ...Including natural phrasings like "write an article" or "post a blog" lets users invoke skills the way they actually talk, instead of memorizing a special command.
Pillar 4: Bake quality assurance into hooks
Hooks let you run custom scripts at specific Claude Code lifecycle events — before/after a file edit, before/after a tool call. I treat hooks as the last line of defense for quality.
For my blogs, every MDX edit triggers a hook that runs three checks:
- The frontmatter YAML still parses.
- JA and EN article counts match.
- Internal links point to articles that actually exist.
When that hook is wired up, Claude Code runs it the moment it finishes editing a file, sees any failures, and starts fixing them on its own. The "I forgot to run the validator" class of human error simply stops happening.
#!/bin/bash
# .claude/hooks/post-edit-mdx.sh
FILE="$1"
[[ "$FILE" == *.mdx ]] || exit 0
# Frontmatter validation
node scripts/validate-frontmatter.mjs "$FILE" || exit 1
# JA/EN count check
JA=$(find content/articles/ja -name "*.mdx" | wc -l)
EN=$(find content/articles/en -name "*.mdx" | wc -l)
[ "$JA" -eq "$EN" ] || echo "⚠️ JA=$JA EN=$EN — mismatch"Hooks should be fast, idempotent, and fail with a clear message. Get those three right and Claude Code will read the output and recover on its own.
Pillar 5: Parallelize with subagents
Long-running tasks run faster and more safely when you split them across subagents — separate Claude Code processes spawned from the main session, each handling a single sub-task.
The three patterns I use most often:
First, separate research from implementation. "Find where the cache layer lives in this repo" is research; spin it off to a subagent so the main context stays clean, then use only the returned summary (file paths, key snippets) to do the actual work.
Second, parallelize across independent targets. When I need to update all four sites at once, I launch one subagent per site, each operating in its own working directory. End-to-end time drops to roughly a quarter.
Third, run a dedicated verification subagent. After implementation, hand the diff to a second agent and ask it to review with fresh eyes. The agent that wrote the code is rarely the best reviewer of it.
Each pillar reinforces the next
These five pillars are not independent features. CLAUDE.md sets direction, MCP wires you into the world, skills lock down repeatable steps, hooks guarantee quality, and subagents add parallelism. Once the loop is closed, Claude Code stops feeling like a tool you reach for and starts feeling like the engine your workflow runs on.
Day-to-day coding works fine without any of this, of course. But the moment your workload involves repetition or multiple projects in parallel, the gap between an operationally designed Claude Code and a stock one widens fast.
If you only do one thing today, write the three core sections of CLAUDE.md — Critical Rules, Autonomous Execution Policy, and Troubleshooting Table. You will find yourself listing things you have explained to Claude Code more than once, and that list is exactly where operational design begins.