All posts
AI-assisted development
How to Make AI Write Clean Code Every Time
Triple Moon Goddess March 2026 8 min read
Most developers get mediocre code from AI. Here's why — and the system that fixes it.
Introducing clean-vibe
Your codebase has more violations than you think.
Triple Moon Goddess March 2026 5 min read
clean-vibe scans your entire GitHub repository for Clean Code violations using a two-pass AI analysis.
← All posts
AI-assisted development

How to Make AI Write Clean Code Every Time

Triple Moon Goddess March 2026 8 min read

Most developers get mediocre code from AI. Here's why — and the system that fixes it.

The problem nobody talks about

AI will write you working code almost instantly. It will also write you unmaintainable, inconsistent, security-naive code just as fast — and it will do so cheerfully, confidently, and without a word of warning.

The problem isn't that AI can't write clean code. It can. The problem is that it won't unless you build a system that makes it.

Here's what happens without a system: you start a session, describe what you want, get code that works. Next session, different conventions. Third session, the AI sees the patterns already in the codebase and mirrors them — including the bad ones. By month three, you have a codebase that looks like it was written by six different developers with six different opinions, because effectively it was.

"Without a mechanism to enforce standards across sessions, standards don't get enforced."

This isn't a criticism of AI. It's a description of how AI works. It has no persistent memory. It optimises for satisfying the current request. It defers to whatever it sees in context. The fix is a system.

Why AI code quality degrades over time

Three forces work against you:

amnesia
Context amnesia. Each session starts blank. The AI doesn't remember what it decided last time, what patterns you established, or what bugs you spent hours fixing.
mirroring
Pattern mirroring. The AI looks at your existing code and writes more of it. Good codebase: good new code. Inconsistent codebase: more inconsistency.
optimising
Request optimisation. The AI's job is to satisfy your immediate request. Cleanness, security, and maintainability are secondary unless you make them primary.

None of this is malicious. It's the default behaviour of a tool optimising for the wrong thing. The system below changes what it optimises for.

The methodology: four steps before you write code

01
Define the platform, not just the feature
Write down what each app does, who uses it, how parts share data, the auth model, what data is sensitive, and what the business model is. Every hour here saves ten hours of refactoring.
02
Write CLAUDE.md before any code
The instruction set every AI session reads first. Lives at the repo root. Contains structure rules, data rules, clean code rules, explicit prohibitions, and a commit checklist. This is the enforcement mechanism.
03
Scaffold the shared boundary first
Before app-specific code, create the shared package with schema constants, canonical types, one DB init, one API client. Enforce import rules in tsconfig. This is what makes a codebase pluggable.
04
Write the build plan as session instructions
Each session gets a prerequisite, a single goal, numbered steps, and concrete done-when criteria. The session plan is the memory the AI doesn't have.

The CLAUDE.md file

CLAUDE.md is the most important file in your repository. It lives at the repo root. Every AI session reads it before doing anything. It is how you get consistent behaviour from a tool that has no memory.

A good CLAUDE.md contains:

What the project is — one table, each module, who uses it, what it does. Two minutes to read, eliminates ten minutes of context-setting per session.

Import rules — where things live, and what is allowed to import from what. This is the rule that makes modularity actually work:

# The rule that makes plug-and-play possible
packages/shared/   ← imports from nowhere else
apps/client/       ← imports from shared only
apps/api/          ← imports from shared only

# Apps never import from each other. Ever.
# If app A needs something from app B, it belongs in shared.

The explicit prohibitions table — this is more effective than positive rules alone. A table that says "use any" in one column and "defeats the type system, define a proper type" in the next is harder to ignore than a style guide paragraph.

Before every commit checklist — a literal checklist the AI runs before finishing any task. Zero TypeScript errors. No hardcoded values. No empty catch blocks. No imports across app boundaries. This is the gate.

The clean code rules

These go verbatim into CLAUDE.md. They are not a style guide — they are enforced by the commit checklist.

Rule What it means in practice
Intention-revealing names If a comment is needed to explain a name, rename it. d is not a name. clientRecord is.
One responsibility If you can extract a meaningful sub-function, the original does more than one thing.
Max 3 parameters Beyond 3, group into a typed object. No boolean flag parameters — split into two functions.
Throw, don't return null Empty catch blocks are bugs. Fail loudly. A clear error is better than silent wrong behaviour.
Comments explain why Never what. If code needs a comment to explain what it does, rewrite the code.
No any in TypeScript Ever. Use unknown and narrow, or define the type.
Boy Scout Rule Leave every file cleaner than you found it.

The single test for any line of code

Read the code aloud. If it doesn't sound like clear prose describing what it does, it needs work.

What this actually changes

With this system in place, every AI session opens by reading CLAUDE.md. It knows the structure, the rules, the prohibited patterns. It knows what shared means and why apps don't import from each other. It knows that any is a blocker, that empty catch blocks are bugs, that sensitive data doesn't get hardcoded.

