---
name: Codebase Hygiene
slug: codebase-hygiene
category: Quality
description: Codebase Hygiene finds semantic duplicates and shallow modules that spread complexity across a codebase. It is read-only and advisory, used before routing any real changes through BUILD with full gates.
github: "https://github.com/romiluz13/cc10x/tree/main/plugins/cc10x/skills/codebase-hygiene"
language: Python
stars: 164
forks: 25
install: "npx degit https://github.com/romiluz13/cc10x/tree/main/plugins/cc10x/skills/codebase-hygiene ~/.claude/skills/codebase-hygiene"
installs_to: ~/.claude/skills/codebase-hygiene
source_path: plugins/cc10x/skills/codebase-hygiene/SKILL.md
collection_size: 21
category_size: 1897
collection_url: "https://dirskills.com/collections/romiluz13/cc10x"
added: 2026-09-08T05:35:32.824Z
last_synced: 2026-09-08T05:35:32.824Z
canonical_url: "https://dirskills.com/skills/codebase-hygiene"
---

# Codebase Hygiene

Codebase Hygiene finds semantic duplicates and shallow modules that spread complexity across a codebase. It is read-only and advisory, used before routing any real changes through BUILD with full gates.

**Install:**

```bash
npx degit https://github.com/romiluz13/cc10x/tree/main/plugins/cc10x/skills/codebase-hygiene ~/.claude/skills/codebase-hygiene
```

## README

# Codebase Hygiene (Duplicate Detection + Module Deepening)

Advisory and read-heavy. Diagnoses and proposes; does not refactor. Any actual change goes through BUILD with full gates.

## Mode: DUPLICATE DETECTION

Semantic duplicates: functions serving the same purpose but implemented independently under different names. Copy-paste detectors catch syntactic duplicates; this finds "same intent, different implementation."

### Method

0. **Scope before you scan** — take the user's named target; else `git log --oneline` for hot spots and weight recently-changed code — deepening pays off in proportion to future change.
1. **Extract catalog** — Grep/Glob for exported functions. Record `name | file:line | signature`.
2. **Categorize by domain** (cheap tier) — validation, formatting, path manipulation, HTTP shaping, date handling. Mechanical bucketing to shrink comparison space.
3. **Drop categories with <3 functions** — can't hide a meaningful duplication pattern.
4. **Detect duplicates per category** (capable tier) — read implementations, decide which share intent. **Never use cheap tier for detection** — it anchors on names and rubber-stamps "these look different."
5. **Emit findings** — group by confidence, highest first. Each finding: what is duplicated, why it matters, the fix, `file:line` evidence. Route through code-reviewer finding contract.

### High-Risk Zones

| Zone | Why it duplicates |
| ------ | ------------------- |
| `utils/`, `helpers/`, `lib/` | Catch-all dumping grounds |
| Validation code | "Is this a valid email/id/url" rewritten per feature |
| Error formatting | Every module invents its own Error → string |
| Path manipulation | Join/normalize/relativize reimplemented |
| String formatting | Truncate, slugify, titlecase, pad re-rolled |
| Date formatting | Parse/format/diff scattered |
| API response shaping | Envelope/pagination/error-body copied per endpoint |

### Consolidation Discipline

Never delete a duplicate until all three hold:

1. **Survivor has tests** — pick the implementation with real coverage. If neither has tests, write the test against the chosen survivor first.
2. **All callers updated** — Grep to enumerate callers. Missing one is a silent break.
3. **Re-run after consolidation** — test suite + build/typecheck pass. Green tests on the survivor license the deletion.

---

## Mode: MODULE DEEPENING

Existing code works; the problem is **shape**, not features. LLM-grown codebases accrete shallow modules — thin wrappers, pass-through layers, near-duplicate helpers. Each looks harmless; together they spread complexity across every caller.

**Deep module:** hides a lot of behavior behind a small interface.
**Shallow module:** interface is almost as complex as its implementation — callers learn a thing without getting much.

### The Deletion Test

For each candidate: **If I deleted this module and inlined its code at every call site, where does the complexity go?**

- Complexity **vanishes** → the module was a pass-through / shallow. It adds indirection without hiding complexity. Deepening candidate (delete it or deepen its interface).
- Complexity **reappears across N call sites** → the module is deep. It earns its existence by hiding complexity that would otherwise be duplicated. Leave it alone.

This verdict agrees with `cc10x:codebase-design` (canonical) and `cc10x:architecture`. Depth is leverage at the interface — not a lines-ratio.

| Smell | Usually |
| ------- | --------- |
| Thin wrapper (`doX(a){ return lib.doX(a) }`) | Shallow |
| Pass-through layer (service maps 1:1 to repo) | Shallow |
| Near-duplicate helper (same intent, different name) | Shallow — consolidate first |
| Config/leverage module (small interface, branching/retry/state inside) | Deep — keep |

### Diagnosis Flow (READ-ONLY)

1. Enumerate exported surface (`name | file:line | signature`)
2. Flag shallow shapes
3. Cross-reference near-duplicates (run duplicate detection mode first — consolidate before deepening)
4. Run deletion test on each survivor
5. Output: candidate list, not a refactor

### Present Candidates Before Proposing Interfaces

Badge each candidate: **Strong** (unambiguous), **Worth-exploring** (real cost/risk), **Speculative** (hunch, low confidence).

For each: before/after sketch (current shallow interface vs proposed deeper one) with deletion test result. Then stop and ask which to pursue. Do not design interfaces for candidates the user hasn't chosen.

### Two-Adapters Rule for Seam Placement

When designing the deeper interface, a **port** (an injected external dependency seam) needs two concrete **adapters** — e.g. a production transport and a test stand-in. An ordinary caller or a test exercising a public interface is NOT an adapter; the two-adapter rule is about ports, not every seam.

For a non-port seam (the common case for module deepening): the test must be able to reach the interface. If only production code crosses the seam and no test can reach it → the seam is a guess. Put the interface where a test can reach it, or don't introduce it. This aligns with `cc10x:codebase-design` — "one adapter means a hypothetical seam" applies to ports; internal seams need reachability, not a second adapter.

### Handoff to BUILD

This skill ends at: chosen candidate + deeper-interface proposal + named seam. It does NOT edit code. The refactor routes through planner → BUILD workflow (builder → reviewer → verifier → doc-sync → memory). The deepening is verified: survivor interface has tests at its seam, every caller is repointed, suite + typecheck pass after merge.

Proposing is read-only; changing is gated.
