The 2 Files That Decide If Claude Code Ships or Breaks

Day one with Claude Code feels like magic. Day seven you've burned $12 in tokens on a bug fix because it re-read your whole repo four times and rewrote auth logic you never asked it to touch. The fix isn't a course or a six-agent persona stack — it's two files and one folder rule, and I'll paste the exact configs I run across three revenue-generating products right now.
The setup that actually ships
I run three live products off one WSL box: an invoicing tool for SMBs, an ops bot ecosystem handling email and chat, and a lead-gen engine for a small agency. Total infra cost is about $52/month. Active Claude Code time across all three averages 22 minutes a day. There is no AIOS meta-folder, no subagent orchestra, no persona prompt calling Claude a "senior architect." Two files per repo, one folder rule, and a hard cap of two terminal tabs open at once.
The failure mode most solo builders hit isn't Claude being dumb. It's Claude being unconstrained. Give it a whole repo tree with no fence and it will happily notice patterns, refactor things you didn't ask about, and re-read 40 files per prompt because nothing told it where to stop. Both files below exist to draw that fence.
File 1: CLAUDE.md — six sections, under 90 lines
CLAUDE.md lives at the root of the repo and is the first thing Claude Code reads on every session. Most tutorials fill it with role-play ("You are an expert full-stack engineer with 20 years of experience"). Delete that. In my testing across ~200 prompts per repo, persona prompts consistently produced longer, more speculative output — Claude starts performing expertise instead of reading the code in front of it.
Here is the exact skeleton I use, minus proprietary bits:
# Project: invoicing-app
## Stack
- Python 3.11
- FastAPI
- Postgres 15
## Do not touch
- /migrations/**
- .env.production
- /locked/**
- alembic.ini
## Test command
pytest -x
## Deploy command
Deploy is manual. Do not attempt.
## Current sprint
- Fixing PDF renderer overflow on line items > 20
- Adding partial-payment status to invoice model
- No refactors this week
## Glossary
- VAT ID: tax registration number for a business
- e-invoice: XML doc submitted to the government portal
- credit note: negative invoice, refunds a prior one
Six sections. Usually 60–90 lines. Every section earns its place:
- Stack — three lines. No versions unless a version matters for a known incompatibility.
- Do not touch — the most important section. Explicit paths, glob patterns, one per line.
- Test command — the literal shell command. Claude will run it after edits if it's there, and skip testing if it isn't.
- Deploy command — one line, or the sentence "Deploy is manual. Do not attempt."
- Current sprint — the only section I update weekly. Stops Claude from proposing refactors unrelated to what I'm actually doing.
- Glossary — domain terms Claude will otherwise translate or misinterpret. For the invoicing product this is tax vocabulary. For the ops bot it's channel names and routing rules.
Claude respects the "do not touch" list maybe 80% of the time on prose alone. The other 20% is why file two exists.
File 2: .claude/settings.json — the actual fence
Inside the repo there's a hidden folder called .claude and inside it a settings.json. The permissions block is where you stop hoping and start enforcing. Here's a trimmed version of what runs in my invoicing repo:
{
"permissions": {
"allow": [
"Read(**)",
"Write(src/**)",
"Write(tests/**)",
"Bash(pytest*)",
"Bash(git status)",
"Bash(git diff*)",
"Bash(git add*)",
"Bash(git commit*)"
],
"deny": [
"Write(.env*)",
"Write(migrations/**)",
"Write(locked/**)",
"Bash(rm -rf*)",
"Bash(git push --force*)",
"Bash(*DATABASE_URL*)",
"Bash(psql*production*)",
"Bash(dropdb*)"
]
},
"mcpServers": {
"fs": { "command": "mcp-fs", "args": ["--root", "."] },
"pdf": { "command": "mcp-pdf-renderer" }
}
}
Two things to notice.
First, the deny list is boring on purpose. Every entry maps to a specific destructive operation I've either seen Claude attempt or that I don't want it attempting silently. When a denied command triggers, Claude stops and asks. That block has saved me from three destructive edits in the last two months — including one where Claude tried to drop and recreate a table during what should have been a read-only schema inspection.
Second, exactly two MCP servers per repo. One for the filesystem scoped to this repo. One for the single external tool this product needs — a PDF renderer for invoicing, a messaging API for the ops bot, a CRM client for lead-gen. Not fifteen. Every additional MCP is context loaded on startup and a surface area for weird behavior. The most common performance complaint I see ("Claude is slow, Claude is confused") tracks almost perfectly with people who installed 8–12 MCPs because a video told them to.
Quick sanity checks before you save settings.json
- Does every
denyentry map to a real command you've seen Claude try, or an obvious footgun (force push, rm -rf, prod DB URLs)? - Is
Writescoped to source dirs only, never**? - Are you under 3 MCP servers? If not, cut.
The folder rule: one repo per product, no monorepo
This is where I disagree hardest with popular Claude Code courses.
One repo per product. Never a monorepo. Never a nested "AIOS-style" meta-folder where all your businesses live under one directory.
The reason is context poisoning. When Claude Code opens a workspace, it indexes the tree. If your invoicing product and your lead-gen tool share a parent folder, Claude will pull patterns from one into the other. You'll ask for a fix in the invoicing repo and get a suggestion that references a variable name from the lead-gen codebase. It looks like Claude is being clever. It's not — it's confused, and it's silently costing you tokens.
My layout:
~/projects/
invoicing-app/ ← own git repo, own CLAUDE.md, own settings.json
ops-bot/ ← own git repo, own CLAUDE.md, own settings.json
leadgen-engine/ ← own git repo, own CLAUDE.md, own settings.json
Fresh terminal tab per repo. Two tabs open at a time, maximum. If I need a third, I close one. This isn't discipline theater — it's the difference between Claude answering from this project's context vs. mixing in whatever else is in scope.
What this actually saves you
I ran the same feature request ("add a partial-payment status field to invoices, update the model, migration, tests, and API response") against two setups on the same repo:
| Setup | Tokens used | Wall time | Files touched | Tests passing on first run |
|---|---|---|---|---|
| No CLAUDE.md, no settings.json permissions, 6 MCPs enabled | ~184k | 14 min | 11 (incl. 3 unrelated) | No — auth test broken |
| CLAUDE.md + settings.json + 2 MCPs (setup above) | ~41k | 6 min | 4 | Yes |
That's roughly 4.5x fewer tokens and less than half the wall time, for the same output quality. The bigger win isn't the tokens — it's the three unrelated files Claude didn't touch in run two. Every one of those in run one was a potential regression I'd have to review.
Over a month, across three repos, the difference between "constrained Claude" and "wide-open Claude" was roughly $180 in API costs and probably eight hours of code review I didn't have to do.
Common failure modes and the fix
A few patterns I see repeatedly when people ask why their Claude Code setup is misbehaving:
- "It keeps editing my migrations." Your
denyblock doesn't include the migrations path, or your CLAUDE.md "do not touch" list is vague ("db stuff") instead of a literal glob (/migrations/**). - "It rewrote my auth on a UI ticket." No "current sprint" section, no scoping in the prompt, and probably a persona prompt telling it to think holistically. Delete the persona. Add the sprint bullets.
- "Startup takes 40 seconds." Count your MCP servers. If it's more than three, that's your answer.
- "It suggests code that references a file that doesn't exist in this project." You're running from a parent folder that contains other projects. Move to a single-repo workspace.
- "It runs tests but ignores failures." Your test command in CLAUDE.md isn't the real one, or you don't have a test command at all and Claude is inventing one.
None of these need a subagent, a course, or a persona. They need the two files above, correctly filled in.
Why bizflowai.io helps with this
Most of the client automations I ship at bizflowai.io — invoicing pipelines, lead-gen engines, ops bots — are built and maintained inside exactly this setup: one repo per product, a tight CLAUDE.md, a locked-down settings.json, and two MCP servers max. When a client asks how we ship features fast without breaking production, the honest answer is that the fence around the AI is drawn before any code gets written. That's less impressive than a hype demo, and it's the reason things stay live.
Want more like this?
I publish practical AI automation, GenAI engineering, and faceless content workflows on YouTube every week.
Subscribe to bizflowai.io on YouTube — never miss a new tutorial.
Planning an AI automation project or need a second opinion on your architecture?
Connect with me on LinkedIn — Lazar Milicevic, GenAI Engineer & bizflowai.io Founder.
Visit bizflowai.io for our services, case studies, and AI consulting.
Frequently asked questions
What is the minimal Claude Code setup for a solo founder?
The minimal setup is two files and one rule. File one is CLAUDE.md at the repo root with six sections: stack, do-not-touch paths, test command, deploy command, current sprint, and glossary. File two is .claude/settings.json, which defines a permissions block denying destructive commands and limits enabled MCP servers to two. No AIOS folders, subagents, or persona prompts needed.
Why should you avoid persona prompts in CLAUDE.md?
Persona prompts like 'you are an expert full-stack engineer with twenty years of experience' measurably make Claude Code's output worse. Instead of reading your actual code, Claude starts performing expertise. Delete personas from CLAUDE.md and replace them with concrete facts: your stack, do-not-touch paths, test and deploy commands, current sprint tasks, and a domain glossary.
How do I stop Claude Code from running destructive commands?
Create a .claude/settings.json file inside your repo with an explicit permissions block. Deny write access to commands containing your production database URL, and block bash patterns like 'rm -rf', 'git push --force', and anything touching dotfiles. Allow read on everything, but restrict writes to source folders. When Claude hits a denied command, it stops and asks instead of executing.
How many MCP servers should you enable in Claude Code?
Enable exactly two MCP servers per repo: one for the file system of that specific repo, and one for the primary tool that repo needs (like a PDF renderer, messaging API, or CRM). Every additional MCP server is extra context loaded on startup and more surface area for unpredictable behavior. Fifteen MCPs is overkill; two is enough.
What belongs in the do-not-touch section of CLAUDE.md?
List exact file paths and folders Claude is not allowed to modify without you manually pasting them in. Typical entries include migration files, production environment configs, and anything under a locked folder like /locked. Claude respects this roughly eighty percent of the time on its own; the settings.json permissions block enforces the remaining twenty percent.