It still makes mistakes. You still need to review. But the mistakes are smaller, the patterns are consistent, and the codebase accumulates quality instead of debt.

The methodology is the memory the AI doesn't have. You build it once per project. It compounds across every session after that.

Getting started

Copy the template

Get the full CLAUDE.md template, clean code rules reference, and project setup checklist from the methodology guide.

Fill in your platform

Define what each app does, the auth model, data rules, and any domain-specific prohibitions before writing a line of code.

Scaffold shared first

Create packages/shared with schema.ts and types.ts. Enforce import rules in tsconfig. Do this before any app code.

Start every session right

"Read CLAUDE.md before you start." Four words. Run the commit checklist before finishing. That's the whole system.


Scan your codebase first.

See what violations are already there before setting up the system to prevent new ones.

← All posts
Introducing clean-vibe

Your codebase has more violations than you think.

Triple Moon Goddess March 2026 5 min read

clean-vibe is an AI-powered tool that traverses your entire GitHub repository, analyzes every source file against Robert C. Martin's Clean Code principles, and produces a detailed violation report — sorted by severity, filterable by file, downloadable as markdown.

Every codebase accumulates debt. Not the big architectural decisions — those get debated in PRs. The quiet stuff. The function that does three things. The variable named d. The catch block that swallows errors silently. The magic number buried in a conditional.

Martin's Clean Code has been the standard reference for over fifteen years. Most developers have read it — or at least know they should have. But reading the book and consistently applying its principles across a 50,000-line codebase are very different things.

clean-vibe closes that gap.

"Leave the code cleaner than you found it." — Robert C. Martin, Clean Code

How it works

Connect any GitHub repository — public or private — paste in your GitHub token and Anthropic API key, and clean-vibe fetches the full file tree. It estimates scan time per directory so you can run in batches rather than waiting for a monorepo to finish overnight.

Full repo traversal

Fetches every scannable file via GitHub API. Skips lockfiles, dist, maps, and generated code automatically.

Two-pass AI analysis

Haiku for fast full-coverage scanning. Sonnet for deep blocker analysis with root cause and refactored examples.

Session persistence

Results saved to localStorage after every file. Scan a directory today, another tomorrow, merge into one report.

Markdown export

Download the full report as a .md file at any point. Paste it into a PR, a ticket, or a team retrospective.

Three levels of severity

Not all violations are equal. A magic number in a config file is not the same as a catch block that silently swallows errors in a health data platform. clean-vibe sorts accordingly.

blocker
Must fix before merge. Dangerous, incorrect, or violates a hard rule. Will cause real bugs or silent failures in production.
warning
Should fix soon. Clear Clean Code violation that degrades maintainability, obscures intent, or makes the next developer's job harder.
suggestion
Worth considering. Naming or structural improvement. Small changes that compound over time into a significantly cleaner codebase.

What it actually finds

Here's a real example of what the tool surfaces. A function that looks fine at a glance:

✗ before
async function proc(d, t) {
  // process the data
  if (d && t === true) {
    try {
      await save(d);
    } catch(e) {
      console.error(e);
    }
  } else {
    return -1;
  }
}
✓ after
async function saveIfActive(
  record: Record,
  isActive: boolean
): Promise<void> {
  if (!isActive) return;
  try {
    await saveRecord(record);
  } catch (error) {
    showError('Could not save record.');
    throw error;
  }
}

The violations: cryptic parameter names (d, t), a flag argument, a silent catch, an error code return, and a comment describing what the code already says. Five violations in eight lines — none of them obvious without a systematic review.

The two-pass model

Speed matters when you're scanning hundreds of files. clean-vibe uses Claude Haiku for the first pass — fast, cheap, covering every file. The cost for a 200-file repo is roughly $0.15.

After the Haiku pass, any file with blocker-level violations gets a second pass with Claude Sonnet. Sonnet does what Haiku can't: root cause analysis, code smell categorization from Martin's taxonomy, and a concrete refactored example showing the correct approach. This is where the report goes from a list of complaints to an actionable improvement plan.

Zero dependencies. Zero build step.

clean-vibe is a single index.html file. No npm install, no webpack, no server. Open it locally or serve it from any static host. Your API keys stay in your browser — they never pass through any server except Anthropic's and GitHub's directly.

# Clone and open — that's it
git clone https://github.com/Triple-Moon-Goddess/clean-vibe.git
open clean-vibe/index.html

Free for non-commercial use

If you're using clean-vibe for personal projects, learning, or open source work — it's free, forever, no account required. Bring your own Anthropic API key and GitHub token.

Commercial use — at a company, in client work, or as part of a product — requires a license. Three tiers: Individual ($100/year), Team up to 10 developers ($500/year), and Organization unlimited seats ($1,500/year).


Try it on your codebase.

Free for non-commercial use. Your API keys never leave your browser.