If claude-code-best-practice is the encyclopedia, this is the field guide.
An opinionated, production-tested Claude Code configuration for solo developers managing multiple apps.
Not a tutorial — a real setup that runs daily across 10+ personal projects,
shared so you can steal the parts that work for you.
The Story · What's Inside · Key Decisions · Quick Start · Adapting · Philosophy
I'm not a developer. I've spent 20 years close to code without writing much of it — I understand architecture, I can debug a concept, but I don't read diffs. I haven't looked at a line of code in my projects for months.
What I do is build things. I maintain a portfolio of 10+ personal apps — budget trackers, reading lists, encyclopedias, games, tools for my family. Different stacks, different audiences, different deployment targets. One development environment: Claude Code.
After months of trial, error, and way too many hours watching Claude Code attempt the same failing fix for the fifth time, I built a system. Commands that orchestrate agents. Agents that remember what they learned. Skills that preload project conventions. Hooks that nudge without blocking.
This repo is that system, anonymized and documented. It's opinionated because opinions are what's missing from most "best practices" repos — I'll tell you what I chose and why I chose it over the alternative.
As Boris Cherny, who created Claude Code, put it: "Every engineer uses their tools differently." This is my way.
┌───────────────────────────────────────────────────────────┐
│ You type a command │
│ /fix /sync /audit /troubleshoot ... │
└─────────────────────────────┬─────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────┐
│ Agents │
│ │
│ implementer ───── sonnet (simple) / opus (complex) │
│ troubleshooter ── opus only (diagnoses, never codes) │
│ docs-checker ─── sonnet (audits README, CLAUDE.md) │
│ portfolio-sync ─ sonnet (cross-repo coherence) │
│ portfolio-audit haiku (compliance checks) │
│ dev-scanner ──── sonnet (discovers & inventories) │
│ │
│ ┌────────────┐ ┌──────────────────────────────────┐ │
│ │ Memory │ │ Skills (preloaded knowledge) │ │
│ │ per agent │ │ • portfolio-conventions │ │
│ │ per project│ │ • code-quality │ │
│ └────────────┘ │ • property-testing │ │
│ └──────────────────────────────────┘ │
└─────────────────────────────┬─────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────┐
│ Hooks │
│ │
│ doc-guard ──────── "Did you update the docs?" (advisory) │
│ build-check ────── "Any warnings left?" (advisory) │
│ memory-reminder ── "Save what you learned" (advisory) │
│ fix-loop-detector "Same file 3× in 30min?" (advisory) │
│ secret-scan ────── "API key in source?" (blocking) │
└───────────────────────────────────────────────────────────┘
Tip
For a visual, interactive version of this architecture, open the workflow guide.
Commands (8) — entry points that orchestrate everything
| Command | What it does | When to use it |
|---|---|---|
/fix |
Bug fix with 3-level escalation cascade (direct → debugging → troubleshooter) | Something's broken |
/sync |
Portfolio-wide manifest sync + JSON generation | Weekly maintenance |
/audit |
Parallel docs-checker + portfolio-audit | Before releases, compliance sweeps |
/troubleshoot |
Escalate to opus for structural diagnosis after 2 failed fixes | Fix keeps failing |
/new-app |
Full scaffold with portfolio compliance from day one | Starting a new project |
/cleanup |
Stale plans, plugin audit, memory compaction | Weekly housekeeping |
/tech-debt |
Monthly triage (with readiness scoring) → deep review → auto-fix | Monthly health check |
/sync-setup |
Sync this repo from live ~/.claude/ config (anonymize + audit) |
After workflow changes |
Agents (8) — the workers, each with a specific role and model
The model selection matters. I don't pay opus prices for a compliance check that haiku handles perfectly. And I don't trust sonnet with a migration that touches 8 files across 3 layers — that's opus territory.
Skills (5) — preloaded knowledge and user-invocable utilities
- portfolio-conventions: condensed version of cross-project standards (naming, signature, dark mode, docs, manifest format, quality gates, display order). Loaded into
troubleshooterandportfolio-sync. - code-quality: before/during/after checklist, common pitfalls, elegance check, spec compliance check. Loaded into
implementer. - property-testing: patterns for property-based tests (roundtrip, conservation, idempotence, no-crash) using fast-check (TS) or hypothesis (Python). Loaded into
implementer. - deploy-status (user-only): HTTP status + latest CI run for every production app in the portfolio, in one command.
- fresh-session (user-only): audits
~/.claude/for startup-cost drift (CLAUDE.md size, plugin count, registered agents) and flags the biggest contributor.
Why skills instead of just writing longer agent prompts? Because skills are reusable across agents, versionable independently, and don't bloat agents that don't need them.
Hooks (6) — 5 advisory + 1 blocking
- secret-scan (PreToolUse → Write|Edit): blocks writes containing API key patterns (
sk-,AKIA,ghp_, etc.), excludes.env.example(blocking) - fix-loop-detector (PostToolUse → Bash): warns when the same file gets 3+
fix:commits in 30 minutes — a signal to escalate (advisory) - auto-format (PostToolUse → Write|Edit): runs Prettier / Ruff / rustfmt on the edited file if the project has the corresponding config — silent if not (advisory)
- portfolio-yml-validate (PostToolUse → Write|Edit
*.portfolio.yml): checks required fields, slug = folder name, numericsort_order(advisory) - portfolio-drift (PreToolUse → Bash
git commit): warns when dependency/deploy files are staged but.portfolio.yml/ README.md aren't (advisory) - stale-readme-guard (PreToolUse → Bash
git push): checks unpushed commits for deploy/dep changes without a README.md update (advisory)
Most hooks are advisory — in a system where I don't review code, I need Claude Code to exercise judgment, not pass checklists. The one exception is secret scanning: accidentally committing an API key is irreversible enough to justify blocking.
The CLAUDE.md at the root is the backbone — ~80 lines of rules that apply to every project. The most important ones:
Important
The 3-level escalation cascade. Each level forces a different approach. No retrying the same level twice. Every fix attempt requires a stated root cause hypothesis — no "let me try a different approach" without a new theory.
flowchart LR
A["🐛 Bug"] --> B["L1: Direct fix
hypothesis → fix"]
B -->|works| Z["✅ Done"]
B -->|"still broken"| C["L2: Systematic debugging
investigate → hypothesize → fix → verify"]
C -->|works| Z
C -->|"still broken"| D["🛑 STOP"]
D --> E["L3: Troubleshooter
opus · structural diagnosis"]
E --> F["📋 New plan"]
F --> G["🔧 Implementer
executes plan"]
G --> Z
style D fill:#dc2626,color:#fff
style E fill:#8B5CF6,color:#fff
style G fill:#3B82F6,color:#fff
style Z fill:#10B981,color:#fff
Warning
Bug triage before code. When I report a bug, Claude Code must rule out environment issues first — stale cache, service worker, old build. The most common "bugs" in my portfolio weren't bugs at all.
Note
Docs in the same commit as code. README, CLAUDE.md, and .portfolio.yml updates ship with the feature, not as an afterthought. If the commit changes behavior, it changes documentation.
The elegance check. Before presenting non-trivial work, pause and ask: "Is there a more elegant way?" I don't review code — Claude Code is the entire quality bar.
The generalization check. Before implementing a specific request, consider whether it's a special case of a more general pattern. If the general solution is roughly the same effort, implement the general version. If not, implement the specific case cleanly — it's easier to generalize clean code later than to simplify over-engineered code.
These aren't arbitrary choices. Each one came from a specific failure. Read the full story for the context behind each decision.
| Decision | Alternative I considered | Why I went this way |
|---|---|---|
| 3-level escalation cascade | Binary "2 fails → architect" | The old binary rule skipped a crucial step: structured debugging. Level 2 (systematic debugging skill) catches tricky-but-not-architectural bugs without invoking opus. |
| Troubleshooter never codes | One agent diagnoses and implements | When the same agent diagnoses and codes, it's biased toward solutions it can implement quickly rather than the right solution. |
| Advisory hooks + 1 blocker | All advisory or all blocking | Most hooks should nudge, not gate. The exception: secret scanning is blocking because committing an API key is irreversible. |
| Property-based tests for invariants | Unit tests only | Unit tests verify examples. Property tests verify laws — "transfers preserve totals" catches edge cases no human would write. |
| Model selection per task | Always use the best model | Haiku is perfect for audits. Sonnet handles 80% of implementation. Opus is for architecture and complex cross-file work. Matching model to task is a quality decision, not just a cost one. |
| Agent memory over lesson files | Flat markdown files per project | Files had no structure, no auto-injection, no compaction. Agent memory is read at startup, written automatically after corrections, and split when it grows too large. |
| Skills as preloaded context | Dynamic tool calls | Skills need to be available before the agent starts thinking. Dynamic loading means the agent might not know what it needs to know when making its first decision. |
| One manifest per repo (.portfolio.yml) | Central inventory document only | Drift. A central doc goes stale the moment you rename an app. A manifest in the repo travels with the code and gets updated in the same commit. |
Note
The setup is fully modular — you can copy everything, cherry-pick individual pieces, or just read and adapt the patterns to your own system.
git clone https://github.com/w2ur/claude-code-setup.git
cp -r claude-code-setup/commands/ ~/.claude/commands/
cp -r claude-code-setup/agents/ ~/.claude/agents/
cp -r claude-code-setup/skills/ ~/.claude/skills/
cp -r claude-code-setup/hooks/ ~/.claude/hooks/
cp -r claude-code-setup/rules/ ~/.claude/rules/
cp claude-code-setup/CLAUDE.md ~/.claude/CLAUDE.mdThen edit CLAUDE.md and the agent files to replace w2ur, {portfolio-site}, and other placeholders with your own values.
The setup is modular. Want just the escalation system? Copy /fix, the implementer agent, and the troubleshooter agent. Want just the maintenance workflow? Copy /cleanup and /tech-debt. Each piece works independently — the full system is better, but partial adoption works fine.
Browse the files, understand the patterns, and build your own version. The philosophy doc explains the "why" behind each choice — that's often more valuable than the "what."
This system was built for a very specific situation — here's how to adapt it to yours
If you have 1-3 apps: You don't need half of this. Drop portfolio-sync, portfolio-audit, dev-scanner — they exist because I have 10+ repos to keep in sync. Keep /fix, /troubleshoot, the two core agents, and the global CLAUDE.md. That alone is a massive upgrade over bare Claude Code.
If you work in a team: The escalation rules still apply — they're about AI behavior, not team size. The implementer/troubleshooter split actually maps well to teams where juniors implement and seniors review. The memory system needs thought, though — per-developer or shared? I haven't solved that one.
If you have a different stack: My skills are specific to my projects. Throw them out and write your own. The architecture (commands → agents → skills + hooks) doesn't care what language you write in.
If you use a monorepo: The portfolio-sync agent assumes separate repos. You'd need a monorepo-aware version. Everything else works as-is.
Caution
- Application code. Zero lines of app code. Just configuration.
- Personal data. Public apps are mentioned by name (they're live on the internet anyway). Private apps, personal URLs, and paths are anonymized.
- A universal solution. This works for me. Parts of it will work for you. All of it, probably not — and that's fine.
This repo stays in sync with my actual ~/.claude/ setup via /sync-setup — a command that runs a Python sync script to copy, anonymize, and audit for data leaks. After any workflow change (new agent, renamed command, new hook), I run /sync-setup and the repo updates itself. See scripts/ for details.
If something looks outdated, it probably means I changed my setup and haven't synced yet. Open an issue — it's a good nudge.
This is a personal setup, not a framework. I'm not accepting PRs that change the architecture or philosophy. But I welcome:
- Bug reports: if something is broken, inconsistent, or unclear
- Questions: open an issue, I'll answer and improve the docs
- Adaptations: if you built something interesting on top of this, I'd love to hear about it
- claude-code-best-practice — the comprehensive reference (encyclopedic, community-maintained)
- Anthropic's Claude Code docs — official documentation
- William Revah on LinkedIn — where I write about building apps with AI, cognitive biases, and whatever else I'm curious about
MIT — copy, adapt, share. Attribution appreciated but not required.
Built by William — someone who doesn't read code but ships 10+ apps anyway.
Read the philosophy for the full story.