Duplication Hunt
What This Skill Does
Scans source code to find duplicated patterns that indicate extraction
opportunities. Goes beyond simple copy-paste detection to find three types of
duplication:
- Exact duplicates: Identical code blocks (3+ lines) appearing in two or
more locations.
- Renamed duplicates: Structurally identical code where only variable
names, string literals, or numeric constants differ.
- Structural duplicates: Code blocks that follow the same control flow
pattern (same sequence of operations, branches, and loops) with different
specifics — the "same shape, different nouns" pattern.
Ranks findings by occurrence count and block size to surface the highest-value
extraction candidates first.
When To Use
- On a weekly schedule as a codebase hygiene check.
- After a large feature merges to catch introduced duplication.
- When onboarding to a codebase to understand where abstractions are missing.
- When the user asks to "find duplicated code" or "hunt for duplication".
Do Not Use
- For method length — use
hone:method-brevity-audit instead.
- For naming quality — use
hone:intent-clarity-audit instead.
- For test naming — use
hone:test-naming-audit instead.
- For design-level duplication (repeated architectural patterns across
services). This skill operates at the code block level.
- To auto-extract or refactor duplicates. This skill reports findings only.
Inputs To Confirm
- Scope: Which directories or file patterns to scan (default: entire repo,
excluding vendored/generated code).
- Minimum block size: Smallest code block to consider, in lines (default:
4 lines).
- Minimum occurrences: How many times a pattern must appear to be reported
(default: 2 for exact, 3 for structural).
- Exclusions: Glob patterns for files or directories to skip.
- Top-N: Maximum findings to report (default: 15).
Instructions
Identify scannable files. Walk the repository tree. Exclude vendored
directories (node_modules, vendor, dist, build, .git,
__pycache__), generated files, lock files, and user-specified exclusions.
Include test files in the scan — test duplication is also worth finding.
Normalize source code. For each file, produce a normalized form by:
- Removing comments and blank lines.
- Collapsing whitespace and indentation differences.
- Preserving statement structure and control flow keywords.
This normalized form is used for comparison; original code is used for
reporting.
Detect exact duplicates. Slide a window of minimum_block_size to 50
lines across each normalized file. Hash each window. Group windows by hash.
When the same hash appears in 2+ locations (across files or within the same
file), record an exact duplicate finding. Merge overlapping windows into
the largest contiguous block.
Detect renamed duplicates. For blocks that are not exact matches,
replace all identifiers with a placeholder token and all literals with type
placeholders (<STR>, <NUM>, <BOOL>). Re-hash. Group by this
structural hash. Blocks that share a structural hash but differ in the
original are renamed duplicates.
Detect structural duplicates. Reduce each block to its control flow
skeleton: the sequence of keywords (if, else, for, while, return,
try, catch, switch, case, match, function calls as CALL) and
their nesting structure. Hash the skeleton. Group blocks with matching
skeletons that span at least 6 lines. This catches the "same logic,
different details" pattern.
Score and rank. For each finding, compute a value score:
score = occurrences * block_lines * type_weight
where type_weight is 3.0 for exact, 2.0 for renamed, 1.0 for structural.
Sort by score descending.
Suggest extraction targets. For the top findings, note:
- What a shared function/method might look like (parameters needed).
- Which files would benefit from the extraction.
- Whether the duplication is in production code, test code, or both.
Produce the report per Output Requirements.
Output Requirements
Produce a Markdown report:
# Duplication Hunt
**Repo**: <repo name>
**Scanned**: <N> files | **Duplicate groups found**: <count>
## Findings
### 1. <Brief description of the duplicated pattern>
- **Type**: Exact / Renamed / Structural
- **Occurrences**: N locations
- **Block size**: M lines
- **Score**: <value>
**Locations**:
| File | Lines | Preview |
|------|-------|---------|
| src/auth/login.ts | 24-38 | `const token = await fetch(...)` ... |
| src/auth/signup.ts | 31-45 | `const token = await fetch(...)` ... |
**Extraction suggestion**: Extract to a shared `authenticateUser(credentials)`
function in `src/auth/shared.ts`.
---
### 2. ...
## Summary
- **By type**: 5 exact, 3 renamed, 2 structural
- **Total duplicated lines**: ~320 lines across 10 groups
- **Highest-value extractions**: Group 1 (saves ~45 lines), Group 3 (saves ~30 lines)
- **Principle**: "Twice is a smell, three times is a pattern" — groups with 3+ occurrences are strong extraction candidates
Every finding must reference real file paths and line ranges. Previews must be
actual code snippets, not fabricated examples.
Quality Bar
- Every reported duplicate must be verifiable at the stated file:line ranges.
- Exact duplicates must be genuinely identical (modulo whitespace).
- Renamed duplicates must have the same structure when identifiers are replaced.
- Do not flag boilerplate that is intentionally repeated (e.g., license
headers, import blocks of 3 lines or fewer, trivial getters/setters).
- Do not flag configuration files, data fixtures, or migration files.
- Extraction suggestions must be concrete (name the function, list parameters)
and plausible (not every duplicate merits extraction — note when the
coupling cost may outweigh the deduplication benefit).
- If no duplication is found above the threshold, state that explicitly.
1---2name: hone-duplication-hunt3description: Finds duplicated code patterns across the codebase including exact copies and structural duplication (same logic with different variable names). Ranks by frequency and suggests extraction candidates. Designed for weekly runs. Do NOT use for method length, naming, or style concerns.4---56# Duplication Hunt78## What This Skill Does910Scans source code to find duplicated patterns that indicate extraction11opportunities. Goes beyond simple copy-paste detection to find three types of12duplication:13141. **Exact duplicates**: Identical code blocks (3+ lines) appearing in two or15 more locations.162. **Renamed duplicates**: Structurally identical code where only variable17 names, string literals, or numeric constants differ.183. **Structural duplicates**: Code blocks that follow the same control flow19 pattern (same sequence of operations, branches, and loops) with different20 specifics — the "same shape, different nouns" pattern.2122Ranks findings by occurrence count and block size to surface the highest-value23extraction candidates first.2425## When To Use2627- On a weekly schedule as a codebase hygiene check.28- After a large feature merges to catch introduced duplication.29- When onboarding to a codebase to understand where abstractions are missing.30- When the user asks to "find duplicated code" or "hunt for duplication".3132## Do Not Use3334- For method length — use `hone:method-brevity-audit` instead.35- For naming quality — use `hone:intent-clarity-audit` instead.36- For test naming — use `hone:test-naming-audit` instead.37- For design-level duplication (repeated architectural patterns across38 services). This skill operates at the code block level.39- To auto-extract or refactor duplicates. This skill reports findings only.4041## Inputs To Confirm42431. **Scope**: Which directories or file patterns to scan (default: entire repo,44 excluding vendored/generated code).452. **Minimum block size**: Smallest code block to consider, in lines (default:46 4 lines).473. **Minimum occurrences**: How many times a pattern must appear to be reported48 (default: 2 for exact, 3 for structural).494. **Exclusions**: Glob patterns for files or directories to skip.505. **Top-N**: Maximum findings to report (default: 15).5152## Instructions53541. **Identify scannable files.** Walk the repository tree. Exclude vendored55 directories (`node_modules`, `vendor`, `dist`, `build`, `.git`,56 `__pycache__`), generated files, lock files, and user-specified exclusions.57 Include test files in the scan — test duplication is also worth finding.58592. **Normalize source code.** For each file, produce a normalized form by:60 - Removing comments and blank lines.61 - Collapsing whitespace and indentation differences.62 - Preserving statement structure and control flow keywords.63 This normalized form is used for comparison; original code is used for64 reporting.65663. **Detect exact duplicates.** Slide a window of `minimum_block_size` to 5067 lines across each normalized file. Hash each window. Group windows by hash.68 When the same hash appears in 2+ locations (across files or within the same69 file), record an exact duplicate finding. Merge overlapping windows into70 the largest contiguous block.71724. **Detect renamed duplicates.** For blocks that are not exact matches,73 replace all identifiers with a placeholder token and all literals with type74 placeholders (`<STR>`, `<NUM>`, `<BOOL>`). Re-hash. Group by this75 structural hash. Blocks that share a structural hash but differ in the76 original are renamed duplicates.77785. **Detect structural duplicates.** Reduce each block to its control flow79 skeleton: the sequence of keywords (`if`, `else`, `for`, `while`, `return`,80 `try`, `catch`, `switch`, `case`, `match`, function calls as `CALL`) and81 their nesting structure. Hash the skeleton. Group blocks with matching82 skeletons that span at least 6 lines. This catches the "same logic,83 different details" pattern.84856. **Score and rank.** For each finding, compute a value score:86 `score = occurrences * block_lines * type_weight`87 where `type_weight` is 3.0 for exact, 2.0 for renamed, 1.0 for structural.88 Sort by score descending.89907. **Suggest extraction targets.** For the top findings, note:91 - What a shared function/method might look like (parameters needed).92 - Which files would benefit from the extraction.93 - Whether the duplication is in production code, test code, or both.94958. **Produce the report** per Output Requirements.9697## Output Requirements9899Produce a Markdown report:100101```markdown102# Duplication Hunt103104**Repo**: <repo name>105**Scanned**: <N> files | **Duplicate groups found**: <count>106107## Findings108109### 1. <Brief description of the duplicated pattern>110111- **Type**: Exact / Renamed / Structural112- **Occurrences**: N locations113- **Block size**: M lines114- **Score**: <value>115116**Locations**:117118| File | Lines | Preview |119|------|-------|---------|120| src/auth/login.ts | 24-38 | `const token = await fetch(...)` ... |121| src/auth/signup.ts | 31-45 | `const token = await fetch(...)` ... |122123**Extraction suggestion**: Extract to a shared `authenticateUser(credentials)`124function in `src/auth/shared.ts`.125126---127128### 2. ...129130## Summary131132- **By type**: 5 exact, 3 renamed, 2 structural133- **Total duplicated lines**: ~320 lines across 10 groups134- **Highest-value extractions**: Group 1 (saves ~45 lines), Group 3 (saves ~30 lines)135- **Principle**: "Twice is a smell, three times is a pattern" — groups with 3+ occurrences are strong extraction candidates136```137138Every finding must reference real file paths and line ranges. Previews must be139actual code snippets, not fabricated examples.140141## Quality Bar142143- Every reported duplicate must be verifiable at the stated file:line ranges.144- Exact duplicates must be genuinely identical (modulo whitespace).145- Renamed duplicates must have the same structure when identifiers are replaced.146- Do not flag boilerplate that is intentionally repeated (e.g., license147 headers, import blocks of 3 lines or fewer, trivial getters/setters).148- Do not flag configuration files, data fixtures, or migration files.149- Extraction suggestions must be concrete (name the function, list parameters)150 and plausible (not every duplicate merits extraction — note when the151 coupling cost may outweigh the deduplication benefit).152- If no duplication is found above the threshold, state that explicitly.