AgentSkillsCN

quickdup

查找并减少代码重复,清理冗余代码,检测代码克隆,缩小代码库规模,避免 DRY 违规,识别复制粘贴代码。适用于用户询问重复代码、代码清理、缩减代码规模、DRY 原则,或寻找复制粘贴代码时使用。

SKILL.md
--- frontmatter
name: quickdup
description: Find and reduce code duplication, clean up redundant code, detect code clones, reduce codebase size, DRY violations, copy-paste detection. Use when the user asks about duplicate code, code cleanup, reducing code size, DRY principles, or finding copy-pasted code.
argument-hint: "[path or extension]"

Prerequisites

Before running quickdup, check if it is installed:

code
which quickdup

If not found, install it:

  • macOS/Linux: curl -sSL https://raw.githubusercontent.com/asynkron/Asynkron.QuickDup/main/install.sh | bash
  • Windows: iwr -useb https://raw.githubusercontent.com/asynkron/Asynkron.QuickDup/main/install.ps1 | iex
  • From source: go install github.com/asynkron/Asynkron.QuickDup/cmd/quickdup@latest

About QuickDup

QuickDup is a fast structural code clone detector (~100k lines in 500ms). It uses indent-delta fingerprinting to find duplicate code patterns. It is designed as a candidate generator — it optimizes for speed and recall, surfacing candidates fast for AI-assisted review.

Results are written to .quickdup/results.json and cached in .quickdup/cache.gob for fast incremental re-runs.

Workflow

  1. Run quickdup to find duplication candidates
  2. Review the results with -select to inspect specific patterns
  3. Classify each pattern — determine which type of duplication it is (see below)
  4. Refactor using the right pattern — not all duplication should be removed the same way
  5. Re-run to verify duplication is reduced

Determine File Extension

Before running, determine the primary language/extension of the project. Look at the files in the target path and use the appropriate -ext flag (e.g. .go, .ts, .cs, .py, .java, .rs).

Common Usage

Scan current project:

code
quickdup -path . -ext .go

Scan with specific extension (adapt to project language):

code
quickdup -path $ARGUMENTS -ext .ts

Show top 20 patterns:

code
quickdup -path . -ext .go -top 20

Inspect specific patterns in detail:

code
quickdup -path . -ext .go -select 0..5

Strict similarity (fewer false positives):

code
quickdup -path . -ext .go -min-similarity 0.9

Require more occurrences:

code
quickdup -path . -ext .go -min 5

Exclude generated files:

code
quickdup -path . -ext .go -exclude "*.pb.go,*_gen.go,*_test.go"

Compare duplication between branches:

code
quickdup -path . -ext .go -compare origin/main..HEAD

Key Flags

FlagDefaultPurpose
-path.Directory to scan
-ext.goFile extension to match
-min2Minimum occurrences to report
-min-size3Minimum pattern size (lines)
-max-size0Max pattern size (0 = unlimited)
-min-score5Minimum score threshold
-min-similarity0.75Token similarity threshold (0.0-1.0)
-top10Show top N patterns
-selectDetailed view (e.g. 0..5)
-excludeExclude file globs (comma-separated)
-no-cachefalseForce full re-parse
-strategynormalized-indentDetection strategy
-compareCompare between commits (base..head)

Detection Strategies

  • normalized-indent (default) — indent deltas + first word per line
  • word-indent — raw indentation + first word
  • word-only — ignores indentation, first words only
  • inlineable — detects small patterns suitable for inline extraction

Suppressing Known Patterns

If a pattern is intentional duplication, suppress it by adding its hash to .quickdup/ignore.json:

json
{
  "description": "Patterns to ignore",
  "ignored": ["56c2f5f9b27ed5a0"]
}

How to Refactor Duplicated Code

QuickDup finds duplication candidates. The next step is knowing how to fix them. Not all duplication is the same — each type has a different refactoring strategy.

Type 1: Structural Duplication with Contextual Variation

