
Code Clone Assistant
- 127 installs
- 62 repo stars
- Updated August 3, 2026
- terrylica/cc-skills
Use code-clone-assistant for development tasks
About
code-clone-assistant: A skill for development. This provides functionality for development workflows.
- code-clone-assistant
Code Clone Assistant by the numbers
- 127 all-time installs (skills.sh)
- +1 installs in the week ending Jul 27, 2026 (Skillselion tracking)
- Ranked #2,750 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/terrylica/cc-skills --skill code-clone-assistantAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 127 |
|---|---|
| repo stars | ★ 62 |
| Last updated | August 3, 2026 |
| Repository | terrylica/cc-skills ↗ |
What it does
Use code-clone-assistant for development tasks
Files
Code Clone Assistant
Detect code clones and guide refactoring using PMD CPD (exact duplicates) + Semgrep (patterns).
Self-Evolving Skill: This skill improves through use. If instructions are wrong, parameters drifted, or a workaround was needed — fix this file immediately, don't defer. Only update for real, reproducible issues.
Tools
- PMD CPD v7.17.0+: Exact duplicate detection
- Semgrep v1.140.0+: Pattern-based detection
Tested: October 2025 - 30 violations detected across 3 sample files Coverage: ~3x more violations than using either tool alone
---
When to Use This Skill
Use this skill when:
- Finding duplicate code in a codebase
- Detecting DRY violations
- Refactoring similar code patterns
- Identifying copy-paste code
---
Why Two Tools?
PMD CPD and Semgrep detect different clone types:
| Aspect | PMD CPD | Semgrep |
|---|---|---|
| Detects | Exact copy-paste duplicates | Similar patterns with variations |
| Scope | Across files ✅ | Within/across files (Pro only) |
| Matching | Token-based (ignores formatting) | Pattern-based (AST matching) |
| Rules | ❌ No custom rules | ✅ Custom rules |
Result: Using both finds ~3x more DRY violations.
Clone Types
| Type | Description | PMD CPD | Semgrep |
|---|---|---|---|
| Type-1 | Exact copies | ✅ Default | ✅ |
| Type-2 | Renamed identifiers | ✅ --ignore-* | ✅ |
| Type-3 | Near-miss with variations | ⚠️ Partial | ✅ Patterns |
| Type-4 | Semantic clones (same behavior) | ❌ | ❌ |
---
Quick Start Workflow
# Step 1: Detect exact duplicates (PMD CPD)
pmd cpd -d . -l python --minimum-tokens 20 -f markdown > pmd-results.md
# Step 2: Detect pattern violations (Semgrep)
semgrep --config=clone-rules.yaml --sarif --quiet > semgrep-results.sarif
# Step 3: Analyze combined results (Claude Code)
# Parse both outputs, prioritize by severity
# Step 4: Refactor (Claude Code with user approval)
# Extract shared functions, consolidate patterns, verify tests---
---
Accepted Exceptions (Known Intentional Duplication)
Not all code duplication is a problem. Some codebases deliberately use copy-and-adapt patterns where refactoring would be harmful. When running clone detection, always check for accepted exceptions before recommending refactoring.
When Duplication Is Acceptable
| Pattern | Why Acceptable | Example |
|---|---|---|
| Generation-per-directory experiments | Each generation is an immutable, self-contained experiment. Sharing code across generations would break provenance and make past experiments non-reproducible. | SQL templates, sweep scripts where each gen{NNN}/ is independent |
| SQL templates with placeholder substitution | SQL has no import/include mechanism. Templates use sed placeholder replacement (__PLACEHOLDER__), not function calls. Extracting shared CTEs into separate files would break the single-file execution model. | ClickHouse sweep templates sharing signal detection + metrics CTEs |
| Protocol/schema boilerplate | Serialization formats, API contracts, and wire protocols require exact structure in each location. Abstracting them hides the contract. | NDJSON telemetry line construction in wrapper scripts |
| Test fixtures and golden files | Test data intentionally duplicates production patterns to verify behavior. Sharing fixtures creates brittle cross-test dependencies. | Test setup code, expected output snapshots |
How to Report Accepted Exceptions
When clone detection finds duplication that matches an accepted exception pattern:
1. Report it — always show the user what was found (lines, tokens, files) 2. Flag as accepted — explicitly state it matches a known exception pattern 3. Explain why — cite the specific reason refactoring is not recommended 4. Do NOT recommend refactoring — this is the key difference from actionable findings
Example output format:
Code Clone Analysis Results
PMD CPD Findings:
Clone 1: 115 lines (575 tokens) — base_bars → signals CTEs
gen610_template.sql:33 ↔ gen710_template.sql:38
Status: ACCEPTED EXCEPTION (generation-per-directory experiment)
Reason: Each generation is immutable. Shared CTEs would break
experiment provenance and reproducibility.
Clone 2: 36 lines (478 tokens) — metrics aggregation
gen610_template.sql:207 ↔ gen710_template.sql:244
Status: ACCEPTED EXCEPTION (SQL template without include mechanism)
Actionable Findings: 0
Accepted Exceptions: 2Project-Level Exception Configuration
Projects can declare accepted exception patterns in their CLAUDE.md:
## Code Clone Exceptions
- `sql/gen*_template.sql` — generation-per-directory experiments (immutable)
- `scripts/gen*/` — copy-and-adapt sweep scripts (no shared infrastructure)
- `tests/fixtures/` — intentional duplication for test isolationWhen this section exists in a project's CLAUDE.md, the code-clone-assistant should check it before classifying findings.
---
Reference Documentation
For detailed information, see:
- Detection Commands - PMD CPD and Semgrep command details
- Complete Workflow - Detection, analysis, and presentation phases
- Refactoring Strategies - Approaches for addressing violations
---
Troubleshooting
| Issue | Cause | Solution |
|---|---|---|
| PMD CPD not found | Not installed or not in PATH | brew install pmd or download from PMD releases |
| Semgrep timeout | Large codebase scan | Use --exclude to limit scope |
| No duplicates detected | minimum-tokens too high | Lower --minimum-tokens value (try 15) |
| Too many false positives | minimum-tokens too low | Increase --minimum-tokens (try 30+) |
| Language not recognized | Wrong -l flag | Check PMD CPD supported languages list |
| SARIF parse error | Semgrep output malformed | Upgrade Semgrep to latest version |
| Memory error on large repo | Java heap too small | Set PMD_JAVA_OPTS=-Xmx4g |
| Missing clone rules file | Custom rules not created | Create clone-rules.yaml or use default config |
Post-Execution Reflection
After this skill completes, check before closing:
1. Did the command succeed? — If not, fix the instruction or error table that caused the failure. 2. Did parameters or output change? — If the underlying tool's interface drifted, update Usage examples and Parameters table to match. 3. Was a workaround needed? — If you had to improvise (different flags, extra steps), update this SKILL.md so the next invocation doesn't need the same workaround.
Only update if the issue is real and reproducible — not speculative.
rules:
# BASELINE RULES (Original)
- id: duplicate-validation-pattern
pattern-either:
- pattern: |
if not $VAR or len($VAR) < $N:
raise ValueError(...)
- pattern: |
if not $VAR or '@' not in $VAR:
raise ValueError(...)
- pattern: |
if $VAR < 0:
raise ValueError(...)
message: Duplicate validation logic detected - consider extracting to shared function
languages: [python]
severity: WARNING
metadata:
category: maintainability
subcategory: code-duplication
- id: duplicate-error-collection-pattern
pattern: |
errors = []
...
if $COND1 not in $DATA:
errors.append(...)
...
if $COND2 not in $DATA:
errors.append(...)
message: Duplicate error collection pattern - consider extracting validator
languages: [python]
severity: WARNING
metadata:
category: maintainability
subcategory: code-duplication
note: Use PMD CPD --exclude flag to exclude test files where duplication is acceptable
- id: js-duplicate-validation
pattern-either:
- pattern: |
if (!$VAR || $VAR.length < $N) {
throw new Error(...);
}
- pattern: |
if (!$VAR || !$VAR.includes('@')) {
throw new Error(...);
}
- pattern: |
if ($VAR < 0) {
throw new Error(...);
}
message: Duplicate validation logic - consider extracting to shared function
languages: [javascript, typescript]
severity: WARNING
metadata:
category: maintainability
subcategory: code-duplication
# ADVANCED RULES (Using metavariable features)
- id: duplicate-validation-threshold
patterns:
- pattern-either:
- pattern: |
if not $VAR or len($VAR) < $N:
raise ValueError(...)
- pattern: |
if len($VAR) < $N:
raise ValueError(...)
- metavariable-comparison:
metavariable: $N
comparison: $N > 0 and $N < 10
message: Duplicate validation with threshold $N - extract to constant or validator
languages: [python]
severity: WARNING
metadata:
category: maintainability
subcategory: code-duplication
feature: metavariable-comparison
- id: common-field-duplication
patterns:
- pattern: |
if not $VAR or len($VAR) < $N:
raise ValueError(...)
- metavariable-regex:
metavariable: $VAR
regex: "^(name|username|email|password|title)$"
message: Duplicate validation for common field '$VAR' - extract to shared validators
languages: [python]
severity: WARNING
metadata:
category: maintainability
subcategory: code-duplication
feature: metavariable-regex
- id: nested-field-validation
patterns:
- pattern: |
if not $OBJ.get($KEY) or $COND:
raise ValueError(...)
- metavariable-pattern:
metavariable: $KEY
patterns:
- pattern: "'email'"
message: Duplicate nested email validation - extract to validator
languages: [python]
severity: WARNING
metadata:
category: maintainability
subcategory: code-duplication
feature: metavariable-pattern
- id: function-level-duplication
patterns:
- pattern-inside: |
def $FUNC($...ARGS):
...
- pattern: |
errors = []
...
if $COND1 not in $DATA:
errors.append(...)
...
if $COND2 not in $DATA:
errors.append(...)
message: Duplicate error collection in function $FUNC - extract to validator class
languages: [python]
severity: WARNING
metadata:
category: maintainability
subcategory: code-duplication
feature: pattern-inside
- id: highlight-duplicate-values
patterns:
- pattern: |
errors.append($MSG)
- focus-metavariable: $MSG
message: Repeated error message pattern - consolidate error handling
languages: [python]
severity: INFO
metadata:
category: maintainability
subcategory: code-duplication
feature: focus-metavariable
- id: duplicate-function-signatures
patterns:
- pattern: |
def $FUNC($ARG):
if not $ARG or len($ARG) < $N:
raise ValueError(...)
...
- metavariable-regex:
metavariable: $FUNC
regex: "^(validate|check|verify)_(name|email|username|password)$"
message: Similar validation function '$FUNC' - consolidate to single validator
languages: [python]
severity: INFO
metadata:
category: maintainability
subcategory: code-duplication
feature: metavariable-regex
note: Reduced noise by targeting specific common validator names
- id: js-duplicate-async-validation
pattern-either:
- pattern: |
async function $FUNC($ARG) {
if (!$ARG || $ARG.length < $N) {
throw new Error(...);
}
...
}
- pattern: |
const $FUNC = async ($ARG) => {
if (!$ARG || $ARG.length < $N) {
throw new Error(...);
}
...
}
message: Duplicate async validation pattern - extract to shared async validator
languages: [javascript, typescript]
severity: WARNING
metadata:
category: maintainability
subcategory: code-duplication
feature: async-patterns
- id: ts-duplicate-type-guards
patterns:
- pattern: |
function is$TYPE($VAR: any): $VAR is $TYPE {
return $VAR !== null && typeof $VAR.$FIELD === '$FIELDTYPE';
}
- metavariable-regex:
metavariable: $TYPE
regex: "^(String|Number|Object|Array|Valid)"
message: Duplicate TypeScript type guard for '$TYPE' - consolidate to generic type guard
languages: [typescript]
severity: INFO
metadata:
category: maintainability
subcategory: code-duplication
feature: typescript-specific
Skill: Code Clone Assistant
Complete Detection Workflow
Phase 1: Detection
/usr/bin/env bash << 'CONFIG_EOF'
# Create working directory
mkdir -p /tmp/dry-audit-$(date +%Y%m%d)
cd /tmp/dry-audit-$(date +%Y%m%d)
# Run both tools
pmd cpd -d /path/to/project -l python --minimum-tokens 20 -f markdown > pmd-cpd.md
semgrep --config=/path/to/clone-rules.yaml --sarif --quiet /path/to/project > semgrep.sarif
CONFIG_EOFPhase 2: Analysis
# Parse PMD CPD (direct read - LLM-native format)
cat pmd-cpd.md
# Parse Semgrep SARIF
jq -r '.runs[0].results[] | "\(.ruleId): \(.message.text) at \(.locations[0].physicalLocation.artifactLocation.uri):\(.locations[0].physicalLocation.region.startLine)"' semgrep.sarifCombine findings:
1. List PMD CPD duplications by severity (tokens/lines) 1. List Semgrep violations by file 1. Check for accepted exceptions — read the project's CLAUDE.md for a "Code Clone Exceptions" section. Also check if the duplication matches any known acceptable pattern (see Accepted Exceptions) 1. Classify each finding as actionable or accepted exception 1. Prioritize actionable findings: Exact duplicates across files > Large within-file > Patterns
Phase 3: Presentation
Present to user:
- Total findings (PMD + Semgrep)
- Breakdown: actionable vs accepted exceptions
- For actionable: files affected, estimated effort, suggested approach
- For accepted: which exception pattern applies and why refactoring is not recommended
Example (with accepted exceptions):
Code Clone Analysis Results
===========================
PMD CPD: 5 duplications found
Actionable: 2
Accepted exceptions: 3
Accepted Exceptions:
1. 115 lines — base_bars → signals CTEs (gen610 ↔ gen710)
Exception: generation-per-directory experiment (immutable provenance)
2. 36 lines — metrics aggregation SELECT (gen610 ↔ gen710)
Exception: SQL template without include mechanism
3. 20 lines — trade_outcomes exit logic (gen610 ↔ gen710)
Exception: generation-per-directory experiment (immutable provenance)
Actionable Findings:
1. process_user_data() duplicated in file1.py:5 and file2.py:5 (21 lines)
2. Duplicate validation logic across 6 locations (Semgrep)
Recommended Refactoring:
- Extract process_user_data() to shared utils module
- Create validate_input() function for validation logic
Proceed with refactoring? (y/n)Phase 4: Refactoring (With User Approval)
1. Read affected files using Read tool 1. Create shared functions/classes 1. Replace duplicates using Edit tool 1. Run tests using Bash tool 1. Commit changes if tests pass
---
Best Practices
DO:
- ✅ Run both PMD CPD and Semgrep (complementary coverage)
- ✅ Check for accepted exceptions before recommending refactoring
- ✅ Read the project's
CLAUDE.mdfor exception declarations - ✅ Start with conservative thresholds (PMD: 50 tokens)
- ✅ Review results before refactoring
- ✅ Run full test suite after refactoring
- ✅ Commit incrementally
DON'T:
- ❌ Only use one tool (miss ~70% of violations)
- ❌ Set thresholds too low (noise overwhelms signal)
- ❌ Refactor without understanding context
- ❌ Recommend refactoring for accepted exceptions (intentional duplication)
- ❌ Skip test verification
Skill: Code Clone Assistant
Detection Commands
PMD CPD (Exact Duplicates)
# Markdown format (optimal for AI processing)
pmd cpd -d . -l python --minimum-tokens 20 -f markdown
# Multi-language projects (run separately per language)
pmd cpd -d . -l python --minimum-tokens 20 -f markdown > pmd-python.md
pmd cpd -d . -l ecmascript --minimum-tokens 20 -f markdown > pmd-js.mdTuning thresholds:
- New codebases: 30-50 tokens
- Legacy codebases: 75-100 tokens (start high, lower gradually)
Exclusions:
pmd cpd -d . -l python --minimum-tokens 20 \
--exclude="**/tests/**,**/node_modules/**,**/__pycache__/**" \
-f markdownSemgrep (Pattern Violations)
# SARIF format (CI/CD standard)
semgrep --config=clone-rules.yaml --sarif --quiet
# Text format (human-readable)
semgrep --config=clone-rules.yaml --quiet
# Parse SARIF with jq
semgrep --config=clone-rules.yaml --sarif --quiet | \
jq -r '.runs[0].results[] | "\(.ruleId): \(.message.text)"'Full rules file: ./clone-rules.yaml
______________________________________________________________________
Evolution Log
Convention: Reverse chronological order (newest on top, oldest at bottom). Prepend new entries.
---
2026-02-26: Initial Evolution Log
Status: Skill is in use and maintained. Track improvements here.
Purpose
This evolution log tracks updates to the skill. Each entry should note:
- What changed (content, structure, tooling)
- Why it changed (bug fix, feature request, best practice)
- Files affected
How to Use
1. When updating SKILL.md or references, add an entry here with the date 2. Keep entries reverse-chronological (newest first) 3. Link to ADRs or GitHub issues when relevant 4. Reference specific line changes when helpful
---
Skill: Code Clone Assistant
______________________________________________________________________
Security
Allowed Tools: Read, Grep, Bash, Edit, Write
Safe Refactoring:
- Only refactor after user approval
- Run tests before marking complete
- Never use destructive commands
- Preserve git history
- Validate file paths before editing
______________________________________________________________________
Detailed Documentation
For comprehensive details, see:
- PMD CPD Reference:
reference-pmd.md- Commands, options, exclusions, error handling - Semgrep Reference:
reference-semgrep.md- Rules, patterns, advanced features - Examples:
examples.md- Real-world examples, complementary detection scenarios - Sample Rules:
clone-rules.yaml- Ready-to-use Semgrep patterns
______________________________________________________________________
Installation
# Check installation
which pmd # Should be /opt/homebrew/bin/pmd
which semgrep # Should be /opt/homebrew/bin/semgrep
# Install if missing
brew install pmd # PMD v7.17.0+
brew install semgrep # Semgrep v1.140.0+______________________________________________________________________
Testing Results
Test Date: October 26, 2025 Files Tested: 3 files (sample1.py, sample2.py, sample.js)
Results:
- PMD CPD: 9 exact duplications
- Semgrep: 21 pattern violations
- Total Unique: ~27 DRY violations
- Coverage: 3x more than either tool alone
______________________________________________________________________
This skill uses only tested commands validated in October 2025 with PMD CPD and Semgrep