DEV Community

Mehmet TURAÇ
Mehmet TURAÇ

Posted on

I Built a Claude Code Skill That Reads Your Codebase's DNA in 20 Files

Every team has a senior developer who, during code review, writes comments like:
"We never use axios directly here — go through the apiClient wrapper."
"All errors need the AppError class, never throw raw strings."
"Files are kebab-case in this project, not camelCase."

None of these rules are in a linter. None are in a README. They live in one person's head.
When that person leaves — or when an AI assistant writes code — they get violated constantly.

I built a Claude Code skill that finds these rules automatically, writes them to a machine-readable profile, and enforces them every time Claude generates new code. I called it Codebase DNA Guardian.

Here's how it works, what I learned building it, and a real scan on a 1,388-file production codebase.

The core idea: surgical sampling, not full reads

Reading an entire codebase is wasteful and slow. A 500-file TypeScript project would blow through any context window before you extracted a single pattern.

The insight: you don't need all 500 files. You need:

  1. Config files (3–5): tsconfig.json, .eslintrc, pyproject.toml — these tell you the rules the team agreed on
  2. Entry points (2–3): main.ts, app.ts — bootstrap patterns, global state setup
  3. One vertical slice (4–6 files): pick the most "average" feature and read route → service → repository → test. This single slice reveals more about a project's conventions than 50 random files.
  4. Error handling samples (2–3): grep for catch, throw, AppError
  5. Tests (2–3): framework, mocking strategy, file naming

15–20 files total. Enough to extract reliable patterns across 8 categories.

What the scan produces

After running /dna-scan on a project, the skill writes .claude/dna.md:

| ID | Tier | Rule | Example | Counter-example |
|----|------|------|---------|---------------|
| A1 | 🔴 HARD | Frontend HTTP via frappe-ui createResource — no raw fetch/axios | `createResource({ url: 'hrms.api...' })` | `axios.get(...)` |
| E1 | 🔴 HARD | Python: frappe.throw() + _() i18n on all user errors | `frappe.throw(_("Invalid date"))` | `raise Exception("Invalid date")` |
| D4 | 🟢 PREF | Date handling: dayjs (frontend) / frappe.utils.getdate (Python) | `dayjs()` | `moment()` |
Enter fullscreen mode Exit fullscreen mode

Every rule has a severity tier:

Tier What Claude does
🔴 HARD Stops. Explains the rule. Asks you to confirm before proceeding.
🟡 SOFT Writes compliant code, adds a one-line footnote.
🟢 PREF Silently applies it. You never see it.

Once .claude/dna.md exists, Claude reads it before every code generation — no extra commands needed. The DNA is always active.

Real scan: frappe/hrms (1,388 files, 18 sampled)

I ran it on frappe/hrms, an open-source HR & payroll system. Python backend + Vue 3 PWA frontend + TypeScript roster service — three languages, three frameworks, one monorepo.

18 files sampled. 19 rules extracted. Scan time: under 3 minutes.

Results:

Consistency Score: 90/100

🔴 HARD rules: 10 — all passing ✅
   ✅ A1  frappe-ui createResource — no raw fetch/axios found
   ✅ D2  Ionic Vue (IonPage/IonContent) on all views
   ✅ E1  frappe.throw() + _() on all Python errors
   ✅ T1  IntegrationTestCase — frappe.tests used correctly

🟡 SOFT drift: 1
   ⚠️  E3  frontend/src/components/FormView.vue:536,563
           console.log() on error paths — should be console.error()

🧟 Zombie dependency:
   ⚠️  html2canvas@^1.4.1 — declared in package.json, zero imports found
Enter fullscreen mode Exit fullscreen mode

The zombie dependency alone is worth the scan. html2canvas is 0.8 MB. It ships to every user. Nobody imports it.

The dashboard

The project includes a React dashboard that renders the scan results visually — animated score ring, per-service consistency bars, zombie tracker, evolution sparkline.

DNA Guardian Services Tab

DNA Guardian Rules Tab

It's driven by a DNA_DATA object your scan populates. Run /dna-preview inside Claude Code and it bundles, serves, and screenshots it automatically.

Monorepo support

For multi-service projects, the scan runs in waves:

Wave 1: root — shared config, CI, shared utilities
Wave 2: per-service — one vertical slice each
Wave 3: cross-comparison — diff patterns across services
Wave 4: classify — intentional divergence vs accidental drift
Enter fullscreen mode Exit fullscreen mode

Output goes to .claude/dna/root.md + per-service overrides. Resolution order: service DNA > root DNA. If aegis.md says "use JOSE" but root.md says "use jsonwebtoken", Aegis wins for code inside that service.

What I found wrong in my own skill

Before publishing I ran a rigorous code review — 7 independent reviewer angles, 11 confirmed bugs. The most instructive ones:

Shell operator precedence:

# WRONG — -maxdepth 2 only applies to the first -name clause
find . -maxdepth 2 -type f -name "*.json" -o -name "*.toml" -o -name "*.yaml"

# CORRECT
find . -maxdepth 2 -type f \( -name "*.json" -o -name "*.toml" -o -name "*.yaml" \)
Enter fullscreen mode Exit fullscreen mode

Without the parens, -o breaks the -maxdepth 2 constraint for .toml and .yaml. In any real project this recurses into node_modules/ and returns thousands of files.

GNU grep alternation:

# WRONG on Linux (BRE mode — matches the literal string "catch|Error|throw")
grep -rl "catch\|Error\|throw" src/

# CORRECT — use ERE mode
grep -Erl "catch|Error|throw" src/
Enter fullscreen mode Exit fullscreen mode

Two-dot vs three-dot git diff:

# WRONG — includes commits on main that aren't in the branch
git diff main..feature/my-branch --name-only

# CORRECT — compares against merge-base
git diff main...feature/my-branch --name-only
Enter fullscreen mode Exit fullscreen mode

Finding three shell-level bugs in a skill that's entirely instructions (no executable code) was a reminder: AI agent instructions are code. They have the same failure modes as programs.

Install

npx skills add mturac/codebase-dna-guardian
Enter fullscreen mode Exit fullscreen mode

Or via npm:

npm install -g codebase-dna-guardian
Enter fullscreen mode Exit fullscreen mode

GitHub → mturac/codebase-dna-guardian

The skill is MIT licensed, includes AGENTS.md for Cursor/Copilot/Windsurf compatibility, and ships with the React dashboard component.


The thing I keep coming back to: every codebase has a senior developer embedded in it — in the file history, in the naming patterns, in the error handling strategies. This skill just reads it.

Top comments (0)