Two blocks share the same control flow and structure, but differ in injected behavior (which function is called, which parameters are passed, whether some context like an index exists).

How to recognize it:

  • Same loops, same branching, same method calls in the same order
  • Only the behavior inside the structure differs

How to refactor:

  1. Ignore the differences — mentally replace the differing lines with placeholders. If the code still "reads the same", you have structural duplication.
  2. Identify the invariant structure — same loops, branching, method calls in the same order. That is the structure to extract.
  3. Identify the varying behavior — what methods differ? What parameters differ? What context exists in one version but not the other? These become delegates, lambdas, or strategy objects.
  4. Extract, do not merge — do NOT write if (variant) { ... } else { ... }. Instead, extract the shared structure and pass behavior in.
  5. Preserve meaning at call sites — the call site should still clearly express intent.

Good:

code
IterateAndResolve(array, i => CreateResolve(i), ...)

Bad:

code
IterateAndResolve(array, withIndex: true)

Rule of thumb: If two methods differ only in what they do inside a shared structure, extract the structure. If they differ in structure, keep them separate.

Type 2: Structural Switch Duplication

Repeated switch/pattern match blocks on the same domain structures. Common in AST walkers, serializers, interpreters, and compilers.

How to recognize it:

  • Repeated switch or pattern matching blocks
  • Short, trivial case bodies
  • Each case extracts or forwards structure
  • No real algorithm, just classification

When to leave it alone:

  • Each case is one or two lines
  • The code is stable and unlikely to drift
  • The abstraction would just wrap a switch
  • The switch documents the domain shape — removing it hides meaning

When to refactor:

  • Same switch appears 3+ times
  • Case list starts diverging between copies
  • Case logic grows beyond trivial access

How to refactor:

  • Extract the smallest possible helper
  • Return data, do not hide control flow
  • Use pattern matching, not flags

Good: Statement? TryUnwrapBody(Statement s) Bad: HandleStatement(s, mode)

Rule of thumb: If the switch describes structure, duplication is documentation. If the switch implements behavior, consider extraction.

Type 3: Parameter Bundle Duplication

The same set of context values passed together in multiple places — same parameters, same order, same meaning.

How to recognize it:

  • Same group of 4+ parameters passed together repeatedly
  • Usually forwarded to constructors or methods
  • Reads like a "context snapshot"
  • Adding a new parameter would require editing many call sites

How to refactor:

Extract a value object:

code
new ExecutionContext(thisValue, realmState, isStrict, homeObject, privateScope)

Then pass the single object instead of 5+ individual arguments.

When to leave it: Appears only once, is highly localized, or has extremely short lifetime.

Rule of thumb: If the same parameter list appears 2-3+ times, it wants to become a named type.

Type 4: Argument Unpacking Duplication

Duplicated defensive parsing of callback arguments — same local variables, same guards, same positional decoding.

How to recognize it:

  • Same argument index checks (args.Count >= 1, args[0])
  • Same type unwrapping logic
  • Same local variable names
  • Appears inside lambdas, which amplifies the noise

How to refactor:

Extract a small helper whose only job is to unpack the arguments:

code
UnwrapResolveReject(args, out var resolve, out var reject);

This is purely mechanical code — the intent is obscured by boilerplate, and any bug fix would need to be applied to every copy.

Rule of thumb: If you copy the same argument decoding logic twice, extract it. If the extraction reads like English, you picked the right abstraction.


Guidelines

  • Always determine the correct -ext for the project before running
  • Start with defaults, then tighten -min-similarity if too many false positives
  • Use -select 0..5 to inspect the top candidates before refactoring
  • After identifying duplicates, classify them by type before refactoring
  • Not all duplication should be removed — structural switch duplication is often intentional documentation
  • After refactoring, re-run to confirm duplication is reduced
  • For large projects, quickdup caches results — subsequent runs are near-instant
  • When the user wants to clean up or reduce code size, run quickdup first to identify targets, then refactor the highest-scoring patterns using the appropriate strategy for each type